SAX.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:37k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * SAX.c : Default SAX handler to build a tree.
  3.  *
  4.  * See Copyright for the status of this software.
  5.  *
  6.  * Daniel Veillard <Daniel.Veillard@w3.org>
  7.  */
  8. #ifdef WIN32
  9. #include "win32config.h"
  10. #else
  11. #include "config.h"
  12. #endif
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <libxml/xmlmemory.h>
  16. #include <libxml/tree.h>
  17. #include <libxml/parser.h>
  18. #include <libxml/parserInternals.h>
  19. #include <libxml/valid.h>
  20. #include <libxml/entities.h>
  21. #include "xml-error.h"
  22. #include <libxml/debugXML.h>
  23. #include <libxml/xmlIO.h>
  24. #include <libxml/SAX.h>
  25. /* #define DEBUG_SAX */
  26. /* #define DEBUG_SAX_TREE */
  27. /**
  28.  * getPublicId:
  29.  * @ctx: the user data (XML parser context)
  30.  *
  31.  * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
  32.  *
  33.  * Returns a xmlChar *
  34.  */
  35. const xmlChar *
  36. getPublicId(void *ctx)
  37. {
  38.     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  39.     return(NULL);
  40. }
  41. /**
  42.  * getSystemId:
  43.  * @ctx: the user data (XML parser context)
  44.  *
  45.  * Return the system ID, basically URL or filename e.g.
  46.  * http://www.sgmlsource.com/dtds/memo.dtd
  47.  *
  48.  * Returns a xmlChar *
  49.  */
  50. const xmlChar *
  51. getSystemId(void *ctx)
  52. {
  53.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  54.     return(BAD_CAST ctxt->input->filename); 
  55. }
  56. /**
  57.  * getLineNumber:
  58.  * @ctx: the user data (XML parser context)
  59.  *
  60.  * Return the line number of the current parsing point.
  61.  *
  62.  * Returns an int
  63.  */
  64. int
  65. getLineNumber(void *ctx)
  66. {
  67.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  68.     return(ctxt->input->line);
  69. }
  70. /**
  71.  * getColumnNumber:
  72.  * @ctx: the user data (XML parser context)
  73.  *
  74.  * Return the column number of the current parsing point.
  75.  *
  76.  * Returns an int
  77.  */
  78. int
  79. getColumnNumber(void *ctx)
  80. {
  81.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  82.     return(ctxt->input->col);
  83. }
  84. /*
  85.  * The default SAX Locator.
  86.  */
  87. xmlSAXLocator xmlDefaultSAXLocator = {
  88.     getPublicId, getSystemId, getLineNumber, getColumnNumber
  89. };
  90. /**
  91.  * isStandalone:
  92.  * @ctx: the user data (XML parser context)
  93.  *
  94.  * Is this document tagged standalone ?
  95.  *
  96.  * Returns 1 if true
  97.  */
  98. int
  99. isStandalone(void *ctx)
  100. {
  101.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  102.     return(ctxt->myDoc->standalone == 1);
  103. }
  104. /**
  105.  * hasInternalSubset:
  106.  * @ctx: the user data (XML parser context)
  107.  *
  108.  * Does this document has an internal subset
  109.  *
  110.  * Returns 1 if true
  111.  */
  112. int
  113. hasInternalSubset(void *ctx)
  114. {
  115.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  116.     return(ctxt->myDoc->intSubset != NULL);
  117. }
  118. /**
  119.  * hasExternalSubset:
  120.  * @ctx: the user data (XML parser context)
  121.  *
  122.  * Does this document has an external subset
  123.  *
  124.  * Returns 1 if true
  125.  */
  126. int
  127. hasExternalSubset(void *ctx)
  128. {
  129.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  130.     return(ctxt->myDoc->extSubset != NULL);
  131. }
  132. /**
  133.  * internalSubset:
  134.  * @ctx: the user data (XML parser context)
  135.  *
  136.  * Callback on internal subset declaration.
  137.  */
  138. void
  139. internalSubset(void *ctx, const xmlChar *name,
  140.        const xmlChar *ExternalID, const xmlChar *SystemID)
  141. {
  142.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  143. #ifdef DEBUG_SAX
  144.     fprintf(stderr, "SAX.internalSubset(%s, %s, %s)n",
  145.             name, ExternalID, SystemID);
  146. #endif
  147.     xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
  148. }
  149. /**
  150.  * externalSubset:
  151.  * @ctx: the user data (XML parser context)
  152.  *
  153.  * Callback on external subset declaration.
  154.  */
  155. void
  156. externalSubset(void *ctx, const xmlChar *name,
  157.        const xmlChar *ExternalID, const xmlChar *SystemID)
  158. {
  159.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  160. #ifdef DEBUG_SAX
  161.     fprintf(stderr, "SAX.externalSubset(%s, %s, %s)n",
  162.             name, ExternalID, SystemID);
  163. #endif
  164.     if (((ExternalID != NULL) || (SystemID != NULL)) &&
  165.         (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
  166. /*
  167.  * Try to fetch and parse the external subset.
  168.  */
  169. xmlParserInputPtr oldinput;
  170. int oldinputNr;
  171. int oldinputMax;
  172. xmlParserInputPtr *oldinputTab;
  173. int oldwellFormed;
  174. xmlParserInputPtr input = NULL;
  175. xmlCharEncoding enc;
  176. /*
  177.  * Ask the Entity resolver to load the damn thing
  178.  */
  179. if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
  180.     input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
  181.                                         SystemID);
  182. if (input == NULL) {
  183.     return;
  184. }
  185. xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
  186. /*
  187.  * make sure we won't destroy the main document context
  188.  */
  189. oldinput = ctxt->input;
  190. oldinputNr = ctxt->inputNr;
  191. oldinputMax = ctxt->inputMax;
  192. oldinputTab = ctxt->inputTab;
  193. oldwellFormed = ctxt->wellFormed;
  194. ctxt->inputTab = (xmlParserInputPtr *)
  195.                  xmlMalloc(5 * sizeof(xmlParserInputPtr));
  196. if (ctxt->inputTab == NULL) {
  197.     ctxt->errNo = XML_ERR_NO_MEMORY;
  198.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  199. ctxt->sax->error(ctxt->userData, 
  200.      "externalSubset: out of memoryn");
  201.     ctxt->errNo = XML_ERR_NO_MEMORY;
  202.     ctxt->input = oldinput;
  203.     ctxt->inputNr = oldinputNr;
  204.     ctxt->inputMax = oldinputMax;
  205.     ctxt->inputTab = oldinputTab;
  206.     return;
  207. }
  208. ctxt->inputNr = 0;
  209. ctxt->inputMax = 5;
  210. ctxt->input = NULL;
  211. xmlPushInput(ctxt, input);
  212. /*
  213.  * On the fly encoding conversion if needed
  214.  */
  215. enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
  216. xmlSwitchEncoding(ctxt, enc);
  217. if (input->filename == NULL)
  218.     input->filename = (char *) xmlStrdup(SystemID);
  219. input->line = 1;
  220. input->col = 1;
  221. input->base = ctxt->input->cur;
  222. input->cur = ctxt->input->cur;
  223. input->free = NULL;
  224. /*
  225.  * let's parse that entity knowing it's an external subset.
  226.  */
  227. xmlParseExternalSubset(ctxt, ExternalID, SystemID);
  228.         /*
  229.  * Free up the external entities
  230.  */
  231. while (ctxt->inputNr > 1)
  232.     xmlPopInput(ctxt);
  233. xmlFreeInputStream(ctxt->input);
  234.         xmlFree(ctxt->inputTab);
  235. /*
  236.  * Restore the parsing context of the main entity
  237.  */
  238. ctxt->input = oldinput;
  239. ctxt->inputNr = oldinputNr;
  240. ctxt->inputMax = oldinputMax;
  241. ctxt->inputTab = oldinputTab;
  242. /* ctxt->wellFormed = oldwellFormed; */
  243.     }
  244. }
  245. /**
  246.  * resolveEntity:
  247.  * @ctx: the user data (XML parser context)
  248.  * @publicId: The public ID of the entity
  249.  * @systemId: The system ID of the entity
  250.  *
  251.  * The entity loader, to control the loading of external entities,
  252.  * the application can either:
  253.  *    - override this resolveEntity() callback in the SAX block
  254.  *    - or better use the xmlSetExternalEntityLoader() function to
  255.  *      set up it's own entity resolution routine
  256.  *
  257.  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  258.  */
  259. xmlParserInputPtr
  260. resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
  261. {
  262.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  263. #ifdef DEBUG_SAX
  264.     fprintf(stderr, "SAX.resolveEntity(%s, %s)n", publicId, systemId);
  265. #endif
  266.     return(xmlLoadExternalEntity((const char *) systemId,
  267.  (const char *) publicId, ctxt));
  268. }
  269. /**
  270.  * getEntity:
  271.  * @ctx: the user data (XML parser context)
  272.  * @name: The entity name
  273.  *
  274.  * Get an entity by name
  275.  *
  276.  * Returns the xmlEntityPtr if found.
  277.  */
  278. xmlEntityPtr
  279. getEntity(void *ctx, const xmlChar *name)
  280. {
  281.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  282.     xmlEntityPtr ret;
  283. #ifdef DEBUG_SAX
  284.     fprintf(stderr, "SAX.getEntity(%s)n", name);
  285. #endif
  286.     ret = xmlGetDocEntity(ctxt->myDoc, name);
  287.     return(ret);
  288. }
  289. /**
  290.  * getParameterEntity:
  291.  * @ctx: the user data (XML parser context)
  292.  * @name: The entity name
  293.  *
  294.  * Get a parameter entity by name
  295.  *
  296.  * Returns the xmlEntityPtr if found.
  297.  */
  298. xmlEntityPtr
  299. getParameterEntity(void *ctx, const xmlChar *name)
  300. {
  301.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  302.     xmlEntityPtr ret;
  303. #ifdef DEBUG_SAX
  304.     fprintf(stderr, "SAX.getParameterEntity(%s)n", name);
  305. #endif
  306.     ret = xmlGetParameterEntity(ctxt->myDoc, name);
  307.     return(ret);
  308. }
  309. /**
  310.  * entityDecl:
  311.  * @ctx: the user data (XML parser context)
  312.  * @name:  the entity name 
  313.  * @type:  the entity type 
  314.  * @publicId: The public ID of the entity
  315.  * @systemId: The system ID of the entity
  316.  * @content: the entity value (without processing).
  317.  *
  318.  * An entity definition has been parsed
  319.  */
  320. void
  321. entityDecl(void *ctx, const xmlChar *name, int type,
  322.           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
  323. {
  324.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  325. #ifdef DEBUG_SAX
  326.     fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)n",
  327.             name, type, publicId, systemId, content);
  328. #endif
  329.     if (ctxt->inSubset == 1)
  330. xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
  331.               systemId, content);
  332.     else if (ctxt->inSubset == 2)
  333. xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
  334.               systemId, content);
  335.     else {
  336. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  337.     ctxt->sax->error(ctxt, 
  338.      "SAX.entityDecl(%s) called while not in subsetn", name);
  339.     }
  340. }
  341. /**
  342.  * attributeDecl:
  343.  * @ctx: the user data (XML parser context)
  344.  * @fullname:  the attribute name 
  345.  * @type:  the attribute type 
  346.  * @publicId: The public ID of the attribute
  347.  * @systemId: The system ID of the attribute
  348.  * @content: the attribute value (without processing).
  349.  *
  350.  * An attribute definition has been parsed
  351.  */
  352. void
  353. attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
  354.               int type, int def, const xmlChar *defaultValue,
  355.       xmlEnumerationPtr tree)
  356. {
  357.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  358.     xmlAttributePtr attr;
  359.     xmlChar *name = NULL, *prefix = NULL;
  360. #ifdef DEBUG_SAX
  361.     fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)n",
  362.             elem, fullname, type, def, defaultValue);
  363. #endif
  364.     name = xmlSplitQName(ctxt, fullname, &prefix);
  365.     if (ctxt->inSubset == 1)
  366. attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
  367.                                name, prefix, type, def, defaultValue, tree);
  368.     else if (ctxt->inSubset == 2)
  369. attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
  370.                                name, prefix, type, def, defaultValue, tree);
  371.     else {
  372. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  373.     ctxt->sax->error(ctxt, 
  374.      "SAX.attributeDecl(%s) called while not in subsetn", name);
  375. return;
  376.     }
  377.     if (attr == 0) ctxt->valid = 0;
  378.     if (ctxt->validate && ctxt->wellFormed &&
  379.         ctxt->myDoc && ctxt->myDoc->intSubset)
  380. ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
  381.                                         attr);
  382.     if (prefix != NULL)
  383. xmlFree(prefix);
  384.     if (name != NULL)
  385. xmlFree(name);
  386. }
  387. /**
  388.  * elementDecl:
  389.  * @ctx: the user data (XML parser context)
  390.  * @name:  the element name 
  391.  * @type:  the element type 
  392.  * @publicId: The public ID of the element
  393.  * @systemId: The system ID of the element
  394.  * @content: the element value (without processing).
  395.  *
  396.  * An element definition has been parsed
  397.  */
  398. void
  399. elementDecl(void *ctx, const xmlChar *name, int type,
  400.     xmlElementContentPtr content)
  401. {
  402.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  403.     xmlElementPtr elem = NULL;
  404. #ifdef DEBUG_SAX
  405.     fprintf(stderr, "SAX.elementDecl(%s, %d, ...)n",
  406.             fullname, type);
  407. #endif
  408.     
  409.     if (ctxt->inSubset == 1)
  410. elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
  411.                              name, type, content);
  412.     else if (ctxt->inSubset == 2)
  413. elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
  414.                              name, type, content);
  415.     else {
  416. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  417.     ctxt->sax->error(ctxt, 
  418.      "SAX.elementDecl(%s) called while not in subsetn", name);
  419. return;
  420.     }
  421.     if (elem == NULL) ctxt->valid = 0;
  422.     if (ctxt->validate && ctxt->wellFormed &&
  423.         ctxt->myDoc && ctxt->myDoc->intSubset)
  424. ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
  425. }
  426. /**
  427.  * notationDecl:
  428.  * @ctx: the user data (XML parser context)
  429.  * @name: The name of the notation
  430.  * @publicId: The public ID of the entity
  431.  * @systemId: The system ID of the entity
  432.  *
  433.  * What to do when a notation declaration has been parsed.
  434.  */
  435. void
  436. notationDecl(void *ctx, const xmlChar *name,
  437.      const xmlChar *publicId, const xmlChar *systemId)
  438. {
  439.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  440.     xmlNotationPtr nota = NULL;
  441. #ifdef DEBUG_SAX
  442.     fprintf(stderr, "SAX.notationDecl(%s, %s, %s)n", name, publicId, systemId);
  443. #endif
  444.     if (ctxt->inSubset == 1)
  445. nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
  446.                               publicId, systemId);
  447.     else if (ctxt->inSubset == 2)
  448. nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
  449.                               publicId, systemId);
  450.     else {
  451. if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  452.     ctxt->sax->error(ctxt, 
  453.      "SAX.notationDecl(%s) called while not in subsetn", name);
  454. return;
  455.     }
  456.     if (nota == NULL) ctxt->valid = 0;
  457.     if (ctxt->validate && ctxt->wellFormed &&
  458.         ctxt->myDoc && ctxt->myDoc->intSubset)
  459. ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
  460.                                        nota);
  461. }
  462. /**
  463.  * unparsedEntityDecl:
  464.  * @ctx: the user data (XML parser context)
  465.  * @name: The name of the entity
  466.  * @publicId: The public ID of the entity
  467.  * @systemId: The system ID of the entity
  468.  * @notationName: the name of the notation
  469.  *
  470.  * What to do when an unparsed entity declaration is parsed
  471.  */
  472. void
  473. unparsedEntityDecl(void *ctx, const xmlChar *name,
  474.    const xmlChar *publicId, const xmlChar *systemId,
  475.    const xmlChar *notationName)
  476. {
  477.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  478. #ifdef DEBUG_SAX
  479.     fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)n",
  480.             name, publicId, systemId, notationName);
  481. #endif
  482.     if (ctxt->validate && ctxt->wellFormed &&
  483.         ctxt->myDoc && ctxt->myDoc->intSubset)
  484. ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
  485.                                       notationName);
  486.     xmlAddDocEntity(ctxt->myDoc, name,
  487.                     XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
  488.     publicId, systemId, notationName);
  489. }
  490. /**
  491.  * setDocumentLocator:
  492.  * @ctx: the user data (XML parser context)
  493.  * @loc: A SAX Locator
  494.  *
  495.  * Receive the document locator at startup, actually xmlDefaultSAXLocator
  496.  * Everything is available on the context, so this is useless in our case.
  497.  */
  498. void
  499. setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
  500. {
  501.     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  502. #ifdef DEBUG_SAX
  503.     fprintf(stderr, "SAX.setDocumentLocator()n");
  504. #endif
  505. }
  506. /**
  507.  * startDocument:
  508.  * @ctx: the user data (XML parser context)
  509.  *
  510.  * called when the document start being processed.
  511.  */
  512. void
  513. startDocument(void *ctx)
  514. {
  515.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  516.     xmlDocPtr doc;
  517. #ifdef DEBUG_SAX
  518.     fprintf(stderr, "SAX.startDocument()n");
  519. #endif
  520.     doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
  521.     if (doc != NULL) {
  522. if (ctxt->encoding != NULL)
  523.     doc->encoding = xmlStrdup(ctxt->encoding);
  524. else
  525.     doc->encoding = NULL;
  526. doc->standalone = ctxt->standalone;
  527.     }
  528. }
  529. /**
  530.  * endDocument:
  531.  * @ctx: the user data (XML parser context)
  532.  *
  533.  * called when the document end has been detected.
  534.  */
  535. void
  536. endDocument(void *ctx)
  537. {
  538.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  539. #ifdef DEBUG_SAX
  540.     fprintf(stderr, "SAX.endDocument()n");
  541. #endif
  542.     if (ctxt->validate && ctxt->wellFormed &&
  543.         ctxt->myDoc && ctxt->myDoc->intSubset)
  544. ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
  545. }
  546. /**
  547.  * attribute:
  548.  * @ctx: the user data (XML parser context)
  549.  * @name:  The attribute name
  550.  * @value:  The attribute value
  551.  *
  552.  * Handle an attribute that has been read by the parser.
  553.  * The default handling is to convert the attribute into an
  554.  * DOM subtree and past it in a new xmlAttr element added to
  555.  * the element.
  556.  */
  557. void
  558. attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
  559. {
  560.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  561.     xmlAttrPtr ret;
  562.     xmlChar *name;
  563.     xmlChar *ns;
  564.     xmlChar *nval;
  565.     xmlNsPtr namespace;
  566. /****************
  567. #ifdef DEBUG_SAX
  568.     fprintf(stderr, "SAX.attribute(%s, %s)n", fullname, value);
  569. #endif
  570.  ****************/
  571.     /*
  572.      * Split the full name into a namespace prefix and the tag name
  573.      */
  574.     name = xmlSplitQName(ctxt, fullname, &ns);
  575.     /*
  576.      * Do the last stave of the attribute normalization
  577.      */
  578.     nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
  579.        ctxt->node, fullname, value);
  580.     if (nval != NULL)
  581. value = nval;
  582.     /*
  583.      * Check whether it's a namespace definition
  584.      */
  585.     if ((ns == NULL) &&
  586.         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
  587.         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
  588. /* a default namespace definition */
  589. xmlNewNs(ctxt->node, value, NULL);
  590. if (name != NULL) 
  591.     xmlFree(name);
  592. if (nval != NULL)
  593.     xmlFree(nval);
  594. return;
  595.     }
  596.     if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
  597.         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
  598. /*
  599.  * Validate also for namespace decls, they are attributes from
  600.  * an XML-1.0 perspective
  601.  TODO ... doesn't map well with current API
  602.         if (ctxt->validate && ctxt->wellFormed &&
  603.     ctxt->myDoc && ctxt->myDoc->intSubset)
  604.     ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
  605.        ctxt->node, ret, value);
  606.  */
  607. /* a standard namespace definition */
  608. xmlNewNs(ctxt->node, value, name);
  609. xmlFree(ns);
  610. if (name != NULL) 
  611.     xmlFree(name);
  612. if (nval != NULL)
  613.     xmlFree(nval);
  614. return;
  615.     }
  616.     if (ns != NULL)
  617. namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
  618.     else {
  619. namespace = NULL;
  620.     }
  621.     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
  622.     ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
  623.     if (ret != NULL) {
  624.         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
  625.     xmlNodePtr tmp;
  626.     ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
  627.     tmp = ret->children;
  628.     while (tmp != NULL) {
  629. tmp->parent = (xmlNodePtr) ret;
  630. if (tmp->next == NULL)
  631.     ret->last = tmp;
  632. tmp = tmp->next;
  633.     }
  634. } else {
  635.     ret->children = xmlNewDocText(ctxt->myDoc, value);
  636.     ret->last = ret->children;
  637.     if (ret->children != NULL)
  638. ret->children->parent = (xmlNodePtr) ret;
  639. }
  640.     }
  641.     if (ctxt->validate && ctxt->wellFormed &&
  642.         ctxt->myDoc && ctxt->myDoc->intSubset) {
  643. /*
  644.  * If we don't substitute entities, the validation should be
  645.  * done on a value with replaced entities anyway.
  646.  */
  647.         if (!ctxt->replaceEntities) {
  648.     xmlChar *val;
  649.     ctxt->depth++;
  650.     val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
  651.                           0,0,0);
  652.     ctxt->depth--;
  653.     if (val == NULL)
  654. ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
  655. ctxt->myDoc, ctxt->node, ret, value);
  656.     else {
  657. ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
  658.         ctxt->myDoc, ctxt->node, ret, val);
  659.                 xmlFree(val);
  660.     }
  661. } else {
  662.     ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
  663.        ctxt->node, ret, value);
  664. }
  665.     } else {
  666.         /*
  667.  * when validating, the ID registration is done at the attribute
  668.  * validation level. Otherwise we have to do specific handling here.
  669.  */
  670. if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
  671.     xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
  672. else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
  673.     xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
  674.     }
  675.     if (nval != NULL)
  676. xmlFree(nval);
  677.     if (name != NULL) 
  678. xmlFree(name);
  679.     if (ns != NULL) 
  680. xmlFree(ns);
  681. }
  682. /**
  683.  * startElement:
  684.  * @ctx: the user data (XML parser context)
  685.  * @name:  The element name
  686.  * @atts:  An array of name/value attributes pairs, NULL terminated
  687.  *
  688.  * called when an opening tag has been processed.
  689.  */
  690. void
  691. startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
  692. {
  693.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  694.     xmlNodePtr ret;
  695.     xmlNodePtr parent = ctxt->node;
  696.     xmlNsPtr ns;
  697.     xmlChar *name;
  698.     xmlChar *prefix;
  699.     const xmlChar *att;
  700.     const xmlChar *value;
  701.     int i;
  702. #ifdef DEBUG_SAX
  703.     fprintf(stderr, "SAX.startElement(%s)n", fullname);
  704. #endif
  705.     /*
  706.      * First check on validity:
  707.      */
  708.     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 
  709.         ((ctxt->myDoc->intSubset == NULL) ||
  710.  ((ctxt->myDoc->intSubset->notations == NULL) && 
  711.   (ctxt->myDoc->intSubset->elements == NULL) &&
  712.   (ctxt->myDoc->intSubset->attributes == NULL) && 
  713.   (ctxt->myDoc->intSubset->entities == NULL)))) {
  714. if (ctxt->vctxt.error != NULL) {
  715.             ctxt->vctxt.error(ctxt->vctxt.userData,
  716.       "Validation failed: no DTD found !n");
  717. }
  718. ctxt->validate = 0;
  719.     }
  720.        
  721.     /*
  722.      * Split the full name into a namespace prefix and the tag name
  723.      */
  724.     name = xmlSplitQName(ctxt, fullname, &prefix);
  725.     /*
  726.      * Note : the namespace resolution is deferred until the end of the
  727.      *        attributes parsing, since local namespace can be defined as
  728.      *        an attribute at this level.
  729.      */
  730.     ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
  731.     if (ret == NULL) return;
  732.     if (ctxt->myDoc->children == NULL) {
  733. #ifdef DEBUG_SAX_TREE
  734. fprintf(stderr, "Setting %s as rootn", name);
  735. #endif
  736.         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
  737.     } else if (parent == NULL) {
  738.         parent = ctxt->myDoc->children;
  739.     }
  740.     /*
  741.      * We are parsing a new node.
  742.      */
  743. #ifdef DEBUG_SAX_TREE
  744.     fprintf(stderr, "pushing(%s)n", name);
  745. #endif
  746.     nodePush(ctxt, ret);
  747.     /*
  748.      * Link the child element
  749.      */
  750.     if (parent != NULL) {
  751.         if (parent->type == XML_ELEMENT_NODE) {
  752. #ifdef DEBUG_SAX_TREE
  753.     fprintf(stderr, "adding child %s to %sn", name, parent->name);
  754. #endif
  755.     xmlAddChild(parent, ret);
  756. } else {
  757. #ifdef DEBUG_SAX_TREE
  758.     fprintf(stderr, "adding sibling %s to ", name);
  759.     xmlDebugDumpOneNode(stderr, parent, 0);
  760. #endif
  761.     xmlAddSibling(parent, ret);
  762. }
  763.     }
  764.     /*
  765.      * If it's the Document root, finish the Dtd validation and
  766.      * check the document root element for validity
  767.      */
  768.     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
  769. ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
  770. ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
  771. ctxt->vctxt.finishDtd = 1;
  772.     }
  773.     /*
  774.      * process all the attributes whose name start with "xml"
  775.      */
  776.     if (atts != NULL) {
  777.         i = 0;
  778. att = atts[i++];
  779. value = atts[i++];
  780.         while ((att != NULL) && (value != NULL)) {
  781.     if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
  782. attribute(ctxt, att, value);
  783.     att = atts[i++];
  784.     value = atts[i++];
  785. }
  786.     }
  787.     /*
  788.      * process all the other attributes
  789.      */
  790.     if (atts != NULL) {
  791.         i = 0;
  792. att = atts[i++];
  793. value = atts[i++];
  794.         while ((att != NULL) && (value != NULL)) {
  795.     if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
  796. attribute(ctxt, att, value);
  797.     /*
  798.      * Next ones
  799.      */
  800.     att = atts[i++];
  801.     value = atts[i++];
  802. }
  803.     }
  804.     /*
  805.      * Search the namespace, note that since the attributes have been
  806.      * processed, the local namespaces are available.
  807.      */
  808.     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
  809.     if ((ns == NULL) && (parent != NULL))
  810. ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
  811.     xmlSetNs(ret, ns);
  812.     if (prefix != NULL)
  813. xmlFree(prefix);
  814.     if (name != NULL)
  815. xmlFree(name);
  816. }
  817. /**
  818.  * endElement:
  819.  * @ctx: the user data (XML parser context)
  820.  * @name:  The element name
  821.  *
  822.  * called when the end of an element has been detected.
  823.  */
  824. void
  825. endElement(void *ctx, const xmlChar *name)
  826. {
  827.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  828.     xmlParserNodeInfo node_info;
  829.     xmlNodePtr cur = ctxt->node;
  830. #ifdef DEBUG_SAX
  831.     if (name == NULL)
  832.         fprintf(stderr, "SAX.endElement(NULL)n");
  833.     else
  834. fprintf(stderr, "SAX.endElement(%s)n", name);
  835. #endif
  836.     
  837.     /* Capture end position and add node */
  838.     if (cur != NULL && ctxt->record_info) {
  839.       node_info.end_pos = ctxt->input->cur - ctxt->input->base;
  840.       node_info.end_line = ctxt->input->line;
  841.       node_info.node = cur;
  842.       xmlParserAddNodeInfo(ctxt, &node_info);
  843.     }
  844.     if (ctxt->validate && ctxt->wellFormed &&
  845.         ctxt->myDoc && ctxt->myDoc->intSubset)
  846.         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
  847.      cur);
  848.     
  849.     /*
  850.      * end of parsing of this node.
  851.      */
  852. #ifdef DEBUG_SAX_TREE
  853.     fprintf(stderr, "popping(%s)n", cur->name);
  854. #endif
  855.     nodePop(ctxt);
  856. }
  857. /**
  858.  * reference:
  859.  * @ctx: the user data (XML parser context)
  860.  * @name:  The entity name
  861.  *
  862.  * called when an entity reference is detected. 
  863.  */
  864. void
  865. reference(void *ctx, const xmlChar *name)
  866. {
  867.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  868.     xmlNodePtr ret;
  869. #ifdef DEBUG_SAX
  870.     fprintf(stderr, "SAX.reference(%s)n", name);
  871. #endif
  872.     if (name[0] == '#')
  873. ret = xmlNewCharRef(ctxt->myDoc, name);
  874.     else
  875. ret = xmlNewReference(ctxt->myDoc, name);
  876. #ifdef DEBUG_SAX_TREE
  877.     fprintf(stderr, "add reference %s to %s n", name, ctxt->node->name);
  878. #endif
  879.     xmlAddChild(ctxt->node, ret);
  880. }
  881. /**
  882.  * characters:
  883.  * @ctx: the user data (XML parser context)
  884.  * @ch:  a xmlChar string
  885.  * @len: the number of xmlChar
  886.  *
  887.  * receiving some chars from the parser.
  888.  * Question: how much at a time ???
  889.  */
  890. void
  891. characters(void *ctx, const xmlChar *ch, int len)
  892. {
  893.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  894.     xmlNodePtr lastChild;
  895. #ifdef DEBUG_SAX
  896.     fprintf(stderr, "SAX.characters(%.30s, %d)n", ch, len);
  897. #endif
  898.     /*
  899.      * Handle the data if any. If there is no child
  900.      * add it as content, otherwise if the last child is text,
  901.      * concatenate it, else create a new node of type text.
  902.      */
  903.     if (ctxt->node == NULL) {
  904. #ifdef DEBUG_SAX_TREE
  905. fprintf(stderr, "add chars: ctxt->node == NULL !n");
  906. #endif
  907.         return;
  908.     }
  909.     lastChild = xmlGetLastChild(ctxt->node);
  910. #ifdef DEBUG_SAX_TREE
  911.     fprintf(stderr, "add chars to %s n", ctxt->node->name);
  912. #endif
  913.     if (lastChild == NULL)
  914. xmlNodeAddContentLen(ctxt->node, ch, len);
  915.     else {
  916. if (xmlNodeIsText(lastChild))
  917.     xmlTextConcat(lastChild, ch, len);
  918. else {
  919.     lastChild = xmlNewTextLen(ch, len);
  920.     xmlAddChild(ctxt->node, lastChild);
  921. }
  922.     }
  923. }
  924. /**
  925.  * ignorableWhitespace:
  926.  * @ctx: the user data (XML parser context)
  927.  * @ch:  a xmlChar string
  928.  * @len: the number of xmlChar
  929.  *
  930.  * receiving some ignorable whitespaces from the parser.
  931.  * Question: how much at a time ???
  932.  */
  933. void
  934. ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
  935. {
  936.     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  937. #ifdef DEBUG_SAX
  938.     fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)n", ch, len);
  939. #endif
  940. }
  941. /**
  942.  * processingInstruction:
  943.  * @ctx: the user data (XML parser context)
  944.  * @target:  the target name
  945.  * @data: the PI data's
  946.  * @len: the number of xmlChar
  947.  *
  948.  * A processing instruction has been parsed.
  949.  */
  950. void
  951. processingInstruction(void *ctx, const xmlChar *target,
  952.                       const xmlChar *data)
  953. {
  954.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  955.     xmlNodePtr ret;
  956.     xmlNodePtr parent = ctxt->node;
  957. #ifdef DEBUG_SAX
  958.     fprintf(stderr, "SAX.processingInstruction(%s, %s)n", target, data);
  959. #endif
  960.     ret = xmlNewPI(target, data);
  961.     if (ret == NULL) return;
  962.     parent = ctxt->node;
  963.     if (ctxt->inSubset == 1) {
  964. xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
  965. return;
  966.     } else if (ctxt->inSubset == 2) {
  967. xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
  968. return;
  969.     }
  970.     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
  971. #ifdef DEBUG_SAX_TREE
  972.     fprintf(stderr, "Setting PI %s as rootn", target);
  973. #endif
  974.         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
  975. return;
  976.     }
  977.     if (parent->type == XML_ELEMENT_NODE) {
  978. #ifdef DEBUG_SAX_TREE
  979. fprintf(stderr, "adding PI %s child to %sn", target, parent->name);
  980. #endif
  981. xmlAddChild(parent, ret);
  982.     } else {
  983. #ifdef DEBUG_SAX_TREE
  984. fprintf(stderr, "adding PI %s sibling to ", target);
  985. xmlDebugDumpOneNode(stderr, parent, 0);
  986. #endif
  987. xmlAddSibling(parent, ret);
  988.     }
  989. }
  990. /**
  991.  * globalNamespace:
  992.  * @ctx: the user data (XML parser context)
  993.  * @href:  the namespace associated URN
  994.  * @prefix: the namespace prefix
  995.  *
  996.  * An old global namespace has been parsed.
  997.  */
  998. void
  999. globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
  1000. {
  1001.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1002. #ifdef DEBUG_SAX
  1003.     fprintf(stderr, "SAX.globalNamespace(%s, %s)n", href, prefix);
  1004. #endif
  1005.     xmlNewGlobalNs(ctxt->myDoc, href, prefix);
  1006. }
  1007. /**
  1008.  * setNamespace:
  1009.  * @ctx: the user data (XML parser context)
  1010.  * @name:  the namespace prefix
  1011.  *
  1012.  * Set the current element namespace.
  1013.  */
  1014. void
  1015. setNamespace(void *ctx, const xmlChar *name)
  1016. {
  1017.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1018.     xmlNsPtr ns;
  1019.     xmlNodePtr parent;
  1020. #ifdef DEBUG_SAX
  1021.     fprintf(stderr, "SAX.setNamespace(%s)n", name);
  1022. #endif
  1023.     ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
  1024.     if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
  1025.         if (ctxt->nodeNr >= 2) {
  1026.     parent = ctxt->nodeTab[ctxt->nodeNr - 2];
  1027.     if (parent != NULL)
  1028. ns = xmlSearchNs(ctxt->myDoc, parent, name);
  1029. }
  1030.     }
  1031.     xmlSetNs(ctxt->node, ns);
  1032. }
  1033. /**
  1034.  * getNamespace:
  1035.  * @ctx: the user data (XML parser context)
  1036.  *
  1037.  * Get the current element namespace.
  1038.  */
  1039. xmlNsPtr
  1040. getNamespace(void *ctx)
  1041. {
  1042.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1043.     xmlNsPtr ret;
  1044. #ifdef DEBUG_SAX
  1045.     fprintf(stderr, "SAX.getNamespace()n");
  1046. #endif
  1047.     ret = ctxt->node->ns;
  1048.     return(ret);
  1049. }
  1050. /**
  1051.  * checkNamespace:
  1052.  * @ctx: the user data (XML parser context)
  1053.  * @namespace: the namespace to check against
  1054.  *
  1055.  * Check that the current element namespace is the same as the
  1056.  * one read upon parsing.
  1057.  */
  1058. int
  1059. checkNamespace(void *ctx, xmlChar *namespace)
  1060. {
  1061.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1062.     xmlNodePtr cur = ctxt->node;
  1063. #ifdef DEBUG_SAX
  1064.     fprintf(stderr, "SAX.checkNamespace(%s)n", namespace);
  1065. #endif
  1066.     /*
  1067.      * Check that the Name in the ETag is the same as in the STag.
  1068.      */
  1069.     if (namespace == NULL) {
  1070.         if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
  1071.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1072. ctxt->sax->error(ctxt, 
  1073.  "End tags for %s don't hold the namespace %sn",
  1074.                  cur->name, cur->ns->prefix);
  1075.     ctxt->wellFormed = 0;
  1076. }
  1077.     } else {
  1078.         if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
  1079.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1080. ctxt->sax->error(ctxt, 
  1081.  "End tags %s holds a prefix %s not used by the open tagn",
  1082.                  cur->name, namespace);
  1083.     ctxt->wellFormed = 0;
  1084. } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
  1085.     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
  1086. ctxt->sax->error(ctxt, 
  1087.     "Start and End tags for %s don't use the same namespaces: %s and %sn",
  1088.                          cur->name, cur->ns->prefix, namespace);
  1089.     ctxt->wellFormed = 0;
  1090. } else
  1091.     return(1);
  1092.     }
  1093.     return(0);
  1094. }
  1095. /**
  1096.  * namespaceDecl:
  1097.  * @ctx: the user data (XML parser context)
  1098.  * @href:  the namespace associated URN
  1099.  * @prefix: the namespace prefix
  1100.  *
  1101.  * A namespace has been parsed.
  1102.  */
  1103. void
  1104. namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
  1105. {
  1106.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1107. #ifdef DEBUG_SAX
  1108.     if (prefix == NULL)
  1109. fprintf(stderr, "SAX.namespaceDecl(%s, NULL)n", href);
  1110.     else
  1111. fprintf(stderr, "SAX.namespaceDecl(%s, %s)n", href, prefix);
  1112. #endif
  1113.     xmlNewNs(ctxt->node, href, prefix);
  1114. }
  1115. /**
  1116.  * comment:
  1117.  * @ctx: the user data (XML parser context)
  1118.  * @value:  the comment content
  1119.  *
  1120.  * A comment has been parsed.
  1121.  */
  1122. void
  1123. comment(void *ctx, const xmlChar *value)
  1124. {
  1125.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1126.     xmlNodePtr ret;
  1127.     xmlNodePtr parent = ctxt->node;
  1128. #ifdef DEBUG_SAX
  1129.     fprintf(stderr, "SAX.comment(%s)n", value);
  1130. #endif
  1131.     ret = xmlNewDocComment(ctxt->myDoc, value);
  1132.     if (ret == NULL) return;
  1133.     if (ctxt->inSubset == 1) {
  1134. xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
  1135. return;
  1136.     } else if (ctxt->inSubset == 2) {
  1137. xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
  1138. return;
  1139.     }
  1140.     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
  1141. #ifdef DEBUG_SAX_TREE
  1142.     fprintf(stderr, "Setting comment as rootn");
  1143. #endif
  1144.         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
  1145. return;
  1146.     }
  1147.     if (parent->type == XML_ELEMENT_NODE) {
  1148. #ifdef DEBUG_SAX_TREE
  1149. fprintf(stderr, "adding comment child to %sn", parent->name);
  1150. #endif
  1151. xmlAddChild(parent, ret);
  1152.     } else {
  1153. #ifdef DEBUG_SAX_TREE
  1154. fprintf(stderr, "adding comment sibling to ");
  1155. xmlDebugDumpOneNode(stderr, parent, 0);
  1156. #endif
  1157. xmlAddSibling(parent, ret);
  1158.     }
  1159. }
  1160. /**
  1161.  * cdataBlock:
  1162.  * @ctx: the user data (XML parser context)
  1163.  * @value:  The pcdata content
  1164.  * @len:  the block length
  1165.  *
  1166.  * called when a pcdata block has been parsed
  1167.  */
  1168. void
  1169. cdataBlock(void *ctx, const xmlChar *value, int len)
  1170. {
  1171.     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
  1172.     xmlNodePtr ret, lastChild;
  1173. #ifdef DEBUG_SAX
  1174.     fprintf(stderr, "SAX.pcdata(%.10s, %d)n", value, len);
  1175. #endif
  1176.     lastChild = xmlGetLastChild(ctxt->node);
  1177. #ifdef DEBUG_SAX_TREE
  1178.     fprintf(stderr, "add chars to %s n", ctxt->node->name);
  1179. #endif
  1180.     if ((lastChild != NULL) &&
  1181.         (lastChild->type == XML_CDATA_SECTION_NODE)) {
  1182. xmlTextConcat(lastChild, value, len);
  1183.     } else {
  1184. ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
  1185. xmlAddChild(ctxt->node, ret);
  1186.     }
  1187. }
  1188. /*
  1189.  * Default handler for XML, builds the DOM tree
  1190.  */
  1191. xmlSAXHandler xmlDefaultSAXHandler = {
  1192.     internalSubset,
  1193.     isStandalone,
  1194.     hasInternalSubset,
  1195.     hasExternalSubset,
  1196.     resolveEntity,
  1197.     getEntity,
  1198.     entityDecl,
  1199.     notationDecl,
  1200.     attributeDecl,
  1201.     elementDecl,
  1202.     unparsedEntityDecl,
  1203.     setDocumentLocator,
  1204.     startDocument,
  1205.     endDocument,
  1206.     startElement,
  1207.     endElement,
  1208.     reference,
  1209.     characters,
  1210.     ignorableWhitespace,
  1211.     processingInstruction,
  1212.     comment,
  1213.     xmlParserWarning,
  1214.     xmlParserError,
  1215.     xmlParserError,
  1216.     getParameterEntity,
  1217.     cdataBlock,
  1218.     externalSubset,
  1219. };
  1220. /**
  1221.  * xmlDefaultSAXHandlerInit:
  1222.  *
  1223.  * Initialize the default SAX handler
  1224.  */
  1225. void
  1226. xmlDefaultSAXHandlerInit(void)
  1227. {
  1228.     xmlDefaultSAXHandler.internalSubset = internalSubset;
  1229.     xmlDefaultSAXHandler.externalSubset = externalSubset;
  1230.     xmlDefaultSAXHandler.isStandalone = isStandalone;
  1231.     xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
  1232.     xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
  1233.     xmlDefaultSAXHandler.resolveEntity = resolveEntity;
  1234.     xmlDefaultSAXHandler.getEntity = getEntity;
  1235.     xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
  1236.     xmlDefaultSAXHandler.entityDecl = entityDecl;
  1237.     xmlDefaultSAXHandler.attributeDecl = attributeDecl;
  1238.     xmlDefaultSAXHandler.elementDecl = elementDecl;
  1239.     xmlDefaultSAXHandler.notationDecl = notationDecl;
  1240.     xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
  1241.     xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
  1242.     xmlDefaultSAXHandler.startDocument = startDocument;
  1243.     xmlDefaultSAXHandler.endDocument = endDocument;
  1244.     xmlDefaultSAXHandler.startElement = startElement;
  1245.     xmlDefaultSAXHandler.endElement = endElement;
  1246.     xmlDefaultSAXHandler.reference = reference;
  1247.     xmlDefaultSAXHandler.characters = characters;
  1248.     xmlDefaultSAXHandler.cdataBlock = cdataBlock;
  1249.     xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
  1250.     xmlDefaultSAXHandler.processingInstruction = processingInstruction;
  1251.     xmlDefaultSAXHandler.comment = comment;
  1252.     if (xmlGetWarningsDefaultValue == 0)
  1253. xmlDefaultSAXHandler.warning = NULL;
  1254.     else
  1255. xmlDefaultSAXHandler.warning = xmlParserWarning;
  1256.     xmlDefaultSAXHandler.error = xmlParserError;
  1257.     xmlDefaultSAXHandler.fatalError = xmlParserError;
  1258. }
  1259. /*
  1260.  * Default handler for HTML, builds the DOM tree
  1261.  */
  1262. xmlSAXHandler htmlDefaultSAXHandler = {
  1263.     NULL,
  1264.     NULL,
  1265.     NULL,
  1266.     NULL,
  1267.     NULL,
  1268.     getEntity,
  1269.     NULL,
  1270.     NULL,
  1271.     NULL,
  1272.     NULL,
  1273.     NULL,
  1274.     setDocumentLocator,
  1275.     startDocument,
  1276.     endDocument,
  1277.     startElement,
  1278.     endElement,
  1279.     NULL,
  1280.     characters,
  1281.     ignorableWhitespace,
  1282.     NULL,
  1283.     comment,
  1284.     xmlParserWarning,
  1285.     xmlParserError,
  1286.     xmlParserError,
  1287.     getParameterEntity,
  1288.     NULL,
  1289.     NULL,
  1290. };
  1291. /**
  1292.  * htmlDefaultSAXHandlerInit:
  1293.  *
  1294.  * Initialize the default SAX handler
  1295.  */
  1296. void
  1297. htmlDefaultSAXHandlerInit(void)
  1298. {
  1299.     htmlDefaultSAXHandler.internalSubset = NULL;
  1300.     htmlDefaultSAXHandler.externalSubset = NULL;
  1301.     htmlDefaultSAXHandler.isStandalone = NULL;
  1302.     htmlDefaultSAXHandler.hasInternalSubset = NULL;
  1303.     htmlDefaultSAXHandler.hasExternalSubset = NULL;
  1304.     htmlDefaultSAXHandler.resolveEntity = NULL;
  1305.     htmlDefaultSAXHandler.getEntity = getEntity;
  1306.     htmlDefaultSAXHandler.getParameterEntity = NULL;
  1307.     htmlDefaultSAXHandler.entityDecl = NULL;
  1308.     htmlDefaultSAXHandler.attributeDecl = NULL;
  1309.     htmlDefaultSAXHandler.elementDecl = NULL;
  1310.     htmlDefaultSAXHandler.notationDecl = NULL;
  1311.     htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
  1312.     htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
  1313.     htmlDefaultSAXHandler.startDocument = startDocument;
  1314.     htmlDefaultSAXHandler.endDocument = endDocument;
  1315.     htmlDefaultSAXHandler.startElement = startElement;
  1316.     htmlDefaultSAXHandler.endElement = endElement;
  1317.     htmlDefaultSAXHandler.reference = NULL;
  1318.     htmlDefaultSAXHandler.characters = characters;
  1319.     htmlDefaultSAXHandler.cdataBlock = NULL;
  1320.     htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
  1321.     htmlDefaultSAXHandler.processingInstruction = NULL;
  1322.     htmlDefaultSAXHandler.comment = comment;
  1323.     htmlDefaultSAXHandler.warning = xmlParserWarning;
  1324.     htmlDefaultSAXHandler.error = xmlParserError;
  1325.     htmlDefaultSAXHandler.fatalError = xmlParserError;
  1326. }