diff options
Diffstat (limited to 'bindings/xml/libxml_xmlparser.c')
-rw-r--r-- | bindings/xml/libxml_xmlparser.c | 265 |
1 files changed, 183 insertions, 82 deletions
diff --git a/bindings/xml/libxml_xmlparser.c b/bindings/xml/libxml_xmlparser.c index 02b8a34..cd7f8ad 100644 --- a/bindings/xml/libxml_xmlparser.c +++ b/bindings/xml/libxml_xmlparser.c @@ -6,6 +6,7 @@ */ #include <stdbool.h> +#include <stdlib.h> #include <string.h> #include <assert.h> @@ -36,21 +37,21 @@ static void xml_parser_end_element_ns(void *ctx, const xmlChar *localname, static dom_exception xml_parser_link_nodes(dom_xml_parser *parser, struct dom_node *dom, xmlNodePtr xml); -static void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, - xmlNodePtr child); -static void xml_parser_add_element_node(dom_xml_parser *parser, +static dom_exception xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_text_node(dom_xml_parser *parser, +static dom_exception xml_parser_add_element_node(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_cdata_section(dom_xml_parser *parser, +static dom_exception xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_entity_reference(dom_xml_parser *parser, +static dom_exception xml_parser_add_cdata_section(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_entity(dom_xml_parser *parser, +static dom_exception xml_parser_add_entity_reference(dom_xml_parser *parser, + struct dom_node *parent, xmlNodePtr child); +static dom_exception xml_parser_add_entity(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_comment(dom_xml_parser *parser, +static dom_exception xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); -static void xml_parser_add_document_type(dom_xml_parser *parser, +static dom_exception xml_parser_add_document_type(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child); static void xml_parser_internal_subset(void *ctx, const xmlChar *name, @@ -96,6 +97,8 @@ struct dom_xml_parser { dom_msg msg; /**< Informational message function */ void *mctx; /**< Pointer to client data */ + + dom_exception err; /**< Last DOM error, if any */ }; /** @@ -133,7 +136,7 @@ static xmlSAXHandler sax_handler = { ._private = NULL, .startElementNs = xml_parser_start_element_ns, .endElementNs = xml_parser_end_element_ns, - .serror = NULL + .serror = NULL, }; static void *dom_xml_alloc(void *ptr, size_t len, void *pw) @@ -231,6 +234,8 @@ dom_xml_parser *dom_xml_parser_create(const char *enc, const char *int_enc, parser->msg = msg; parser->mctx = mctx; + parser->err = DOM_NO_ERR; + return parser; } @@ -271,6 +276,10 @@ dom_xml_error dom_xml_parser_parse_chunk(dom_xml_parser *parser, return DOM_XML_EXTERNAL_ERR | err; } + if (parser->err != DOM_NO_ERR) { + return DOM_XML_DOM_ERR | parser->err; + } + return DOM_XML_OK; } @@ -293,6 +302,10 @@ dom_xml_error dom_xml_parser_completed(dom_xml_parser *parser) return DOM_XML_EXTERNAL_ERR | err; } + if (parser->err != DOM_NO_ERR) { + return DOM_XML_DOM_ERR | parser->err; + } + return DOM_XML_OK; } @@ -304,15 +317,27 @@ dom_xml_error dom_xml_parser_completed(dom_xml_parser *parser) void xml_parser_start_document(void *ctx) { dom_xml_parser *parser = (dom_xml_parser *) ctx; - dom_exception err; +#if LIBXML_VERSION >= 21200 + const xmlError *xmlerr; +#else + xmlErrorPtr xmlerr; +#endif + + if (parser->err != DOM_NO_ERR) + return; /* Invoke libxml2's default behaviour */ xmlSAX2StartDocument(parser->xml_ctx); + xmlerr = xmlCtxtGetLastError(parser->xml_ctx); + if (xmlerr != NULL && xmlerr->level >= XML_ERR_ERROR) { + return; + } /* Link nodes together */ - err = xml_parser_link_nodes(parser, (struct dom_node *) parser->doc, + parser->err = xml_parser_link_nodes(parser, + (struct dom_node *) parser->doc, (xmlNodePtr) parser->xml_ctx->myDoc); - if (err != DOM_NO_ERR) { + if (parser->err != DOM_NO_ERR) { parser->msg(DOM_MSG_WARNING, parser->mctx, "Not able to link document nodes"); } @@ -328,10 +353,21 @@ void xml_parser_end_document(void *ctx) dom_xml_parser *parser = (dom_xml_parser *) ctx; xmlNodePtr node; xmlNodePtr n; - dom_exception err; +#if LIBXML_VERSION >= 21200 + const xmlError *xmlerr; +#else + xmlErrorPtr xmlerr; +#endif + + if (parser->err != DOM_NO_ERR) + return; /* Invoke libxml2's default behaviour */ xmlSAX2EndDocument(parser->xml_ctx); + xmlerr = xmlCtxtGetLastError(parser->xml_ctx); + if (xmlerr != NULL && xmlerr->level >= XML_ERR_ERROR) { + return; + } /* If there is no document, we can't do anything */ if (parser->doc == NULL) { @@ -344,9 +380,13 @@ void xml_parser_end_document(void *ctx) * children which occur after the last Element node in the list */ /* Get XML node */ - err = dom_node_get_user_data((struct dom_node *) parser->doc, + parser->err = dom_node_get_user_data((struct dom_node *) parser->doc, parser->udkey, (void **) (void *) &node); - if (err != DOM_NO_ERR) { + + /* The return value from dom_node_get_user_data() is always + * DOM_NO_ERR, but the returned "node" will be NULL if no user + * data is found. */ + if (parser->err != DOM_NO_ERR || node == NULL) { parser->msg(DOM_MSG_WARNING, parser->mctx, "Failed finding XML node"); return; @@ -368,8 +408,10 @@ void xml_parser_end_document(void *ctx) /* Now, mirror nodes in the DOM */ for (; n != NULL; n = n->next) { - xml_parser_add_node(parser, + parser->err = xml_parser_add_node(parser, (struct dom_node *) node->_private, n); + if (parser->err != DOM_NO_ERR) + return; } } @@ -397,11 +439,23 @@ void xml_parser_start_element_ns(void *ctx, const xmlChar *localname, { dom_xml_parser *parser = (dom_xml_parser *) ctx; xmlNodePtr parent = parser->xml_ctx->node; +#if LIBXML_VERSION >= 21200 + const xmlError *xmlerr; +#else + xmlErrorPtr xmlerr; +#endif + + if (parser->err != DOM_NO_ERR) + return; /* Invoke libxml2's default behaviour */ xmlSAX2StartElementNs(parser->xml_ctx, localname, prefix, URI, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes); + xmlerr = xmlCtxtGetLastError(parser->xml_ctx); + if (xmlerr != NULL && xmlerr->level >= XML_ERR_ERROR) { + return; + } /* If there is no document, we can't do anything */ if (parser->doc == NULL) { @@ -440,16 +494,18 @@ void xml_parser_start_element_ns(void *ctx, const xmlChar *localname, /* Now, mirror nodes in the DOM */ for (; n != parser->xml_ctx->node; n = n->next) { - xml_parser_add_node(parser, + parser->err = xml_parser_add_node(parser, (struct dom_node *) parent->_private, n); + if (parser->err != DOM_NO_ERR) + return; } } /* Mirror the created node and its attributes in the DOM */ - xml_parser_add_node(parser, (struct dom_node *) parent->_private, + parser->err = xml_parser_add_node(parser, + (struct dom_node *) parent->_private, parser->xml_ctx->node); - } /** @@ -466,9 +522,21 @@ void xml_parser_end_element_ns(void *ctx, const xmlChar *localname, dom_xml_parser *parser = (dom_xml_parser *) ctx; xmlNodePtr node = parser->xml_ctx->node; xmlNodePtr n; +#if LIBXML_VERSION >= 21200 + const xmlError *xmlerr; +#else + xmlErrorPtr xmlerr; +#endif + + if (parser->err != DOM_NO_ERR) + return; /* Invoke libxml2's default behaviour */ xmlSAX2EndElementNs(parser->xml_ctx, localname, prefix, URI); + xmlerr = xmlCtxtGetLastError(parser->xml_ctx); + if (xmlerr != NULL && xmlerr->level >= XML_ERR_ERROR) { + return; + } /* If there is no document, we can't do anything */ if (parser->doc == NULL) { @@ -503,8 +571,10 @@ void xml_parser_end_element_ns(void *ctx, const xmlChar *localname, /* Now, mirror nodes in the DOM */ for (; n != NULL; n = n->next) { - xml_parser_add_node(parser, + parser->err = xml_parser_add_node(parser, (struct dom_node *) node->_private, n); + if (parser->err != DOM_NO_ERR) + return; } } @@ -543,9 +613,10 @@ dom_exception xml_parser_link_nodes(dom_xml_parser *parser, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, - xmlNodePtr child) +dom_exception xml_parser_add_node(dom_xml_parser *parser, + struct dom_node *parent, xmlNodePtr child) { static const char *node_types[] = { "THIS_IS_NOT_A_NODE", @@ -574,31 +645,26 @@ void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, switch (child->type) { case XML_ELEMENT_NODE: - xml_parser_add_element_node(parser, parent, child); - break; + return xml_parser_add_element_node(parser, parent, child); case XML_TEXT_NODE: - xml_parser_add_text_node(parser, parent, child); - break; + return xml_parser_add_text_node(parser, parent, child); case XML_CDATA_SECTION_NODE: - xml_parser_add_cdata_section(parser, parent, child); - break; + return xml_parser_add_cdata_section(parser, parent, child); case XML_ENTITY_REF_NODE: - xml_parser_add_entity_reference(parser, parent, child); - break; + return xml_parser_add_entity_reference(parser, parent, child); case XML_COMMENT_NODE: - xml_parser_add_comment(parser, parent, child); - break; + return xml_parser_add_comment(parser, parent, child); case XML_DTD_NODE: - xml_parser_add_document_type(parser, parent, child); - break; - case XML_ENTITY_DECL: - xml_parser_add_entity(parser, parent, child); - break; + return xml_parser_add_document_type(parser, parent, child); + case XML_ENTITY_DECL: + return xml_parser_add_entity(parser, parent, child); default: parser->msg(DOM_MSG_NOTICE, parser->mctx, "Unsupported node type: %s", node_types[child->type]); } + + return DOM_NO_ERR; } /** @@ -607,8 +673,9 @@ void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_element_node(dom_xml_parser *parser, +dom_exception xml_parser_add_element_node(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child) { struct dom_element *el, *ins_el = NULL; @@ -626,7 +693,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for tag name"); - return; + return err; } /* Create element node */ @@ -637,7 +704,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed creating element '%s'", child->name); - return; + return err; } /* No longer need tag name */ @@ -660,7 +727,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for namespace"); - return; + return err; } /* QName is "prefix:localname", @@ -680,7 +747,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, dom_string_unref(namespace); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for qname"); - return; + return err; } /* Create element node */ @@ -692,7 +759,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed creating element '%s'", qnamebuf); - return; + return err; } /* No longer need namespace / qname */ @@ -752,7 +819,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for namespace"); - return; + goto cleanup; } /* QName is "prefix:localname", @@ -772,7 +839,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, dom_string_unref(namespace); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for qname"); - return; + goto cleanup; } /* Create attribute */ @@ -784,7 +851,7 @@ void xml_parser_add_element_node(dom_xml_parser *parser, parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed creating attribute \ '%s'", qnamebuf); - return; + goto cleanup; } /* No longer need namespace / qname */ @@ -794,8 +861,12 @@ void xml_parser_add_element_node(dom_xml_parser *parser, /* Clone subtree (attribute value) */ for (c = a->children; c != NULL; c = c->next) { - xml_parser_add_node(parser, + err = xml_parser_add_node(parser, (struct dom_node *) attr, c); + if (err != DOM_NO_ERR) { + dom_node_unref((struct dom_node *) attr); + goto cleanup; + } } /* Link nodes together */ @@ -861,14 +932,14 @@ void xml_parser_add_element_node(dom_xml_parser *parser, /* No longer interested in element node */ dom_node_unref((struct dom_node *) el); - return; + return DOM_NO_ERR; cleanup: /* No longer want node (any attributes attached to it * will be cleaned up with it) */ dom_node_unref((struct dom_node *) el); - return; + return err; } /** @@ -877,9 +948,10 @@ cleanup: * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, - xmlNodePtr child) +dom_exception xml_parser_add_text_node(dom_xml_parser *parser, + struct dom_node *parent, xmlNodePtr child) { struct dom_text *text, *ins_text = NULL; dom_string *data; @@ -891,7 +963,7 @@ void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for text node contents "); - return; + return err; } /* Create text node */ @@ -900,7 +972,7 @@ void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, dom_string_unref(data); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for text node"); - return; + return err; } /* No longer need data */ @@ -913,7 +985,7 @@ void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, dom_node_unref((struct dom_node *) text); parser->msg(DOM_MSG_ERROR, parser->mctx, "Failed attaching text node"); - return; + return err; } /* We're not interested in the inserted text node */ @@ -925,11 +997,13 @@ void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, child); if (err != DOM_NO_ERR) { dom_node_unref((struct dom_node *) text); - return; + return err; } /* No longer interested in text node */ dom_node_unref((struct dom_node *) text); + + return DOM_NO_ERR; } /** @@ -938,8 +1012,9 @@ void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_cdata_section(dom_xml_parser *parser, +dom_exception xml_parser_add_cdata_section(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child) { struct dom_cdata_section *cdata, *ins_cdata = NULL; @@ -952,7 +1027,7 @@ void xml_parser_add_cdata_section(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for cdata section contents"); - return; + return err; } /* Create cdata section */ @@ -961,7 +1036,7 @@ void xml_parser_add_cdata_section(dom_xml_parser *parser, dom_string_unref(data); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for cdata section"); - return; + return err; } /* No longer need data */ @@ -974,7 +1049,7 @@ void xml_parser_add_cdata_section(dom_xml_parser *parser, dom_node_unref((struct dom_node *) cdata); parser->msg(DOM_MSG_ERROR, parser->mctx, "Failed attaching cdata section"); - return; + return err; } /* We're not interested in the inserted cdata section */ @@ -986,11 +1061,13 @@ void xml_parser_add_cdata_section(dom_xml_parser *parser, child); if (err != DOM_NO_ERR) { dom_node_unref((struct dom_node *) cdata); - return; + return err; } /* No longer interested in cdata section */ dom_node_unref((struct dom_node *) cdata); + + return DOM_NO_ERR; } /** @@ -999,8 +1076,9 @@ void xml_parser_add_cdata_section(dom_xml_parser *parser, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_entity_reference(dom_xml_parser *parser, +dom_exception xml_parser_add_entity_reference(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child) { struct dom_entity_reference *entity, *ins_entity = NULL; @@ -1014,7 +1092,7 @@ void xml_parser_add_entity_reference(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for entity reference name"); - return; + return err; } /* Create text node */ @@ -1024,7 +1102,7 @@ void xml_parser_add_entity_reference(dom_xml_parser *parser, dom_string_unref(name); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for entity reference"); - return; + return err; } /* No longer need name */ @@ -1032,7 +1110,10 @@ void xml_parser_add_entity_reference(dom_xml_parser *parser, /* Mirror subtree (reference value) */ for (c = child->children; c != NULL; c = c->next) { - xml_parser_add_node(parser, (struct dom_node *) entity, c); + err = xml_parser_add_node(parser, + (struct dom_node *) entity, c); + if (err != DOM_NO_ERR) + return err; } /* Append entity reference to parent */ @@ -1042,7 +1123,7 @@ void xml_parser_add_entity_reference(dom_xml_parser *parser, dom_node_unref((struct dom_node *) entity); parser->msg(DOM_MSG_ERROR, parser->mctx, "Failed attaching entity reference"); - return; + return err; } /* We're not interested in the inserted entity reference */ @@ -1054,19 +1135,33 @@ void xml_parser_add_entity_reference(dom_xml_parser *parser, child); if (err != DOM_NO_ERR) { dom_node_unref((struct dom_node *) entity); - return; + return err; } /* No longer interested in entity reference */ dom_node_unref((struct dom_node *) entity); + + return DOM_NO_ERR; } -static void xml_parser_add_entity(dom_xml_parser *parser, - struct dom_node *parent, xmlNodePtr child) +/** + * Add an entity to the DOM + * + * \param parser The parser context + * \param parent The parent DOM node + * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise + */ +dom_exception xml_parser_add_entity(dom_xml_parser *parser, + struct dom_node *parent, xmlNodePtr child) { - UNUSED(parser); - UNUSED(parent); - UNUSED(child); + UNUSED(parser); + UNUSED(parent); + UNUSED(child); + + /** \todo implement */ + + return DOM_NO_ERR; } /** @@ -1075,9 +1170,10 @@ static void xml_parser_add_entity(dom_xml_parser *parser, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, - xmlNodePtr child) +dom_exception xml_parser_add_comment(dom_xml_parser *parser, + struct dom_node *parent, xmlNodePtr child) { struct dom_comment *comment, *ins_comment = NULL; dom_string *data; @@ -1089,7 +1185,7 @@ void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for comment data"); - return; + return err; } /* Create comment */ @@ -1098,7 +1194,7 @@ void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, dom_string_unref(data); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "No memory for comment node"); - return; + return err; } /* No longer need data */ @@ -1111,7 +1207,7 @@ void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, dom_node_unref((struct dom_node *) comment); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed attaching comment node"); - return; + return err; } /* We're not interested in the inserted comment */ @@ -1123,11 +1219,13 @@ void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, child); if (err != DOM_NO_ERR) { dom_node_unref((struct dom_node *) comment); - return; + return err; } /* No longer interested in comment */ dom_node_unref((struct dom_node *) comment); + + return DOM_NO_ERR; } /** @@ -1136,8 +1234,9 @@ void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, * \param parser The parser context * \param parent The parent DOM node * \param child The xmlNode to mirror in the DOM as a child of parent + * \return DOM_NO_ERR on success, appropriate error otherwise */ -void xml_parser_add_document_type(dom_xml_parser *parser, +dom_exception xml_parser_add_document_type(dom_xml_parser *parser, struct dom_node *parent, xmlNodePtr child) { xmlDtdPtr dtd = (xmlDtdPtr) child; @@ -1163,7 +1262,7 @@ void xml_parser_add_document_type(dom_xml_parser *parser, if (err != DOM_NO_ERR) { parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed to create document type"); - return; + return err; } /* Add doctype to document */ @@ -1173,7 +1272,7 @@ void xml_parser_add_document_type(dom_xml_parser *parser, dom_node_unref((struct dom_node *) doctype); parser->msg(DOM_MSG_CRITICAL, parser->mctx, "Failed attaching doctype"); - return; + return err; } /* Not interested in inserted node */ @@ -1185,11 +1284,13 @@ void xml_parser_add_document_type(dom_xml_parser *parser, child); if (err != DOM_NO_ERR) { dom_node_unref((struct dom_node *) doctype); - return; + return err; } /* No longer interested in doctype */ dom_node_unref((struct dom_node *) doctype); + + return DOM_NO_ERR; } /* ------------------------------------------------------------------------*/ |