Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
  6.  */
  7.  
  8. #include <stdbool.h>
  9. #include <string.h>
  10. #include <assert.h>
  11.  
  12. #include <libxml/parser.h>
  13. #include <libxml/SAX2.h>
  14. #include <libxml/xmlerror.h>
  15.  
  16. #include <dom/dom.h>
  17.  
  18. #include <libwapcaplet/libwapcaplet.h>
  19.  
  20. #include "xmlerror.h"
  21. #include "xmlparser.h"
  22. #include "utils.h"
  23.  
  24. #include "core/document.h"
  25.  
  26. static void xml_parser_start_document(void *ctx);
  27. static void xml_parser_end_document(void *ctx);
  28. static void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
  29.                 const xmlChar *prefix, const xmlChar *URI,
  30.                 int nb_namespaces, const xmlChar **namespaces,
  31.                 int nb_attributes, int nb_defaulted,
  32.                 const xmlChar **attributes);
  33. static void xml_parser_end_element_ns(void *ctx, const xmlChar *localname,
  34.                 const xmlChar *prefix, const xmlChar *URI);
  35.  
  36. static dom_exception xml_parser_link_nodes(dom_xml_parser *parser,
  37.                 struct dom_node *dom, xmlNodePtr xml);
  38.  
  39. static void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent,
  40.                 xmlNodePtr child);
  41. static void xml_parser_add_element_node(dom_xml_parser *parser,
  42.                 struct dom_node *parent, xmlNodePtr child);
  43. static void xml_parser_add_text_node(dom_xml_parser *parser,
  44.                 struct dom_node *parent, xmlNodePtr child);
  45. static void xml_parser_add_cdata_section(dom_xml_parser *parser,
  46.                 struct dom_node *parent, xmlNodePtr child);
  47. static void xml_parser_add_entity_reference(dom_xml_parser *parser,
  48.                 struct dom_node *parent, xmlNodePtr child);
  49. static void xml_parser_add_entity(dom_xml_parser *parser,
  50.         struct dom_node *parent, xmlNodePtr child);
  51. static void xml_parser_add_comment(dom_xml_parser *parser,
  52.                 struct dom_node *parent, xmlNodePtr child);
  53. static void xml_parser_add_document_type(dom_xml_parser *parser,
  54.                 struct dom_node *parent, xmlNodePtr child);
  55.  
  56. static void xml_parser_internal_subset(void *ctx, const xmlChar *name,
  57.                 const xmlChar *ExternalID, const xmlChar *SystemID);
  58. static int xml_parser_is_standalone(void *ctx);
  59. static int xml_parser_has_internal_subset(void *ctx);
  60. static int xml_parser_has_external_subset(void *ctx);
  61. static xmlParserInputPtr xml_parser_resolve_entity(void *ctx,
  62.                 const xmlChar *publicId, const xmlChar *systemId);
  63. static xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name);
  64. static void xml_parser_entity_decl(void *ctx, const xmlChar *name,
  65.                 int type, const xmlChar *publicId, const xmlChar *systemId,
  66.                 xmlChar *content);
  67. static void xml_parser_notation_decl(void *ctx, const xmlChar *name,
  68.                 const xmlChar *publicId, const xmlChar *systemId);
  69. static void xml_parser_attribute_decl(void *ctx, const xmlChar *elem,
  70.                 const xmlChar *fullname, int type, int def,
  71.                 const xmlChar *defaultValue, xmlEnumerationPtr tree);
  72. static void xml_parser_element_decl(void *ctx, const xmlChar *name,
  73.                 int type, xmlElementContentPtr content);
  74. static void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name,
  75.                 const xmlChar *publicId, const xmlChar *systemId,
  76.                 const xmlChar *notationName);
  77. static void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc);
  78. static void xml_parser_reference(void *ctx, const xmlChar *name);
  79. static void xml_parser_characters(void *ctx, const xmlChar *ch, int len);
  80. static void xml_parser_comment(void *ctx, const xmlChar *value);
  81. static xmlEntityPtr xml_parser_get_parameter_entity(void *ctx,
  82.                 const xmlChar *name);
  83. static void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len);
  84. static void xml_parser_external_subset(void *ctx, const xmlChar *name,
  85.                 const xmlChar *ExternalID, const xmlChar *SystemID);
  86.  
  87. /**
  88.  * libdom XML parser object
  89.  */
  90. struct dom_xml_parser {
  91.         xmlParserCtxtPtr xml_ctx;       /**< libxml parser context */
  92.  
  93.         struct dom_document *doc;       /**< DOM Document we're building */
  94.  
  95.         dom_string *udkey;      /**< Key for DOM node user data */
  96.  
  97.         dom_msg msg;            /**< Informational message function */
  98.         void *mctx;             /**< Pointer to client data */
  99. };
  100.  
  101. /**
  102.  * SAX callback dispatch table
  103.  */
  104. static xmlSAXHandler sax_handler = {
  105.         .internalSubset         = xml_parser_internal_subset,
  106.         .isStandalone           = xml_parser_is_standalone,
  107.         .hasInternalSubset      = xml_parser_has_internal_subset,
  108.         .hasExternalSubset      = xml_parser_has_external_subset,
  109.         .resolveEntity          = xml_parser_resolve_entity,
  110.         .getEntity              = xml_parser_get_entity,
  111.         .entityDecl             = xml_parser_entity_decl,
  112.         .notationDecl           = xml_parser_notation_decl,
  113.         .attributeDecl          = xml_parser_attribute_decl,
  114.         .elementDecl            = xml_parser_element_decl,
  115.         .unparsedEntityDecl     = xml_parser_unparsed_entity_decl,
  116.         .setDocumentLocator     = xml_parser_set_document_locator,
  117.         .startDocument          = xml_parser_start_document,
  118.         .endDocument            = xml_parser_end_document,
  119.         .startElement           = NULL,
  120.         .endElement             = NULL,
  121.         .reference              = xml_parser_reference,
  122.         .characters             = xml_parser_characters,
  123.         .ignorableWhitespace    = xml_parser_characters,
  124.         .processingInstruction  = NULL,
  125.         .comment                = xml_parser_comment,
  126.         .warning                = NULL,
  127.         .error                  = NULL,
  128.         .fatalError             = NULL,
  129.         .getParameterEntity     = xml_parser_get_parameter_entity,
  130.         .cdataBlock             = xml_parser_cdata_block,
  131.         .externalSubset         = xml_parser_external_subset,
  132.         .initialized            = XML_SAX2_MAGIC,
  133.         ._private               = NULL,
  134.         .startElementNs         = xml_parser_start_element_ns,
  135.         .endElementNs           = xml_parser_end_element_ns,
  136.         .serror                 = NULL
  137. };
  138.  
  139. static void *dom_xml_alloc(void *ptr, size_t len, void *pw)
  140. {
  141.         UNUSED(pw);
  142.  
  143.         if (ptr == NULL)
  144.                 return len > 0 ? malloc(len) : NULL;
  145.  
  146.         if (len == 0) {
  147.                 free(ptr);
  148.                 return NULL;
  149.         }
  150.  
  151.         return realloc(ptr, len);
  152. }
  153.  
  154. /**
  155.  * Create an XML parser instance
  156.  *
  157.  * \param enc      Source charset, or NULL
  158.  * \param int_enc  Desired charset of document buffer (UTF-8 or UTF-16)
  159.  * \param msg      Informational message function
  160.  * \param mctx     Pointer to client-specific private data
  161.  * \return Pointer to instance, or NULL on memory exhaustion
  162.  *
  163.  * Neither ::enc nor ::int_enc are used here.
  164.  * libxml only supports a UTF-8 document buffer and forcibly setting the
  165.  * parser encoding is not yet implemented
  166.  */
  167. dom_xml_parser *dom_xml_parser_create(const char *enc, const char *int_enc,
  168.                 dom_msg msg, void *mctx, dom_document **document)
  169. {
  170.         dom_xml_parser *parser;
  171.         dom_exception err;
  172.         int ret;
  173.  
  174.         UNUSED(enc);
  175.         UNUSED(int_enc);
  176.  
  177.         parser = dom_xml_alloc(NULL, sizeof(dom_xml_parser), NULL);
  178.         if (parser == NULL) {
  179.                 msg(DOM_MSG_CRITICAL, mctx, "No memory for parser");
  180.                 return NULL;
  181.         }
  182.  
  183.         parser->xml_ctx =
  184.                 xmlCreatePushParserCtxt(&sax_handler, parser, "", 0, NULL);
  185.         if (parser->xml_ctx == NULL) {
  186.                 dom_xml_alloc(parser, 0, NULL);
  187.                 msg(DOM_MSG_CRITICAL, mctx, "Failed to create XML parser");
  188.                 return NULL;
  189.         }
  190.  
  191.         /* Set options of parsing context */
  192.         ret = xmlCtxtUseOptions(parser->xml_ctx, XML_PARSE_DTDATTR |
  193.                         XML_PARSE_DTDLOAD);
  194.         if (ret != 0) {
  195.                 xmlFreeParserCtxt(parser->xml_ctx);
  196.                 dom_xml_alloc(parser, 0, NULL);
  197.                 msg(DOM_MSG_CRITICAL, mctx, "Failed setting parser options");
  198.                 return NULL;
  199.         }
  200.  
  201.         /* Create key for user data registration */
  202.         err = dom_string_create((const uint8_t *) "__xmlnode",
  203.                         SLEN("__xmlnode"), &parser->udkey);
  204.         if (err != DOM_NO_ERR) {
  205.                 xmlFreeParserCtxt(parser->xml_ctx);
  206.                 dom_xml_alloc(parser, 0, NULL);
  207.                 msg(DOM_MSG_CRITICAL, mctx, "No memory for userdata key");
  208.                 return NULL;
  209.         }
  210.  
  211.         err = dom_implementation_create_document(
  212.                         DOM_IMPLEMENTATION_XML,
  213.                         /* namespace */ NULL,
  214.                         /* qname */ NULL,
  215.                         /* doctype */ NULL,
  216.                         NULL,
  217.                         NULL,
  218.                         document);
  219.  
  220.         if (err != DOM_NO_ERR) {
  221.                 xmlFreeParserCtxt(parser->xml_ctx);
  222.                 dom_string_unref(parser->udkey);
  223.                 dom_xml_alloc(parser, 0, NULL);
  224.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  225.                                 "Failed creating document");
  226.                 return NULL;
  227.         }
  228.  
  229.         parser->doc = (dom_document *) dom_node_ref(*document);
  230.  
  231.         parser->msg = msg;
  232.         parser->mctx = mctx;
  233.  
  234.         return parser;
  235. }
  236.  
  237. /**
  238.  * Destroy an XML parser instance
  239.  *
  240.  * \param parser  The parser instance to destroy
  241.  */
  242. void dom_xml_parser_destroy(dom_xml_parser *parser)
  243. {
  244.         dom_string_unref(parser->udkey);
  245.         dom_node_unref(parser->doc);
  246.  
  247.         xmlFreeDoc(parser->xml_ctx->myDoc);
  248.        
  249.         xmlFreeParserCtxt(parser->xml_ctx);
  250.  
  251.         dom_xml_alloc(parser, 0, NULL);
  252. }
  253.  
  254. /**
  255.  * Parse a chunk of data
  256.  *
  257.  * \param parser  The XML parser instance to use for parsing
  258.  * \param data    Pointer to data chunk
  259.  * \param len     Byte length of data chunk
  260.  * \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <libxml error> on failure
  261.  */
  262. dom_xml_error dom_xml_parser_parse_chunk(dom_xml_parser *parser,
  263.                 uint8_t *data, size_t len)
  264. {
  265.         xmlParserErrors err;
  266.  
  267.         err = xmlParseChunk(parser->xml_ctx, (char *) data, len, 0);
  268.         if (err != XML_ERR_OK) {
  269.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  270.                                 "xmlParseChunk failed: %d", err);
  271.                 return DOM_XML_EXTERNAL_ERR | err;
  272.         }
  273.  
  274.         return DOM_XML_OK;
  275. }
  276.  
  277. /**
  278.  * Notify parser that datastream is empty
  279.  *
  280.  * \param parser  The XML parser instance to notify
  281.  * \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <libxml error> on failure
  282.  *
  283.  * This will force any remaining data through the parser
  284.  */
  285. dom_xml_error dom_xml_parser_completed(dom_xml_parser *parser)
  286. {
  287.         xmlParserErrors err;
  288.  
  289.         err = xmlParseChunk(parser->xml_ctx, "", 0, 1);
  290.         if (err != XML_ERR_OK) {
  291.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  292.                                 "xmlParseChunk failed: %d", err);
  293.                 return DOM_XML_EXTERNAL_ERR | err;
  294.         }
  295.  
  296.         return DOM_XML_OK;
  297. }
  298.  
  299. /**
  300.  * Handle a document start SAX event
  301.  *
  302.  * \param ctx  The callback context
  303.  */
  304. void xml_parser_start_document(void *ctx)
  305. {
  306.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  307.         dom_exception err;
  308.  
  309.         /* Invoke libxml2's default behaviour */
  310.         xmlSAX2StartDocument(parser->xml_ctx);
  311.  
  312.         /* Link nodes together */
  313.         err = xml_parser_link_nodes(parser, (struct dom_node *) parser->doc,
  314.                         (xmlNodePtr) parser->xml_ctx->myDoc);
  315.         if (err != DOM_NO_ERR) {
  316.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  317.                                 "Not able to link document nodes");
  318.         }
  319. }
  320.  
  321. /**
  322.  * Handle a document end SAX event
  323.  *
  324.  * \param ctx  The callback context
  325.  */
  326. void xml_parser_end_document(void *ctx)
  327. {
  328.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  329.         xmlNodePtr node;
  330.         xmlNodePtr n;
  331.         dom_exception err;
  332.  
  333.         /* Invoke libxml2's default behaviour */
  334.         xmlSAX2EndDocument(parser->xml_ctx);
  335.  
  336.         /* If there is no document, we can't do anything */
  337.         if (parser->doc == NULL) {
  338.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  339.                                 "No document in end_document");
  340.                 return;
  341.         }
  342.  
  343.         /* We need to mirror any child nodes at the end of the list of
  344.          * children which occur after the last Element node in the list */
  345.  
  346.         /* Get XML node */
  347.         err = dom_node_get_user_data((struct dom_node *) parser->doc,
  348.                         parser->udkey, (void **) (void *) &node);
  349.         if (err != DOM_NO_ERR) {
  350.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  351.                                 "Failed finding XML node");
  352.                 return;
  353.         }
  354.  
  355.         /* Find last Element node, if any */
  356.         for (n = node->last; n != NULL; n = n->prev) {
  357.                 if (n->type == XML_ELEMENT_NODE)
  358.                         break;
  359.         }
  360.  
  361.         if (n == NULL) {
  362.                 /* No Element node found; entire list needs mirroring */
  363.                 n = node->children;
  364.         } else {
  365.                 /* Found last Element; skip over it */
  366.                 n = n->next;
  367.         }
  368.  
  369.         /* Now, mirror nodes in the DOM */
  370.         for (; n != NULL; n = n->next) {
  371.                 xml_parser_add_node(parser,
  372.                                 (struct dom_node *) node->_private, n);
  373.         }
  374. }
  375.  
  376. /**
  377.  * Handle an element open SAX event
  378.  *
  379.  * \param ctx            The callback context
  380.  * \param localname      The local name of the element
  381.  * \param prefix         The element namespace prefix
  382.  * \param URI            The element namespace URI
  383.  * \param nb_namespaces  The number of namespace definitions
  384.  * \param namespaces     Array of nb_namespaces prefix/URI pairs
  385.  * \param nb_attributes  The total number of attributes
  386.  * \param nb_defaulted   The number of defaulted attributes
  387.  * \param attributes     Array of nb_attributes attribute values
  388.  *
  389.  * The number of non-defaulted attributes is ::nb_attributes - ::nb_defaulted
  390.  * The defaulted attributes are at the end of the array ::attributes.
  391.  */
  392. void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
  393.                 const xmlChar *prefix, const xmlChar *URI,
  394.                 int nb_namespaces, const xmlChar **namespaces,
  395.                 int nb_attributes, int nb_defaulted,
  396.                 const xmlChar **attributes)
  397. {
  398.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  399.         xmlNodePtr parent = parser->xml_ctx->node;
  400.  
  401.         /* Invoke libxml2's default behaviour */
  402.         xmlSAX2StartElementNs(parser->xml_ctx, localname, prefix, URI,
  403.                         nb_namespaces, namespaces, nb_attributes,
  404.                         nb_defaulted, attributes);
  405.  
  406.         /* If there is no document, we can't do anything */
  407.         if (parser->doc == NULL) {
  408.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  409.                                 "No document in start_element_ns");
  410.                 return;
  411.         }
  412.  
  413.         if (parent == NULL) {
  414.                 /* No parent; use document */
  415.                 parent = (xmlNodePtr) parser->xml_ctx->myDoc;
  416.         }
  417.  
  418.         if (parent->type == XML_DOCUMENT_NODE ||
  419.                         parent->type == XML_ELEMENT_NODE) {
  420.                 /* Mirror in the DOM all children of the parent node
  421.                  * between the previous Element child (or the start,
  422.                  * whichever is encountered first) and the Element
  423.                  * just created */
  424.                 xmlNodePtr n;
  425.  
  426.                 /* Find previous element node, if any */
  427.                 for (n = parser->xml_ctx->node->prev; n != NULL;
  428.                                 n = n->prev) {
  429.                         if (n->type == XML_ELEMENT_NODE)
  430.                                 break;
  431.                 }
  432.  
  433.                 if (n == NULL) {
  434.                         /* No previous Element; use parent's children */
  435.                         n = parent->children;
  436.                 } else {
  437.                         /* Previous Element; skip over it */
  438.                         n = n->next;
  439.                 }
  440.  
  441.                 /* Now, mirror nodes in the DOM */
  442.                 for (; n != parser->xml_ctx->node; n = n->next) {
  443.                         xml_parser_add_node(parser,
  444.                                         (struct dom_node *) parent->_private,
  445.                                         n);
  446.                 }
  447.         }
  448.  
  449.         /* Mirror the created node and its attributes in the DOM */
  450.         xml_parser_add_node(parser, (struct dom_node *) parent->_private,
  451.                         parser->xml_ctx->node);
  452.  
  453. }
  454.  
  455. /**
  456.  * Handle an element close SAX event
  457.  *
  458.  * \param ctx        The callback context
  459.  * \param localname  The local name of the element
  460.  * \param prefix     The element namespace prefix
  461.  * \param URI        The element namespace URI
  462.  */
  463. void xml_parser_end_element_ns(void *ctx, const xmlChar *localname,
  464.                 const xmlChar *prefix, const xmlChar *URI)
  465. {
  466.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  467.         xmlNodePtr node = parser->xml_ctx->node;
  468.         xmlNodePtr n;
  469.  
  470.         /* Invoke libxml2's default behaviour */
  471.         xmlSAX2EndElementNs(parser->xml_ctx, localname, prefix, URI);
  472.  
  473.         /* If there is no document, we can't do anything */
  474.         if (parser->doc == NULL) {
  475.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  476.                                 "No document in end_element_ns");
  477.                 return;
  478.         }
  479.  
  480.         /* If node wasn't linked, we can't do anything */
  481.         if (node->_private == NULL) {
  482.                 parser->msg(DOM_MSG_WARNING, parser->mctx,
  483.                                 "Node '%s' not linked", node->name);
  484.                 return;
  485.         }
  486.  
  487.         /* We need to mirror any child nodes at the end of the list of
  488.          * children which occur after the last Element node in the list */
  489.  
  490.         /* Find last Element node, if any */
  491.         for (n = node->last; n != NULL; n = n->prev) {
  492.                 if (n->type == XML_ELEMENT_NODE)
  493.                         break;
  494.         }
  495.  
  496.         if (n == NULL) {
  497.                 /* No Element node found; entire list needs mirroring */
  498.                 n = node->children;
  499.         } else {
  500.                 /* Found last Element; skip over it */
  501.                 n = n->next;
  502.         }
  503.  
  504.         /* Now, mirror nodes in the DOM */
  505.         for (; n != NULL; n = n->next) {
  506.                 xml_parser_add_node(parser,
  507.                                 (struct dom_node *) node->_private, n);
  508.         }
  509. }
  510.  
  511. /**
  512.  * Link a DOM and XML node together
  513.  *
  514.  * \param parser  The parser context
  515.  * \param dom     The DOM node
  516.  * \param xml     The XML node
  517.  * \return DOM_NO_ERR on success, appropriate error otherwise
  518.  */
  519. dom_exception xml_parser_link_nodes(dom_xml_parser *parser,
  520.                 struct dom_node *dom, xmlNodePtr xml)
  521. {
  522.         void *prev_data;
  523.         dom_exception err;
  524.  
  525.         /* Register XML node as user data for DOM node */
  526.         err = dom_node_set_user_data(dom, parser->udkey, xml, NULL,
  527.                         &prev_data);
  528.         if (err != DOM_NO_ERR) {
  529.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  530.                                 "Failed setting user data: %d", err);
  531.                 return err;
  532.         }
  533.  
  534.         /* Register DOM node with the XML node */
  535.         xml->_private = dom;
  536.  
  537.         return DOM_NO_ERR;
  538. }
  539.  
  540. /**
  541.  * Add a node to the DOM
  542.  *
  543.  * \param parser  The parser context
  544.  * \param parent  The parent DOM node
  545.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  546.  */
  547. void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent,
  548.                 xmlNodePtr child)
  549. {
  550.         static const char *node_types[] = {
  551.                 "THIS_IS_NOT_A_NODE",
  552.                 "XML_ELEMENT_NODE",
  553.                 "XML_ATTRIBUTE_NODE",
  554.                 "XML_TEXT_NODE",
  555.                 "XML_CDATA_SECTION_NODE",
  556.                 "XML_ENTITY_REF_NODE",
  557.                 "XML_ENTITY_NODE",
  558.                 "XML_PI_NODE",
  559.                 "XML_COMMENT_NODE",
  560.                 "XML_DOCUMENT_NODE",
  561.                 "XML_DOCUMENT_TYPE_NODE",
  562.                 "XML_DOCUMENT_FRAG_NODE",
  563.                 "XML_NOTATION_NODE",
  564.                 "XML_HTML_DOCUMENT_NODE",
  565.                 "XML_DTD_NODE",
  566.                 "XML_ELEMENT_DECL",
  567.                 "XML_ATTRIBUTE_DECL",
  568.                 "XML_ENTITY_DECL",
  569.                 "XML_NAMESPACE_DECL",
  570.                 "XML_XINCLUDE_START",
  571.                 "XML_XINCLUDE_END",
  572.                 "XML_DOCB_DOCUMENT_NODE"
  573.         };
  574.  
  575.         switch (child->type) {
  576.         case XML_ELEMENT_NODE:
  577.                 xml_parser_add_element_node(parser, parent, child);
  578.                 break;
  579.         case XML_TEXT_NODE:
  580.                 xml_parser_add_text_node(parser, parent, child);
  581.                 break;
  582.         case XML_CDATA_SECTION_NODE:
  583.                 xml_parser_add_cdata_section(parser, parent, child);
  584.                 break;
  585.         case XML_ENTITY_REF_NODE:
  586.                 xml_parser_add_entity_reference(parser, parent, child);
  587.                 break;
  588.         case XML_COMMENT_NODE:
  589.                 xml_parser_add_comment(parser, parent, child);
  590.                 break;
  591.         case XML_DTD_NODE:
  592.                 xml_parser_add_document_type(parser, parent, child);
  593.                 break;
  594.     case XML_ENTITY_DECL:
  595.         xml_parser_add_entity(parser, parent, child);
  596.         break;
  597.         default:
  598.                 parser->msg(DOM_MSG_NOTICE, parser->mctx,
  599.                                 "Unsupported node type: %s",
  600.                                 node_types[child->type]);
  601.         }
  602. }
  603.  
  604. /**
  605.  * Add an element node to the DOM
  606.  *
  607.  * \param parser  The parser context
  608.  * \param parent  The parent DOM node
  609.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  610.  */
  611. void xml_parser_add_element_node(dom_xml_parser *parser,
  612.                 struct dom_node *parent, xmlNodePtr child)
  613. {
  614.         struct dom_element *el, *ins_el = NULL;
  615.         xmlAttrPtr a;
  616.         dom_exception err;
  617.  
  618.         /* Create the element node */
  619.         if (child->ns == NULL) {
  620.                 /* No namespace */
  621.                 dom_string *tag_name;
  622.  
  623.                 /* Create tag name DOM string */
  624.                 err = dom_string_create(child->name,
  625.                                 strlen((const char *) child->name), &tag_name);
  626.                 if (err != DOM_NO_ERR) {
  627.                         parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  628.                                         "No memory for tag name");
  629.                         return;
  630.                 }
  631.  
  632.                 /* Create element node */
  633.                 err = dom_document_create_element(parser->doc,
  634.                                 tag_name, &el);
  635.                 if (err != DOM_NO_ERR) {
  636.                         dom_string_unref(tag_name);
  637.                         parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  638.                                         "Failed creating element '%s'",
  639.                                         child->name);
  640.                         return;
  641.                 }
  642.  
  643.                 /* No longer need tag name */
  644.                 dom_string_unref(tag_name);
  645.         } else {
  646.                 /* Namespace */
  647.                 dom_string *namespace;
  648.                 dom_string *qname;
  649.                 size_t qnamelen = (child->ns->prefix != NULL ?
  650.                         strlen((const char *) child->ns->prefix) : 0) +
  651.                         (child->ns->prefix != NULL ? 1 : 0) /* ':' */ +
  652.                         strlen((const char *) child->name);
  653.                 uint8_t qnamebuf[qnamelen + 1 /* '\0' */];
  654.  
  655.                 /* Create namespace DOM string */
  656.                 err = dom_string_create(
  657.                                 child->ns->href,
  658.                                 strlen((const char *) child->ns->href),
  659.                                 &namespace);
  660.                 if (err != DOM_NO_ERR) {
  661.                         parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  662.                                         "No memory for namespace");
  663.                         return;
  664.                 }
  665.  
  666.                 /* QName is "prefix:localname",
  667.                  * or "localname" if there is no prefix */
  668.                 sprintf((char *) qnamebuf, "%s%s%s",
  669.                         child->ns->prefix != NULL ?
  670.                                 (const char *) child->ns->prefix : "",
  671.                         child->ns->prefix != NULL ? ":" : "",
  672.                         (const char *) child->name);
  673.  
  674.                 /* Create qname DOM string */
  675.                 err = dom_string_create(
  676.                                 qnamebuf,
  677.                                 qnamelen,
  678.                                 &qname);
  679.                 if (err != DOM_NO_ERR) {
  680.                         dom_string_unref(namespace);
  681.                         parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  682.                                         "No memory for qname");
  683.                         return;
  684.                 }
  685.  
  686.                 /* Create element node */
  687.                 err = dom_document_create_element_ns(parser->doc,
  688.                                 namespace, qname, &el);
  689.                 if (err != DOM_NO_ERR) {
  690.                         dom_string_unref(namespace);
  691.                         dom_string_unref(qname);
  692.                         parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  693.                                         "Failed creating element '%s'",
  694.                                         qnamebuf);
  695.                         return;
  696.                 }
  697.  
  698.                 /* No longer need namespace / qname */
  699.                 dom_string_unref(namespace);
  700.                 dom_string_unref(qname);
  701.         }
  702.  
  703.         /* Add attributes to created element */
  704.         for (a = child->properties; a != NULL; a = a->next) {
  705.                 struct dom_attr *attr, *prev_attr;
  706.                 xmlNodePtr c;
  707.  
  708.                 /* Create attribute node */
  709.                 if (a->ns == NULL) {
  710.                         /* Attribute has no namespace */
  711.                         dom_string *name;
  712.  
  713.                         /* Create attribute name DOM string */
  714.                         err = dom_string_create(
  715.                                         a->name,
  716.                                         strlen((const char *) a->name),
  717.                                         &name);
  718.                         if (err != DOM_NO_ERR) {
  719.                                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  720.                                                 "No memory for attribute name");
  721.                                 goto cleanup;
  722.                         }
  723.  
  724.                         /* Create attribute */
  725.                         err = dom_document_create_attribute(parser->doc,
  726.                                         name, &attr);
  727.                         if (err != DOM_NO_ERR) {
  728.                                 dom_string_unref(name);
  729.                                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  730.                                                 "Failed creating attribute \
  731.                                                 '%s'", a->name);
  732.                                 goto cleanup;
  733.                         }
  734.  
  735.                         /* No longer need attribute name */
  736.                         dom_string_unref(name);
  737.                 } else {
  738.                         /* Attribute has namespace */
  739.                         dom_string *namespace;
  740.                         dom_string *qname;
  741.                         size_t qnamelen = (a->ns->prefix != NULL ?
  742.                                 strlen((const char *) a->ns->prefix) : 0) +
  743.                                 (a->ns->prefix != NULL ? 1 : 0) /* ':' */ +
  744.                                 strlen((const char *) a->name);
  745.                         uint8_t qnamebuf[qnamelen + 1 /* '\0' */];
  746.  
  747.                         /* Create namespace DOM string */
  748.                         err = dom_string_create(
  749.                                         a->ns->href,
  750.                                         strlen((const char *) a->ns->href),
  751.                                         &namespace);
  752.                         if (err != DOM_NO_ERR) {
  753.                                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  754.                                                 "No memory for namespace");
  755.                                 return;
  756.                         }
  757.  
  758.                         /* QName is "prefix:localname",
  759.                          * or "localname" if there is no prefix */
  760.                         sprintf((char *) qnamebuf, "%s%s%s",
  761.                                 a->ns->prefix != NULL ?
  762.                                         (const char *) a->ns->prefix : "",
  763.                                 a->ns->prefix != NULL ? ":" : "",
  764.                                 (const char *) a->name);
  765.  
  766.                         /* Create qname DOM string */
  767.                         err = dom_string_create(
  768.                                         qnamebuf,
  769.                                         qnamelen,
  770.                                         &qname);
  771.                         if (err != DOM_NO_ERR) {
  772.                                 dom_string_unref(namespace);
  773.                                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  774.                                                 "No memory for qname");
  775.                                 return;
  776.                         }
  777.  
  778.                         /* Create attribute */
  779.                         err = dom_document_create_attribute_ns(parser->doc,
  780.                                         namespace, qname, &attr);
  781.                         if (err != DOM_NO_ERR) {
  782.                                 dom_string_unref(namespace);
  783.                                 dom_string_unref(qname);
  784.                                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  785.                                                 "Failed creating attribute \
  786.                                                 '%s'", qnamebuf);
  787.                                 return;
  788.                         }
  789.  
  790.                         /* No longer need namespace / qname */
  791.                         dom_string_unref(namespace);
  792.                         dom_string_unref(qname);
  793.                 }
  794.  
  795.                 /* Clone subtree (attribute value) */
  796.                 for (c = a->children; c != NULL; c = c->next) {
  797.                         xml_parser_add_node(parser,
  798.                                         (struct dom_node *) attr, c);
  799.                 }
  800.  
  801.                 /* Link nodes together */
  802.                 err = xml_parser_link_nodes(parser,
  803.                                 (struct dom_node *) attr, (xmlNodePtr) a);
  804.                 if (err != DOM_NO_ERR) {
  805.                         dom_node_unref((struct dom_node *) attr);
  806.                         goto cleanup;
  807.                 }
  808.  
  809.                 if (a->ns == NULL) {
  810.                         /* And add attribute to the element */
  811.                         err = dom_element_set_attribute_node(el, attr,
  812.                                         &prev_attr);
  813.                         if (err != DOM_NO_ERR) {
  814.                                 dom_node_unref((struct dom_node *) attr);
  815.                                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  816.                                                 "Failed attaching attribute \
  817.                                                 '%s'", a->name);
  818.                                 goto cleanup;
  819.                         }
  820.                 } else {
  821.                         err = dom_element_set_attribute_node_ns(el, attr,
  822.                                         &prev_attr);
  823.                         if (err != DOM_NO_ERR) {
  824.                                 dom_node_unref((struct dom_node *) attr);
  825.                                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  826.                                                 "Failed attaching attribute \
  827.                                                 '%s'", a->name);
  828.                                 goto cleanup;
  829.                         }
  830.                 }
  831.  
  832.                 /* We're not interested in the previous attribute (if any) */
  833.                 if (prev_attr != NULL && prev_attr != attr)
  834.                         dom_node_unref((struct dom_node *) prev_attr);
  835.  
  836.                 /* We're no longer interested in the attribute node */
  837.                 dom_node_unref((struct dom_node *) attr);
  838.         }
  839.  
  840.         /* Append element to parent */
  841.         err = dom_node_append_child(parent, (struct dom_node *) el,
  842.                         (struct dom_node **) (void *) &ins_el);
  843.         if (err != DOM_NO_ERR) {
  844.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  845.                                 "Failed attaching element '%s'",
  846.                                 child->name);
  847.                 goto cleanup;
  848.         }
  849.  
  850.         /* We're not interested in the inserted element */
  851.         if (ins_el != NULL)
  852.                 dom_node_unref((struct dom_node *) ins_el);
  853.  
  854.         /* Link nodes together */
  855.         err = xml_parser_link_nodes(parser, (struct dom_node *) el,
  856.                         child);
  857.         if (err != DOM_NO_ERR) {
  858.                 goto cleanup;
  859.         }
  860.  
  861.         /* No longer interested in element node */
  862.         dom_node_unref((struct dom_node *) el);
  863.  
  864.         return;
  865.  
  866. cleanup:
  867.         /* No longer want node (any attributes attached to it
  868.          * will be cleaned up with it) */
  869.         dom_node_unref((struct dom_node *) el);
  870.  
  871.         return;
  872. }
  873.  
  874. /**
  875.  * Add a text node to the DOM
  876.  *
  877.  * \param parser  The parser context
  878.  * \param parent  The parent DOM node
  879.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  880.  */
  881. void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent,
  882.                 xmlNodePtr child)
  883. {
  884.         struct dom_text *text, *ins_text = NULL;
  885.         dom_string *data;
  886.         dom_exception err;
  887.  
  888.         /* Create DOM string data for text node */
  889.         err = dom_string_create(child->content,
  890.                         strlen((const char *) child->content), &data);
  891.         if (err != DOM_NO_ERR) {
  892.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  893.                                 "No memory for text node contents ");
  894.                 return;
  895.         }
  896.  
  897.         /* Create text node */
  898.         err = dom_document_create_text_node(parser->doc, data, &text);
  899.         if (err != DOM_NO_ERR) {
  900.                 dom_string_unref(data);
  901.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  902.                                 "No memory for text node");
  903.                 return;
  904.         }
  905.  
  906.         /* No longer need data */
  907.         dom_string_unref(data);
  908.  
  909.         /* Append text node to parent */
  910.         err = dom_node_append_child(parent, (struct dom_node *) text,
  911.                         (struct dom_node **) (void *) &ins_text);
  912.         if (err != DOM_NO_ERR) {
  913.                 dom_node_unref((struct dom_node *) text);
  914.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  915.                                 "Failed attaching text node");
  916.                 return;
  917.         }
  918.  
  919.         /* We're not interested in the inserted text node */
  920.         if (ins_text != NULL)
  921.                 dom_node_unref((struct dom_node *) ins_text);
  922.  
  923.         /* Link nodes together */
  924.         err = xml_parser_link_nodes(parser, (struct dom_node *) text,
  925.                         child);
  926.         if (err != DOM_NO_ERR) {
  927.                 dom_node_unref((struct dom_node *) text);
  928.                 return;
  929.         }
  930.  
  931.         /* No longer interested in text node */
  932.         dom_node_unref((struct dom_node *) text);
  933. }
  934.  
  935. /**
  936.  * Add a cdata section to the DOM
  937.  *
  938.  * \param parser  The parser context
  939.  * \param parent  The parent DOM node
  940.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  941.  */
  942. void xml_parser_add_cdata_section(dom_xml_parser *parser,
  943.                 struct dom_node *parent, xmlNodePtr child)
  944. {
  945.         struct dom_cdata_section *cdata, *ins_cdata = NULL;
  946.         dom_string *data;
  947.         dom_exception err;
  948.  
  949.         /* Create DOM string data for cdata section */
  950.         err = dom_string_create(child->content,
  951.                         strlen((const char *) child->content), &data);
  952.         if (err != DOM_NO_ERR) {
  953.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  954.                                 "No memory for cdata section contents");
  955.                 return;
  956.         }
  957.  
  958.         /* Create cdata section */
  959.         err = dom_document_create_cdata_section(parser->doc, data, &cdata);
  960.         if (err != DOM_NO_ERR) {
  961.                 dom_string_unref(data);
  962.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  963.                                 "No memory for cdata section");
  964.                 return;
  965.         }
  966.  
  967.         /* No longer need data */
  968.         dom_string_unref(data);
  969.  
  970.         /* Append cdata section to parent */
  971.         err = dom_node_append_child(parent, (struct dom_node *) cdata,
  972.                         (struct dom_node **) (void *) &ins_cdata);
  973.         if (err != DOM_NO_ERR) {
  974.                 dom_node_unref((struct dom_node *) cdata);
  975.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  976.                                 "Failed attaching cdata section");
  977.                 return;
  978.         }
  979.  
  980.         /* We're not interested in the inserted cdata section */
  981.         if (ins_cdata != NULL)
  982.                 dom_node_unref((struct dom_node *) ins_cdata);
  983.  
  984.         /* Link nodes together */
  985.         err = xml_parser_link_nodes(parser, (struct dom_node *) cdata,
  986.                         child);
  987.         if (err != DOM_NO_ERR) {
  988.                 dom_node_unref((struct dom_node *) cdata);
  989.                 return;
  990.         }
  991.  
  992.         /* No longer interested in cdata section */
  993.         dom_node_unref((struct dom_node *) cdata);
  994. }
  995.  
  996. /**
  997.  * Add an entity reference to the DOM
  998.  *
  999.  * \param parser  The parser context
  1000.  * \param parent  The parent DOM node
  1001.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  1002.  */
  1003. void xml_parser_add_entity_reference(dom_xml_parser *parser,
  1004.                 struct dom_node *parent, xmlNodePtr child)
  1005. {
  1006.         struct dom_entity_reference *entity, *ins_entity = NULL;
  1007.         dom_string *name;
  1008.         xmlNodePtr c;
  1009.         dom_exception err;
  1010.  
  1011.         /* Create name of entity reference */
  1012.         err = dom_string_create(child->name,
  1013.                         strlen((const char *) child->name), &name);
  1014.         if (err != DOM_NO_ERR) {
  1015.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1016.                                 "No memory for entity reference name");
  1017.                 return;
  1018.         }
  1019.  
  1020.         /* Create text node */
  1021.         err = dom_document_create_entity_reference(parser->doc, name,
  1022.                         &entity);
  1023.         if (err != DOM_NO_ERR) {
  1024.                 dom_string_unref(name);
  1025.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1026.                                 "No memory for entity reference");
  1027.                 return;
  1028.         }
  1029.  
  1030.         /* No longer need name */
  1031.         dom_string_unref(name);
  1032.  
  1033.         /* Mirror subtree (reference value) */
  1034.         for (c = child->children; c != NULL; c = c->next) {
  1035.                 xml_parser_add_node(parser, (struct dom_node *) entity, c);
  1036.         }
  1037.  
  1038.         /* Append entity reference to parent */
  1039.         err = dom_node_append_child(parent, (struct dom_node *) entity,
  1040.                         (struct dom_node **) (void *) &ins_entity);
  1041.         if (err != DOM_NO_ERR) {
  1042.                 dom_node_unref((struct dom_node *) entity);
  1043.                 parser->msg(DOM_MSG_ERROR, parser->mctx,
  1044.                                 "Failed attaching entity reference");
  1045.                 return;
  1046.         }
  1047.  
  1048.         /* We're not interested in the inserted entity reference */
  1049.         if (ins_entity != NULL)
  1050.                 dom_node_unref((struct dom_node *) ins_entity);
  1051.  
  1052.         /* Link nodes together */
  1053.         err = xml_parser_link_nodes(parser, (struct dom_node *) entity,
  1054.                         child);
  1055.         if (err != DOM_NO_ERR) {
  1056.                 dom_node_unref((struct dom_node *) entity);
  1057.                 return;
  1058.         }
  1059.  
  1060.         /* No longer interested in entity reference */
  1061.         dom_node_unref((struct dom_node *) entity);
  1062. }
  1063.  
  1064. static void xml_parser_add_entity(dom_xml_parser *parser,
  1065.         struct dom_node *parent, xmlNodePtr child)
  1066. {
  1067.     UNUSED(parser);
  1068.     UNUSED(parent);
  1069.     UNUSED(child);
  1070. }
  1071.  
  1072. /**
  1073.  * Add a comment to the DOM
  1074.  *
  1075.  * \param parser  The parser context
  1076.  * \param parent  The parent DOM node
  1077.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  1078.  */
  1079. void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent,
  1080.                 xmlNodePtr child)
  1081. {
  1082.         struct dom_comment *comment, *ins_comment = NULL;
  1083.         dom_string *data;
  1084.         dom_exception err;
  1085.  
  1086.         /* Create DOM string data for comment */
  1087.         err = dom_string_create(child->content,
  1088.                         strlen((const char *) child->content), &data);
  1089.         if (err != DOM_NO_ERR) {
  1090.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1091.                                 "No memory for comment data");
  1092.                 return;
  1093.         }
  1094.  
  1095.         /* Create comment */
  1096.         err = dom_document_create_comment(parser->doc, data, &comment);
  1097.         if (err != DOM_NO_ERR) {
  1098.                 dom_string_unref(data);
  1099.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1100.                                         "No memory for comment node");
  1101.                 return;
  1102.         }
  1103.  
  1104.         /* No longer need data */
  1105.         dom_string_unref(data);
  1106.  
  1107.         /* Append comment to parent */
  1108.         err = dom_node_append_child(parent, (struct dom_node *) comment,
  1109.                         (struct dom_node **) (void *) &ins_comment);
  1110.         if (err != DOM_NO_ERR) {
  1111.                 dom_node_unref((struct dom_node *) comment);
  1112.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1113.                                 "Failed attaching comment node");
  1114.                 return;
  1115.         }
  1116.  
  1117.         /* We're not interested in the inserted comment */
  1118.         if (ins_comment != NULL)
  1119.                 dom_node_unref((struct dom_node *) ins_comment);
  1120.  
  1121.         /* Link nodes together */
  1122.         err = xml_parser_link_nodes(parser, (struct dom_node *) comment,
  1123.                         child);
  1124.         if (err != DOM_NO_ERR) {
  1125.                 dom_node_unref((struct dom_node *) comment);
  1126.                 return;
  1127.         }
  1128.  
  1129.         /* No longer interested in comment */
  1130.         dom_node_unref((struct dom_node *) comment);
  1131. }
  1132.  
  1133. /**
  1134.  * Add a document type to the DOM
  1135.  *
  1136.  * \param parser  The parser context
  1137.  * \param parent  The parent DOM node
  1138.  * \param child   The xmlNode to mirror in the DOM as a child of parent
  1139.  */
  1140. void xml_parser_add_document_type(dom_xml_parser *parser,
  1141.                 struct dom_node *parent, xmlNodePtr child)
  1142. {
  1143.         xmlDtdPtr dtd = (xmlDtdPtr) child;
  1144.         struct dom_document_type *doctype, *ins_doctype = NULL;
  1145.         const char *qname, *public_id, *system_id;
  1146.         dom_exception err;
  1147.  
  1148.         /* Create qname for doctype */
  1149.         qname = (const char *) dtd->name;
  1150.  
  1151.         /* Create public ID for doctype */
  1152.         public_id = dtd->ExternalID != NULL ?
  1153.                         (const char *) dtd->ExternalID : "";
  1154.  
  1155.         /* Create system ID for doctype */
  1156.         system_id = dtd->SystemID != NULL ?
  1157.                         (const char *) dtd->SystemID : "";
  1158.  
  1159.         /* Create doctype */
  1160.         err = dom_implementation_create_document_type(
  1161.                         qname, public_id, system_id,
  1162.                         &doctype);
  1163.         if (err != DOM_NO_ERR) {
  1164.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1165.                                 "Failed to create document type");
  1166.                 return;
  1167.         }
  1168.  
  1169.         /* Add doctype to document */
  1170.         err = dom_node_append_child(parent, (struct dom_node *) doctype,
  1171.                         (struct dom_node **) (void *) &ins_doctype);
  1172.         if (err != DOM_NO_ERR) {
  1173.                 dom_node_unref((struct dom_node *) doctype);
  1174.                 parser->msg(DOM_MSG_CRITICAL, parser->mctx,
  1175.                                         "Failed attaching doctype");
  1176.                 return;
  1177.         }
  1178.  
  1179.         /* Not interested in inserted node */
  1180.         if (ins_doctype != NULL)
  1181.                 dom_node_unref((struct dom_node *) ins_doctype);
  1182.  
  1183.         /* Link nodes together */
  1184.         err = xml_parser_link_nodes(parser, (struct dom_node *) doctype,
  1185.                         child);
  1186.         if (err != DOM_NO_ERR) {
  1187.                 dom_node_unref((struct dom_node *) doctype);
  1188.                 return;
  1189.         }
  1190.  
  1191.         /* No longer interested in doctype */
  1192.         dom_node_unref((struct dom_node *) doctype);
  1193. }
  1194.  
  1195. /* ------------------------------------------------------------------------*/
  1196.  
  1197. void xml_parser_internal_subset(void *ctx, const xmlChar *name,
  1198.                 const xmlChar *ExternalID, const xmlChar *SystemID)
  1199. {
  1200.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1201.  
  1202.         xmlSAX2InternalSubset(parser->xml_ctx, name, ExternalID, SystemID);
  1203. }
  1204.  
  1205. int xml_parser_is_standalone(void *ctx)
  1206. {
  1207.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1208.  
  1209.         return xmlSAX2IsStandalone(parser->xml_ctx);
  1210. }
  1211.  
  1212. int xml_parser_has_internal_subset(void *ctx)
  1213. {
  1214.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1215.  
  1216.         return xmlSAX2HasInternalSubset(parser->xml_ctx);
  1217. }
  1218.  
  1219. int xml_parser_has_external_subset(void *ctx)
  1220. {
  1221.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1222.  
  1223.         return xmlSAX2HasExternalSubset(parser->xml_ctx);
  1224. }
  1225.  
  1226. xmlParserInputPtr xml_parser_resolve_entity(void *ctx,
  1227.                 const xmlChar *publicId, const xmlChar *systemId)
  1228. {
  1229.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1230.  
  1231.         return xmlSAX2ResolveEntity(parser->xml_ctx, publicId, systemId);
  1232. }
  1233.  
  1234. xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name)
  1235. {
  1236.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1237.  
  1238.         return xmlSAX2GetEntity(parser->xml_ctx, name);
  1239. }
  1240.  
  1241. void xml_parser_entity_decl(void *ctx, const xmlChar *name,
  1242.                 int type, const xmlChar *publicId, const xmlChar *systemId,
  1243.                 xmlChar *content)
  1244. {
  1245.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1246.  
  1247.         xmlSAX2EntityDecl(parser->xml_ctx, name, type, publicId, systemId,
  1248.                         content);
  1249. }
  1250.  
  1251. void xml_parser_notation_decl(void *ctx, const xmlChar *name,
  1252.                 const xmlChar *publicId, const xmlChar *systemId)
  1253. {
  1254.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1255.  
  1256.         xmlSAX2NotationDecl(parser->xml_ctx, name, publicId, systemId);
  1257. }
  1258.  
  1259. void xml_parser_attribute_decl(void *ctx, const xmlChar *elem,
  1260.                 const xmlChar *fullname, int type, int def,
  1261.                 const xmlChar *defaultValue, xmlEnumerationPtr tree)
  1262. {
  1263.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1264.  
  1265.         xmlSAX2AttributeDecl(parser->xml_ctx, elem, fullname, type, def,
  1266.                         defaultValue, tree);
  1267. }
  1268.  
  1269. void xml_parser_element_decl(void *ctx, const xmlChar *name,
  1270.                 int type, xmlElementContentPtr content)
  1271. {
  1272.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1273.  
  1274.         xmlSAX2ElementDecl(parser->xml_ctx, name, type, content);
  1275. }
  1276.  
  1277. void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name,
  1278.                 const xmlChar *publicId, const xmlChar *systemId,
  1279.                 const xmlChar *notationName)
  1280. {
  1281.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1282.  
  1283.         xmlSAX2UnparsedEntityDecl(parser->xml_ctx, name, publicId,
  1284.                         systemId, notationName);
  1285. }
  1286.  
  1287. void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc)
  1288. {
  1289.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1290.  
  1291.         xmlSAX2SetDocumentLocator(parser->xml_ctx, loc);
  1292. }
  1293.  
  1294. void xml_parser_reference(void *ctx, const xmlChar *name)
  1295. {
  1296.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1297.  
  1298.         xmlSAX2Reference(parser->xml_ctx, name);
  1299. }
  1300.  
  1301. void xml_parser_characters(void *ctx, const xmlChar *ch, int len)
  1302. {
  1303.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1304.  
  1305.         xmlSAX2Characters(parser->xml_ctx, ch, len);
  1306. }
  1307.  
  1308. void xml_parser_comment(void *ctx, const xmlChar *value)
  1309. {
  1310.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1311.  
  1312.         xmlSAX2Comment(parser->xml_ctx, value);
  1313. }
  1314.  
  1315. xmlEntityPtr xml_parser_get_parameter_entity(void *ctx, const xmlChar *name)
  1316. {
  1317.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1318.  
  1319.         return xmlSAX2GetParameterEntity(parser->xml_ctx, name);
  1320. }
  1321.  
  1322. void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len)
  1323. {
  1324.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1325.  
  1326.         xmlSAX2CDataBlock(parser->xml_ctx, value, len);
  1327. }
  1328.  
  1329. void xml_parser_external_subset(void *ctx, const xmlChar *name,
  1330.                 const xmlChar *ExternalID, const xmlChar *SystemID)
  1331. {
  1332.         dom_xml_parser *parser = (dom_xml_parser *) ctx;
  1333.  
  1334.         xmlSAX2ExternalSubset(parser->xml_ctx, name, ExternalID, SystemID);
  1335. }
  1336.