diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2007-04-22 00:17:55 +0100 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2007-04-22 00:17:55 +0100 |
commit | c0310456d00840947ff2f93687b1152d71311159 (patch) | |
tree | 2f687e0211ddf494b7ed9fb579ec55ed96727335 | |
parent | 497d74fe5b6a68b904a6944a9c60dd3c631654a6 (diff) | |
parent | 559008cadf0bc3457696e145b0abe764132fe92d (diff) | |
download | xine-lib-c0310456d00840947ff2f93687b1152d71311159.tar.gz xine-lib-c0310456d00840947ff2f93687b1152d71311159.tar.bz2 |
Merge relaxed XML parsing & adapt it to the enumerations.
-rw-r--r-- | src/xine-utils/xmlparser.c | 70 | ||||
-rw-r--r-- | src/xine-utils/xmlparser.h | 1 |
2 files changed, 60 insertions, 11 deletions
diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c index c8723a12e..93217637d 100644 --- a/src/xine-utils/xmlparser.c +++ b/src/xine-utils/xmlparser.c @@ -162,6 +162,7 @@ typedef enum { STATE_TAG_TERM, STATE_ATTRIBUTE_EQUALS, STATE_STRING, + STATE_TAG_TERM_IGNORE, /* <?foo ...?> */ STATE_Q_NODE, STATE_Q_ATTRIBUTE, @@ -176,7 +177,8 @@ typedef enum { #define Q_STATE(CURRENT,NEW) (STATE_##NEW + state - STATE_##CURRENT) -static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec) { +static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_names[], int rec, int relaxed) +{ char tok[TOKEN_SIZE]; char property_name[TOKEN_SIZE]; char node_name[TOKEN_SIZE]; @@ -184,6 +186,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r int res = 0; int parse_res; int bypass_get_token = 0; + int retval = 0; /* used when state==4; non-0 if there are missing </...> */ xml_node_t *subtree = NULL; xml_node_t *current_subtree = NULL; xml_property_t *current_property = NULL; @@ -203,7 +206,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r /* do nothing */ break; case (T_EOF): - return 0; /* normal end */ + return retval; /* normal end */ break; case (T_M_START_1): state = STATE_NODE; @@ -279,8 +282,9 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r /* set node propertys */ subtree->props = properties; lprintf("info: rec %d new subtree %s\n", rec, node_name); - parse_res = xml_parser_get_node(subtree, node_name, rec + 1); - if (parse_res != 0) { + root_names[rec + 1] = node_name; + parse_res = xml_parser_get_node_internal(subtree, root_names, rec + 1, relaxed); + if (parse_res == -1 || parse_res > 0) { return parse_res; } if (current_subtree == NULL) { @@ -290,6 +294,10 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r current_subtree->next = subtree; current_subtree = subtree; } + if (parse_res < -1) { + /* badly-formed XML (missing close tag) */ + return parse_res + 1 + (parse_res == -2); + } state = STATE_IDLE; break; case (T_M_STOP_2): @@ -356,10 +364,26 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } - if (strcmp(tok, root_name) == 0) { + if (strcmp(tok, root_names[rec]) == 0) { state = STATE_TAG_TERM; - } else { - lprintf("error: xml struct, tok=%s, waited_tok=%s\n", tok, root_name); + } else if (relaxed) { + int r = rec; + while (--r >= 0) + if (strcmp(tok, root_names[r]) == 0) { + lprintf("warning: wanted %s, got %s - assuming missing close tags\n", root_names[rec], tok); + retval = r - rec - 1; /* -1 - (no. of implied close tags) */ + state = STATE_TAG_TERM; + break; + } + /* relaxed parsing, ignoring extra close tag (but we don't handle out-of-order) */ + if (r < 0) { + lprintf("warning: extra close tag %s - ignoring\n", tok); + state = STATE_TAG_TERM_IGNORE; + } + } + else + { + lprintf("error: xml struct, tok=%s, waited_tok=%s\n", tok, root_names[rec]); return -1; } break; @@ -374,7 +398,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r case STATE_TAG_TERM: switch (res) { case (T_M_STOP_1): - return 0; + return retval; break; default: lprintf("error: unexpected token \"%s\", state %d\n", tok, state); @@ -505,6 +529,19 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r } break; + /* > expected (following unmatched "</...") */ + case STATE_TAG_TERM_IGNORE: + switch (res) { + case (T_M_STOP_1): + state = STATE_IDLE; + break; + default: + lprintf("error: unexpected token \"%s\", state %d\n", tok, state); + return -1; + break; + } + break; + default: lprintf("error: unknown parser state, state=%d\n", state); @@ -521,12 +558,19 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r } } -int xml_parser_build_tree(xml_node_t **root_node) { - xml_node_t *tmp_node, *pri_node, *q_node = NULL; +static int xml_parser_get_node (xml_node_t *current_node, int relaxed) +{ + char *root_names[MAX_RECURSION + 1]; + root_names[0] = ""; + return xml_parser_get_node_internal (current_node, root_names, 0, relaxed); +} + +int xml_parser_build_tree_relaxed(xml_node_t **root_node, int relaxed) { + xml_node_t *tmp_node, *pri_node, *q_node; int res; tmp_node = new_xml_node(); - res = xml_parser_get_node(tmp_node, "", 0); + res = xml_parser_get_node(tmp_node, relaxed); /* find first non-<?...?> node */; for (pri_node = tmp_node->child; @@ -551,6 +595,10 @@ int xml_parser_build_tree(xml_node_t **root_node) { return res; } +int xml_parser_build_tree(xml_node_t **root_node) { + return xml_parser_build_tree_relaxed (root_node, 0); +} + const char *xml_parser_get_property (const xml_node_t *node, const char *name) { xml_property_t *prop; diff --git a/src/xine-utils/xmlparser.h b/src/xine-utils/xmlparser.h index f202ca28d..8d4915abf 100644 --- a/src/xine-utils/xmlparser.h +++ b/src/xine-utils/xmlparser.h @@ -57,6 +57,7 @@ typedef struct xml_node_s { void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED; int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED; +int xml_parser_build_tree_relaxed(xml_node_t **root_node, int relaxed) XINE_PROTECTED; void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED; |