Paul Cercueil / libxml2

Dependents:   libiio

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SAX2.c Source File

SAX2.c

00001 /*
00002  * SAX2.c : Default SAX2 handler to build a tree.
00003  *
00004  * See Copyright for the status of this software.
00005  *
00006  * Daniel Veillard <daniel@veillard.com>
00007  */
00008 
00009 
00010 #define IN_LIBXML
00011 #include "libxml.h"
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <limits.h>
00015 #include <libxml/xmlmemory.h>
00016 #include <libxml/tree.h>
00017 #include <libxml/parser.h>
00018 #include <libxml/parserInternals.h>
00019 #include <libxml/valid.h>
00020 #include <libxml/entities.h>
00021 #include <libxml/xmlerror.h>
00022 #include <libxml/debugXML.h>
00023 #include <libxml/xmlIO.h>
00024 #include <libxml/SAX.h>
00025 #include <libxml/uri.h>
00026 #include <libxml/valid.h>
00027 #include <libxml/HTMLtree.h>
00028 #include <libxml/globals.h>
00029 
00030 /* Define SIZE_T_MAX unless defined through <limits.h>. */
00031 #ifndef SIZE_T_MAX
00032 # define SIZE_T_MAX     ((size_t)-1)
00033 #endif /* !SIZE_T_MAX */
00034 
00035 /* #define DEBUG_SAX2 */
00036 /* #define DEBUG_SAX2_TREE */
00037 
00038 /**
00039  * TODO:
00040  *
00041  * macro to flag unimplemented blocks
00042  * XML_CATALOG_PREFER user env to select between system/public prefered
00043  * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
00044  *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
00045  *> values "system" and "public".  I have made the default be "system" to
00046  *> match yours.
00047  */
00048 #define TODO                                \
00049     xmlGenericError(xmlGenericErrorContext,             \
00050         "Unimplemented block at %s:%d\n",               \
00051             __FILE__, __LINE__);
00052 
00053 /*
00054  * xmlSAX2ErrMemory:
00055  * @ctxt:  an XML validation parser context
00056  * @msg:   a string to accompany the error message
00057  */
00058 static void
00059 xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
00060     xmlStructuredErrorFunc schannel = NULL;
00061     const char *str1 = "out of memory\n";
00062 
00063     if (ctxt != NULL) {
00064     ctxt->errNo = XML_ERR_NO_MEMORY;
00065     if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
00066         schannel = ctxt->sax->serror;
00067     __xmlRaiseError(schannel,
00068             ctxt->vctxt.error, ctxt->vctxt.userData,
00069             ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
00070             XML_ERR_ERROR, NULL, 0, (const char *) str1,
00071             NULL, NULL, 0, 0,
00072             msg, (const char *) str1, NULL);
00073     ctxt->errNo = XML_ERR_NO_MEMORY;
00074     ctxt->instate = XML_PARSER_EOF;
00075     ctxt->disableSAX = 1;
00076     } else {
00077     __xmlRaiseError(schannel,
00078             NULL, NULL,
00079             ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
00080             XML_ERR_ERROR, NULL, 0, (const char *) str1,
00081             NULL, NULL, 0, 0,
00082             msg, (const char *) str1, NULL);
00083     }
00084 }
00085 
00086 /**
00087  * xmlValidError:
00088  * @ctxt:  an XML validation parser context
00089  * @error:  the error number
00090  * @msg:  the error message
00091  * @str1:  extra data
00092  * @str2:  extra data
00093  *
00094  * Handle a validation error
00095  */
00096 static void
00097 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00098             const char *msg, const char *str1, const char *str2)
00099 {
00100     xmlStructuredErrorFunc schannel = NULL;
00101 
00102     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00103         (ctxt->instate == XML_PARSER_EOF))
00104     return;
00105     if (ctxt != NULL) {
00106     ctxt->errNo = error;
00107     if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
00108         schannel = ctxt->sax->serror;
00109     __xmlRaiseError(schannel,
00110             ctxt->vctxt.error, ctxt->vctxt.userData,
00111             ctxt, NULL, XML_FROM_DTD, error,
00112             XML_ERR_ERROR, NULL, 0, (const char *) str1,
00113             (const char *) str2, NULL, 0, 0,
00114             msg, (const char *) str1, (const char *) str2);
00115     ctxt->valid = 0;
00116     } else {
00117     __xmlRaiseError(schannel,
00118             NULL, NULL,
00119             ctxt, NULL, XML_FROM_DTD, error,
00120             XML_ERR_ERROR, NULL, 0, (const char *) str1,
00121             (const char *) str2, NULL, 0, 0,
00122             msg, (const char *) str1, (const char *) str2);
00123     }
00124 }
00125 
00126 /**
00127  * xmlFatalErrMsg:
00128  * @ctxt:  an XML parser context
00129  * @error:  the error number
00130  * @msg:  the error message
00131  * @str1:  an error string
00132  * @str2:  an error string
00133  *
00134  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
00135  */
00136 static void
00137 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00138                const char *msg, const xmlChar *str1, const xmlChar *str2)
00139 {
00140     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00141         (ctxt->instate == XML_PARSER_EOF))
00142     return;
00143     if (ctxt != NULL)
00144     ctxt->errNo = error;
00145     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
00146                     XML_ERR_FATAL, NULL, 0,
00147             (const char *) str1, (const char *) str2,
00148             NULL, 0, 0, msg, str1, str2);
00149     if (ctxt != NULL) {
00150     ctxt->wellFormed = 0;
00151     ctxt->valid = 0;
00152     if (ctxt->recovery == 0)
00153         ctxt->disableSAX = 1;
00154     }
00155 }
00156 
00157 /**
00158  * xmlWarnMsg:
00159  * @ctxt:  an XML parser context
00160  * @error:  the error number
00161  * @msg:  the error message
00162  * @str1:  an error string
00163  * @str2:  an error string
00164  *
00165  * Handle a parser warning
00166  */
00167 static void
00168 xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00169                const char *msg, const xmlChar *str1)
00170 {
00171     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00172         (ctxt->instate == XML_PARSER_EOF))
00173     return;
00174     if (ctxt != NULL)
00175     ctxt->errNo = error;
00176     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
00177                     XML_ERR_WARNING, NULL, 0,
00178             (const char *) str1, NULL,
00179             NULL, 0, 0, msg, str1);
00180 }
00181 
00182 /**
00183  * xmlNsErrMsg:
00184  * @ctxt:  an XML parser context
00185  * @error:  the error number
00186  * @msg:  the error message
00187  * @str1:  an error string
00188  * @str2:  an error string
00189  *
00190  * Handle a namespace error
00191  */
00192 static void
00193 xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00194             const char *msg, const xmlChar *str1, const xmlChar *str2)
00195 {
00196     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00197         (ctxt->instate == XML_PARSER_EOF))
00198     return;
00199     if (ctxt != NULL)
00200     ctxt->errNo = error;
00201     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
00202                     XML_ERR_ERROR, NULL, 0,
00203             (const char *) str1, (const char *) str2,
00204             NULL, 0, 0, msg, str1, str2);
00205 }
00206 
00207 /**
00208  * xmlNsWarnMsg:
00209  * @ctxt:  an XML parser context
00210  * @error:  the error number
00211  * @msg:  the error message
00212  * @str1:  an error string
00213  *
00214  * Handle a namespace warning
00215  */
00216 static void
00217 xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00218              const char *msg, const xmlChar *str1, const xmlChar *str2)
00219 {
00220     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00221         (ctxt->instate == XML_PARSER_EOF))
00222     return;
00223     if (ctxt != NULL)
00224     ctxt->errNo = error;
00225     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
00226                     XML_ERR_WARNING, NULL, 0,
00227             (const char *) str1, (const char *) str2,
00228             NULL, 0, 0, msg, str1, str2);
00229 }
00230 
00231 /**
00232  * xmlSAX2GetPublicId:
00233  * @ctx: the user data (XML parser context)
00234  *
00235  * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
00236  *
00237  * Returns a xmlChar *
00238  */
00239 const xmlChar *
00240 xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
00241 {
00242     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
00243     return(NULL);
00244 }
00245 
00246 /**
00247  * xmlSAX2GetSystemId:
00248  * @ctx: the user data (XML parser context)
00249  *
00250  * Provides the system ID, basically URL or filename e.g.
00251  * http://www.sgmlsource.com/dtds/memo.dtd
00252  *
00253  * Returns a xmlChar *
00254  */
00255 const xmlChar *
00256 xmlSAX2GetSystemId(void *ctx)
00257 {
00258     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00259     if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
00260     return((const xmlChar *) ctxt->input->filename);
00261 }
00262 
00263 /**
00264  * xmlSAX2GetLineNumber:
00265  * @ctx: the user data (XML parser context)
00266  *
00267  * Provide the line number of the current parsing point.
00268  *
00269  * Returns an int
00270  */
00271 int
00272 xmlSAX2GetLineNumber(void *ctx)
00273 {
00274     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00275     if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
00276     return(ctxt->input->line);
00277 }
00278 
00279 /**
00280  * xmlSAX2GetColumnNumber:
00281  * @ctx: the user data (XML parser context)
00282  *
00283  * Provide the column number of the current parsing point.
00284  *
00285  * Returns an int
00286  */
00287 int
00288 xmlSAX2GetColumnNumber(void *ctx)
00289 {
00290     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00291     if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
00292     return(ctxt->input->col);
00293 }
00294 
00295 /**
00296  * xmlSAX2IsStandalone:
00297  * @ctx: the user data (XML parser context)
00298  *
00299  * Is this document tagged standalone ?
00300  *
00301  * Returns 1 if true
00302  */
00303 int
00304 xmlSAX2IsStandalone(void *ctx)
00305 {
00306     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00307     if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
00308     return(ctxt->myDoc->standalone == 1);
00309 }
00310 
00311 /**
00312  * xmlSAX2HasInternalSubset:
00313  * @ctx: the user data (XML parser context)
00314  *
00315  * Does this document has an internal subset
00316  *
00317  * Returns 1 if true
00318  */
00319 int
00320 xmlSAX2HasInternalSubset(void *ctx)
00321 {
00322     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00323     if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
00324     return(ctxt->myDoc->intSubset != NULL);
00325 }
00326 
00327 /**
00328  * xmlSAX2HasExternalSubset:
00329  * @ctx: the user data (XML parser context)
00330  *
00331  * Does this document has an external subset
00332  *
00333  * Returns 1 if true
00334  */
00335 int
00336 xmlSAX2HasExternalSubset(void *ctx)
00337 {
00338     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00339     if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
00340     return(ctxt->myDoc->extSubset != NULL);
00341 }
00342 
00343 /**
00344  * xmlSAX2InternalSubset:
00345  * @ctx:  the user data (XML parser context)
00346  * @name:  the root element name
00347  * @ExternalID:  the external ID
00348  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
00349  *
00350  * Callback on internal subset declaration.
00351  */
00352 void
00353 xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
00354            const xmlChar *ExternalID, const xmlChar *SystemID)
00355 {
00356     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00357     xmlDtdPtr dtd;
00358     if (ctx == NULL) return;
00359 #ifdef DEBUG_SAX
00360     xmlGenericError(xmlGenericErrorContext,
00361         "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
00362             name, ExternalID, SystemID);
00363 #endif
00364 
00365     if (ctxt->myDoc == NULL)
00366     return;
00367     dtd = xmlGetIntSubset(ctxt->myDoc);
00368     if (dtd != NULL) {
00369     if (ctxt->html)
00370         return;
00371     xmlUnlinkNode((xmlNodePtr) dtd);
00372     xmlFreeDtd(dtd);
00373     ctxt->myDoc->intSubset = NULL;
00374     }
00375     ctxt->myDoc->intSubset =
00376     xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
00377     if (ctxt->myDoc->intSubset == NULL)
00378         xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
00379 }
00380 
00381 /**
00382  * xmlSAX2ExternalSubset:
00383  * @ctx: the user data (XML parser context)
00384  * @name:  the root element name
00385  * @ExternalID:  the external ID
00386  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
00387  *
00388  * Callback on external subset declaration.
00389  */
00390 void
00391 xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
00392            const xmlChar *ExternalID, const xmlChar *SystemID)
00393 {
00394     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00395     if (ctx == NULL) return;
00396 #ifdef DEBUG_SAX
00397     xmlGenericError(xmlGenericErrorContext,
00398         "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
00399             name, ExternalID, SystemID);
00400 #endif
00401     if (((ExternalID != NULL) || (SystemID != NULL)) &&
00402         (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
00403      (ctxt->wellFormed && ctxt->myDoc))) {
00404     /*
00405      * Try to fetch and parse the external subset.
00406      */
00407     xmlParserInputPtr oldinput;
00408     int oldinputNr;
00409     int oldinputMax;
00410     xmlParserInputPtr *oldinputTab;
00411     xmlParserInputPtr input = NULL;
00412     xmlCharEncoding enc;
00413     int oldcharset;
00414     const xmlChar *oldencoding;
00415 
00416     /*
00417      * Ask the Entity resolver to load the damn thing
00418      */
00419     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
00420         input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
00421                                             SystemID);
00422     if (input == NULL) {
00423         return;
00424     }
00425 
00426     xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
00427 
00428     /*
00429      * make sure we won't destroy the main document context
00430      */
00431     oldinput = ctxt->input;
00432     oldinputNr = ctxt->inputNr;
00433     oldinputMax = ctxt->inputMax;
00434     oldinputTab = ctxt->inputTab;
00435     oldcharset = ctxt->charset;
00436     oldencoding = ctxt->encoding;
00437     ctxt->encoding = NULL;
00438 
00439     ctxt->inputTab = (xmlParserInputPtr *)
00440                      xmlMalloc(5 * sizeof(xmlParserInputPtr));
00441     if (ctxt->inputTab == NULL) {
00442         xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
00443         ctxt->input = oldinput;
00444         ctxt->inputNr = oldinputNr;
00445         ctxt->inputMax = oldinputMax;
00446         ctxt->inputTab = oldinputTab;
00447         ctxt->charset = oldcharset;
00448         ctxt->encoding = oldencoding;
00449         return;
00450     }
00451     ctxt->inputNr = 0;
00452     ctxt->inputMax = 5;
00453     ctxt->input = NULL;
00454     xmlPushInput(ctxt, input);
00455 
00456     /*
00457      * On the fly encoding conversion if needed
00458      */
00459     if (ctxt->input->length >= 4) {
00460         enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
00461         xmlSwitchEncoding(ctxt, enc);
00462     }
00463 
00464     if (input->filename == NULL)
00465         input->filename = (char *) xmlCanonicPath(SystemID);
00466     input->line = 1;
00467     input->col = 1;
00468     input->base = ctxt->input->cur;
00469     input->cur = ctxt->input->cur;
00470     input->free = NULL;
00471 
00472     /*
00473      * let's parse that entity knowing it's an external subset.
00474      */
00475     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
00476 
00477         /*
00478      * Free up the external entities
00479      */
00480 
00481     while (ctxt->inputNr > 1)
00482         xmlPopInput(ctxt);
00483     xmlFreeInputStream(ctxt->input);
00484         xmlFree(ctxt->inputTab);
00485 
00486     /*
00487      * Restore the parsing context of the main entity
00488      */
00489     ctxt->input = oldinput;
00490     ctxt->inputNr = oldinputNr;
00491     ctxt->inputMax = oldinputMax;
00492     ctxt->inputTab = oldinputTab;
00493     ctxt->charset = oldcharset;
00494     if ((ctxt->encoding != NULL) &&
00495         ((ctxt->dict == NULL) ||
00496          (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
00497         xmlFree((xmlChar *) ctxt->encoding);
00498     ctxt->encoding = oldencoding;
00499     /* ctxt->wellFormed = oldwellFormed; */
00500     }
00501 }
00502 
00503 /**
00504  * xmlSAX2ResolveEntity:
00505  * @ctx: the user data (XML parser context)
00506  * @publicId: The public ID of the entity
00507  * @systemId: The system ID of the entity
00508  *
00509  * The entity loader, to control the loading of external entities,
00510  * the application can either:
00511  *    - override this xmlSAX2ResolveEntity() callback in the SAX block
00512  *    - or better use the xmlSetExternalEntityLoader() function to
00513  *      set up it's own entity resolution routine
00514  *
00515  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
00516  */
00517 xmlParserInputPtr
00518 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
00519 {
00520     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00521     xmlParserInputPtr ret;
00522     xmlChar *URI;
00523     const char *base = NULL;
00524 
00525     if (ctx == NULL) return(NULL);
00526     if (ctxt->input != NULL)
00527     base = ctxt->input->filename;
00528     if (base == NULL)
00529     base = ctxt->directory;
00530 
00531     URI = xmlBuildURI(systemId, (const xmlChar *) base);
00532 
00533 #ifdef DEBUG_SAX
00534     xmlGenericError(xmlGenericErrorContext,
00535         "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
00536 #endif
00537 
00538     ret = xmlLoadExternalEntity((const char *) URI,
00539                 (const char *) publicId, ctxt);
00540     if (URI != NULL)
00541     xmlFree(URI);
00542     return(ret);
00543 }
00544 
00545 /**
00546  * xmlSAX2GetEntity:
00547  * @ctx: the user data (XML parser context)
00548  * @name: The entity name
00549  *
00550  * Get an entity by name
00551  *
00552  * Returns the xmlEntityPtr if found.
00553  */
00554 xmlEntityPtr
00555 xmlSAX2GetEntity(void *ctx, const xmlChar *name)
00556 {
00557     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00558     xmlEntityPtr ret = NULL;
00559 
00560     if (ctx == NULL) return(NULL);
00561 #ifdef DEBUG_SAX
00562     xmlGenericError(xmlGenericErrorContext,
00563         "SAX.xmlSAX2GetEntity(%s)\n", name);
00564 #endif
00565 
00566     if (ctxt->inSubset == 0) {
00567     ret = xmlGetPredefinedEntity(name);
00568     if (ret != NULL)
00569         return(ret);
00570     }
00571     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
00572     if (ctxt->inSubset == 2) {
00573         ctxt->myDoc->standalone = 0;
00574         ret = xmlGetDocEntity(ctxt->myDoc, name);
00575         ctxt->myDoc->standalone = 1;
00576     } else {
00577         ret = xmlGetDocEntity(ctxt->myDoc, name);
00578         if (ret == NULL) {
00579         ctxt->myDoc->standalone = 0;
00580         ret = xmlGetDocEntity(ctxt->myDoc, name);
00581         if (ret != NULL) {
00582             xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
00583      "Entity(%s) document marked standalone but requires external subset\n",
00584                    name, NULL);
00585         }
00586         ctxt->myDoc->standalone = 1;
00587         }
00588     }
00589     } else {
00590     ret = xmlGetDocEntity(ctxt->myDoc, name);
00591     }
00592     if ((ret != NULL) &&
00593     ((ctxt->validate) || (ctxt->replaceEntities)) &&
00594     (ret->children == NULL) &&
00595     (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
00596     int val;
00597 
00598     /*
00599      * for validation purposes we really need to fetch and
00600      * parse the external entity
00601      */
00602     xmlNodePtr children;
00603     unsigned long oldnbent = ctxt->nbentities;
00604 
00605         val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
00606                                  ret->ExternalID, &children);
00607     if (val == 0) {
00608         xmlAddChildList((xmlNodePtr) ret, children);
00609     } else {
00610         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
00611                    "Failure to process entity %s\n", name, NULL);
00612         ctxt->validate = 0;
00613         return(NULL);
00614     }
00615     ret->owner = 1;
00616     if (ret->checked == 0) {
00617         ret->checked = (ctxt->nbentities - oldnbent + 1) * 2;
00618         if ((ret->content != NULL) && (xmlStrchr(ret->content, '<')))
00619             ret->checked |= 1;
00620     }
00621     }
00622     return(ret);
00623 }
00624 
00625 /**
00626  * xmlSAX2GetParameterEntity:
00627  * @ctx: the user data (XML parser context)
00628  * @name: The entity name
00629  *
00630  * Get a parameter entity by name
00631  *
00632  * Returns the xmlEntityPtr if found.
00633  */
00634 xmlEntityPtr
00635 xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
00636 {
00637     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00638     xmlEntityPtr ret;
00639 
00640     if (ctx == NULL) return(NULL);
00641 #ifdef DEBUG_SAX
00642     xmlGenericError(xmlGenericErrorContext,
00643         "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
00644 #endif
00645 
00646     ret = xmlGetParameterEntity(ctxt->myDoc, name);
00647     return(ret);
00648 }
00649 
00650 
00651 /**
00652  * xmlSAX2EntityDecl:
00653  * @ctx: the user data (XML parser context)
00654  * @name:  the entity name
00655  * @type:  the entity type
00656  * @publicId: The public ID of the entity
00657  * @systemId: The system ID of the entity
00658  * @content: the entity value (without processing).
00659  *
00660  * An entity definition has been parsed
00661  */
00662 void
00663 xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
00664           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
00665 {
00666     xmlEntityPtr ent;
00667     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00668 
00669     if (ctx == NULL) return;
00670 #ifdef DEBUG_SAX
00671     xmlGenericError(xmlGenericErrorContext,
00672         "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
00673             name, type, publicId, systemId, content);
00674 #endif
00675     if (ctxt->inSubset == 1) {
00676     ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
00677                       systemId, content);
00678     if ((ent == NULL) && (ctxt->pedantic))
00679         xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
00680          "Entity(%s) already defined in the internal subset\n",
00681                    name);
00682     if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
00683         xmlChar *URI;
00684         const char *base = NULL;
00685 
00686         if (ctxt->input != NULL)
00687         base = ctxt->input->filename;
00688         if (base == NULL)
00689         base = ctxt->directory;
00690 
00691         URI = xmlBuildURI(systemId, (const xmlChar *) base);
00692         ent->URI = URI;
00693     }
00694     } else if (ctxt->inSubset == 2) {
00695     ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
00696                       systemId, content);
00697     if ((ent == NULL) && (ctxt->pedantic) &&
00698         (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
00699         ctxt->sax->warning(ctxt->userData,
00700          "Entity(%s) already defined in the external subset\n", name);
00701     if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
00702         xmlChar *URI;
00703         const char *base = NULL;
00704 
00705         if (ctxt->input != NULL)
00706         base = ctxt->input->filename;
00707         if (base == NULL)
00708         base = ctxt->directory;
00709 
00710         URI = xmlBuildURI(systemId, (const xmlChar *) base);
00711         ent->URI = URI;
00712     }
00713     } else {
00714     xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
00715                    "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
00716                name, NULL);
00717     }
00718 }
00719 
00720 /**
00721  * xmlSAX2AttributeDecl:
00722  * @ctx: the user data (XML parser context)
00723  * @elem:  the name of the element
00724  * @fullname:  the attribute name
00725  * @type:  the attribute type
00726  * @def:  the type of default value
00727  * @defaultValue: the attribute default value
00728  * @tree:  the tree of enumerated value set
00729  *
00730  * An attribute definition has been parsed
00731  */
00732 void
00733 xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
00734               int type, int def, const xmlChar *defaultValue,
00735           xmlEnumerationPtr tree)
00736 {
00737     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00738     xmlAttributePtr attr;
00739     xmlChar *name = NULL, *prefix = NULL;
00740 
00741     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
00742         return;
00743 
00744 #ifdef DEBUG_SAX
00745     xmlGenericError(xmlGenericErrorContext,
00746         "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
00747             elem, fullname, type, def, defaultValue);
00748 #endif
00749     if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
00750         (type != XML_ATTRIBUTE_ID)) {
00751     /*
00752      * Raise the error but keep the validity flag
00753      */
00754     int tmp = ctxt->valid;
00755     xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
00756           "xml:id : attribute type should be ID\n", NULL, NULL);
00757     ctxt->valid = tmp;
00758     }
00759     /* TODO: optimize name/prefix allocation */
00760     name = xmlSplitQName(ctxt, fullname, &prefix);
00761     ctxt->vctxt.valid = 1;
00762     if (ctxt->inSubset == 1)
00763     attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
00764            name, prefix, (xmlAttributeType) type,
00765            (xmlAttributeDefault) def, defaultValue, tree);
00766     else if (ctxt->inSubset == 2)
00767     attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
00768        name, prefix, (xmlAttributeType) type,
00769        (xmlAttributeDefault) def, defaultValue, tree);
00770     else {
00771         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
00772          "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
00773                    name, NULL);
00774     xmlFreeEnumeration(tree);
00775     return;
00776     }
00777 #ifdef LIBXML_VALID_ENABLED
00778     if (ctxt->vctxt.valid == 0)
00779     ctxt->valid = 0;
00780     if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
00781         (ctxt->myDoc->intSubset != NULL))
00782     ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
00783                                             attr);
00784 #endif /* LIBXML_VALID_ENABLED */
00785     if (prefix != NULL)
00786     xmlFree(prefix);
00787     if (name != NULL)
00788     xmlFree(name);
00789 }
00790 
00791 /**
00792  * xmlSAX2ElementDecl:
00793  * @ctx: the user data (XML parser context)
00794  * @name:  the element name
00795  * @type:  the element type
00796  * @content: the element value tree
00797  *
00798  * An element definition has been parsed
00799  */
00800 void
00801 xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
00802             xmlElementContentPtr content)
00803 {
00804     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00805     xmlElementPtr elem = NULL;
00806 
00807     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
00808         return;
00809 
00810 #ifdef DEBUG_SAX
00811     xmlGenericError(xmlGenericErrorContext,
00812                     "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
00813 #endif
00814 
00815     if (ctxt->inSubset == 1)
00816         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
00817                                  name, (xmlElementTypeVal) type, content);
00818     else if (ctxt->inSubset == 2)
00819         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
00820                                  name, (xmlElementTypeVal) type, content);
00821     else {
00822         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
00823          "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
00824                    name, NULL);
00825         return;
00826     }
00827 #ifdef LIBXML_VALID_ENABLED
00828     if (elem == NULL)
00829         ctxt->valid = 0;
00830     if (ctxt->validate && ctxt->wellFormed &&
00831         ctxt->myDoc && ctxt->myDoc->intSubset)
00832         ctxt->valid &=
00833             xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
00834 #endif /* LIBXML_VALID_ENABLED */
00835 }
00836 
00837 /**
00838  * xmlSAX2NotationDecl:
00839  * @ctx: the user data (XML parser context)
00840  * @name: The name of the notation
00841  * @publicId: The public ID of the entity
00842  * @systemId: The system ID of the entity
00843  *
00844  * What to do when a notation declaration has been parsed.
00845  */
00846 void
00847 xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
00848          const xmlChar *publicId, const xmlChar *systemId)
00849 {
00850     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00851     xmlNotationPtr nota = NULL;
00852 
00853     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
00854         return;
00855 
00856 #ifdef DEBUG_SAX
00857     xmlGenericError(xmlGenericErrorContext,
00858         "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
00859 #endif
00860 
00861     if ((publicId == NULL) && (systemId == NULL)) {
00862     xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
00863          "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
00864                    name, NULL);
00865     return;
00866     } else if (ctxt->inSubset == 1)
00867     nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
00868                               publicId, systemId);
00869     else if (ctxt->inSubset == 2)
00870     nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
00871                               publicId, systemId);
00872     else {
00873     xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
00874          "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
00875                    name, NULL);
00876     return;
00877     }
00878 #ifdef LIBXML_VALID_ENABLED
00879     if (nota == NULL) ctxt->valid = 0;
00880     if ((ctxt->validate) && (ctxt->wellFormed) &&
00881         (ctxt->myDoc->intSubset != NULL))
00882     ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
00883                                            nota);
00884 #endif /* LIBXML_VALID_ENABLED */
00885 }
00886 
00887 /**
00888  * xmlSAX2UnparsedEntityDecl:
00889  * @ctx: the user data (XML parser context)
00890  * @name: The name of the entity
00891  * @publicId: The public ID of the entity
00892  * @systemId: The system ID of the entity
00893  * @notationName: the name of the notation
00894  *
00895  * What to do when an unparsed entity declaration is parsed
00896  */
00897 void
00898 xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
00899            const xmlChar *publicId, const xmlChar *systemId,
00900            const xmlChar *notationName)
00901 {
00902     xmlEntityPtr ent;
00903     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00904     if (ctx == NULL) return;
00905 #ifdef DEBUG_SAX
00906     xmlGenericError(xmlGenericErrorContext,
00907         "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
00908             name, publicId, systemId, notationName);
00909 #endif
00910     if (ctxt->inSubset == 1) {
00911     ent = xmlAddDocEntity(ctxt->myDoc, name,
00912             XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
00913             publicId, systemId, notationName);
00914     if ((ent == NULL) && (ctxt->pedantic) &&
00915         (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
00916         ctxt->sax->warning(ctxt->userData,
00917          "Entity(%s) already defined in the internal subset\n", name);
00918     if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
00919         xmlChar *URI;
00920         const char *base = NULL;
00921 
00922         if (ctxt->input != NULL)
00923         base = ctxt->input->filename;
00924         if (base == NULL)
00925         base = ctxt->directory;
00926 
00927         URI = xmlBuildURI(systemId, (const xmlChar *) base);
00928         ent->URI = URI;
00929     }
00930     } else if (ctxt->inSubset == 2) {
00931     ent = xmlAddDtdEntity(ctxt->myDoc, name,
00932             XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
00933             publicId, systemId, notationName);
00934     if ((ent == NULL) && (ctxt->pedantic) &&
00935         (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
00936         ctxt->sax->warning(ctxt->userData,
00937          "Entity(%s) already defined in the external subset\n", name);
00938     if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
00939         xmlChar *URI;
00940         const char *base = NULL;
00941 
00942         if (ctxt->input != NULL)
00943         base = ctxt->input->filename;
00944         if (base == NULL)
00945         base = ctxt->directory;
00946 
00947         URI = xmlBuildURI(systemId, (const xmlChar *) base);
00948         ent->URI = URI;
00949     }
00950     } else {
00951         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
00952          "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
00953                    name, NULL);
00954     }
00955 }
00956 
00957 /**
00958  * xmlSAX2SetDocumentLocator:
00959  * @ctx: the user data (XML parser context)
00960  * @loc: A SAX Locator
00961  *
00962  * Receive the document locator at startup, actually xmlDefaultSAXLocator
00963  * Everything is available on the context, so this is useless in our case.
00964  */
00965 void
00966 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
00967 {
00968     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
00969 #ifdef DEBUG_SAX
00970     xmlGenericError(xmlGenericErrorContext,
00971         "SAX.xmlSAX2SetDocumentLocator()\n");
00972 #endif
00973 }
00974 
00975 /**
00976  * xmlSAX2StartDocument:
00977  * @ctx: the user data (XML parser context)
00978  *
00979  * called when the document start being processed.
00980  */
00981 void
00982 xmlSAX2StartDocument(void *ctx)
00983 {
00984     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
00985     xmlDocPtr doc;
00986 
00987     if (ctx == NULL) return;
00988 
00989 #ifdef DEBUG_SAX
00990     xmlGenericError(xmlGenericErrorContext,
00991         "SAX.xmlSAX2StartDocument()\n");
00992 #endif
00993     if (ctxt->html) {
00994 #ifdef LIBXML_HTML_ENABLED
00995     if (ctxt->myDoc == NULL)
00996         ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
00997     if (ctxt->myDoc == NULL) {
00998         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
00999         return;
01000     }
01001     ctxt->myDoc->properties = XML_DOC_HTML;
01002     ctxt->myDoc->parseFlags = ctxt->options;
01003 #else
01004         xmlGenericError(xmlGenericErrorContext,
01005         "libxml2 built without HTML support\n");
01006     ctxt->errNo = XML_ERR_INTERNAL_ERROR;
01007     ctxt->instate = XML_PARSER_EOF;
01008     ctxt->disableSAX = 1;
01009     return;
01010 #endif
01011     } else {
01012     doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
01013     if (doc != NULL) {
01014         doc->properties = 0;
01015         if (ctxt->options & XML_PARSE_OLD10)
01016             doc->properties |= XML_DOC_OLD10;
01017         doc->parseFlags = ctxt->options;
01018         if (ctxt->encoding != NULL)
01019         doc->encoding = xmlStrdup(ctxt->encoding);
01020         else
01021         doc->encoding = NULL;
01022         doc->standalone = ctxt->standalone;
01023     } else {
01024         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
01025         return;
01026     }
01027     if ((ctxt->dictNames) && (doc != NULL)) {
01028         doc->dict = ctxt->dict;
01029         xmlDictReference(doc->dict);
01030     }
01031     }
01032     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
01033     (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
01034     ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
01035     if (ctxt->myDoc->URL == NULL)
01036         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
01037     }
01038 }
01039 
01040 /**
01041  * xmlSAX2EndDocument:
01042  * @ctx: the user data (XML parser context)
01043  *
01044  * called when the document end has been detected.
01045  */
01046 void
01047 xmlSAX2EndDocument(void *ctx)
01048 {
01049     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
01050 #ifdef DEBUG_SAX
01051     xmlGenericError(xmlGenericErrorContext,
01052         "SAX.xmlSAX2EndDocument()\n");
01053 #endif
01054     if (ctx == NULL) return;
01055 #ifdef LIBXML_VALID_ENABLED
01056     if (ctxt->validate && ctxt->wellFormed &&
01057         ctxt->myDoc && ctxt->myDoc->intSubset)
01058     ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
01059 #endif /* LIBXML_VALID_ENABLED */
01060 
01061     /*
01062      * Grab the encoding if it was added on-the-fly
01063      */
01064     if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
01065     (ctxt->myDoc->encoding == NULL)) {
01066     ctxt->myDoc->encoding = ctxt->encoding;
01067     ctxt->encoding = NULL;
01068     }
01069     if ((ctxt->inputTab != NULL) &&
01070         (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
01071         (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
01072     (ctxt->myDoc->encoding == NULL)) {
01073     ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
01074     }
01075     if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
01076     (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
01077     ctxt->myDoc->charset = ctxt->charset;
01078     }
01079 }
01080 
01081 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
01082 /**
01083  * xmlSAX2AttributeInternal:
01084  * @ctx: the user data (XML parser context)
01085  * @fullname:  The attribute name, including namespace prefix
01086  * @value:  The attribute value
01087  * @prefix: the prefix on the element node
01088  *
01089  * Handle an attribute that has been read by the parser.
01090  * The default handling is to convert the attribute into an
01091  * DOM subtree and past it in a new xmlAttr element added to
01092  * the element.
01093  */
01094 static void
01095 xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
01096              const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
01097 {
01098     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
01099     xmlAttrPtr ret;
01100     xmlChar *name;
01101     xmlChar *ns;
01102     xmlChar *nval;
01103     xmlNsPtr namespace;
01104 
01105     if (ctxt->html) {
01106     name = xmlStrdup(fullname);
01107     ns = NULL;
01108     namespace = NULL;
01109     } else {
01110     /*
01111      * Split the full name into a namespace prefix and the tag name
01112      */
01113     name = xmlSplitQName(ctxt, fullname, &ns);
01114     if ((name != NULL) && (name[0] == 0)) {
01115         if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
01116         xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
01117                 "invalid namespace declaration '%s'\n",
01118                 fullname, NULL);
01119         } else {
01120         xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
01121                  "Avoid attribute ending with ':' like '%s'\n",
01122                  fullname, NULL);
01123         }
01124         if (ns != NULL)
01125         xmlFree(ns);
01126         ns = NULL;
01127         xmlFree(name);
01128         name = xmlStrdup(fullname);
01129     }
01130     }
01131     if (name == NULL) {
01132         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01133     if (ns != NULL)
01134         xmlFree(ns);
01135     return;
01136     }
01137 
01138 #ifdef LIBXML_HTML_ENABLED
01139     if ((ctxt->html) &&
01140         (value == NULL) && (htmlIsBooleanAttr(fullname))) {
01141             nval = xmlStrdup(fullname);
01142             value = (const xmlChar *) nval;
01143     } else
01144 #endif
01145     {
01146 #ifdef LIBXML_VALID_ENABLED
01147         /*
01148          * Do the last stage of the attribute normalization
01149          * Needed for HTML too:
01150          *   http://www.w3.org/TR/html4/types.html#h-6.2
01151          */
01152         ctxt->vctxt.valid = 1;
01153         nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
01154                                                ctxt->myDoc, ctxt->node,
01155                                                fullname, value);
01156         if (ctxt->vctxt.valid != 1) {
01157             ctxt->valid = 0;
01158         }
01159         if (nval != NULL)
01160             value = nval;
01161 #else
01162         nval = NULL;
01163 #endif /* LIBXML_VALID_ENABLED */
01164     }
01165 
01166     /*
01167      * Check whether it's a namespace definition
01168      */
01169     if ((!ctxt->html) && (ns == NULL) &&
01170         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
01171         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
01172     xmlNsPtr nsret;
01173     xmlChar *val;
01174 
01175         if (!ctxt->replaceEntities) {
01176         ctxt->depth++;
01177         val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
01178                                   0,0,0);
01179         ctxt->depth--;
01180         if (val == NULL) {
01181             xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01182         if (name != NULL)
01183             xmlFree(name);
01184         return;
01185         }
01186     } else {
01187         val = (xmlChar *) value;
01188     }
01189 
01190     if (val[0] != 0) {
01191         xmlURIPtr uri;
01192 
01193         uri = xmlParseURI((const char *)val);
01194         if (uri == NULL) {
01195         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
01196             ctxt->sax->warning(ctxt->userData,
01197              "xmlns: %s not a valid URI\n", val);
01198         } else {
01199         if (uri->scheme == NULL) {
01200             if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
01201             ctxt->sax->warning(ctxt->userData,
01202                  "xmlns: URI %s is not absolute\n", val);
01203         }
01204         xmlFreeURI(uri);
01205         }
01206     }
01207 
01208     /* a default namespace definition */
01209     nsret = xmlNewNs(ctxt->node, val, NULL);
01210 
01211 #ifdef LIBXML_VALID_ENABLED
01212     /*
01213      * Validate also for namespace decls, they are attributes from
01214      * an XML-1.0 perspective
01215      */
01216         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
01217         ctxt->myDoc && ctxt->myDoc->intSubset)
01218         ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
01219                        ctxt->node, prefix, nsret, val);
01220 #endif /* LIBXML_VALID_ENABLED */
01221     if (name != NULL)
01222         xmlFree(name);
01223     if (nval != NULL)
01224         xmlFree(nval);
01225     if (val != value)
01226         xmlFree(val);
01227     return;
01228     }
01229     if ((!ctxt->html) &&
01230     (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
01231         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
01232     xmlNsPtr nsret;
01233     xmlChar *val;
01234 
01235         if (!ctxt->replaceEntities) {
01236         ctxt->depth++;
01237         val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
01238                                   0,0,0);
01239         ctxt->depth--;
01240         if (val == NULL) {
01241             xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01242             xmlFree(ns);
01243         if (name != NULL)
01244             xmlFree(name);
01245         return;
01246         }
01247     } else {
01248         val = (xmlChar *) value;
01249     }
01250 
01251     if (val[0] == 0) {
01252         xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
01253                 "Empty namespace name for prefix %s\n", name, NULL);
01254     }
01255     if ((ctxt->pedantic != 0) && (val[0] != 0)) {
01256         xmlURIPtr uri;
01257 
01258         uri = xmlParseURI((const char *)val);
01259         if (uri == NULL) {
01260             xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
01261              "xmlns:%s: %s not a valid URI\n", name, value);
01262         } else {
01263         if (uri->scheme == NULL) {
01264             xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
01265                "xmlns:%s: URI %s is not absolute\n", name, value);
01266         }
01267         xmlFreeURI(uri);
01268         }
01269     }
01270 
01271     /* a standard namespace definition */
01272     nsret = xmlNewNs(ctxt->node, val, name);
01273     xmlFree(ns);
01274 #ifdef LIBXML_VALID_ENABLED
01275     /*
01276      * Validate also for namespace decls, they are attributes from
01277      * an XML-1.0 perspective
01278      */
01279         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
01280         ctxt->myDoc && ctxt->myDoc->intSubset)
01281         ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
01282                        ctxt->node, prefix, nsret, value);
01283 #endif /* LIBXML_VALID_ENABLED */
01284     if (name != NULL)
01285         xmlFree(name);
01286     if (nval != NULL)
01287         xmlFree(nval);
01288     if (val != value)
01289         xmlFree(val);
01290     return;
01291     }
01292 
01293     if (ns != NULL) {
01294     namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
01295 
01296     if (namespace == NULL) {
01297         xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
01298             "Namespace prefix %s of attribute %s is not defined\n",
01299                      ns, name);
01300     } else {
01301             xmlAttrPtr prop;
01302 
01303             prop = ctxt->node->properties;
01304             while (prop != NULL) {
01305                 if (prop->ns != NULL) {
01306                     if ((xmlStrEqual(name, prop->name)) &&
01307                         ((namespace == prop->ns) ||
01308                          (xmlStrEqual(namespace->href, prop->ns->href)))) {
01309                             xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
01310                                     "Attribute %s in %s redefined\n",
01311                                              name, namespace->href);
01312                         ctxt->wellFormed = 0;
01313                         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
01314                         goto error;
01315                     }
01316                 }
01317                 prop = prop->next;
01318             }
01319         }
01320     } else {
01321     namespace = NULL;
01322     }
01323 
01324     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
01325     ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
01326 
01327     if (ret != NULL) {
01328         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
01329         xmlNodePtr tmp;
01330 
01331         ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
01332         tmp = ret->children;
01333         while (tmp != NULL) {
01334         tmp->parent = (xmlNodePtr) ret;
01335         if (tmp->next == NULL)
01336             ret->last = tmp;
01337         tmp = tmp->next;
01338         }
01339     } else if (value != NULL) {
01340         ret->children = xmlNewDocText(ctxt->myDoc, value);
01341         ret->last = ret->children;
01342         if (ret->children != NULL)
01343         ret->children->parent = (xmlNodePtr) ret;
01344     }
01345     }
01346 
01347 #ifdef LIBXML_VALID_ENABLED
01348     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
01349         ctxt->myDoc && ctxt->myDoc->intSubset) {
01350 
01351     /*
01352      * If we don't substitute entities, the validation should be
01353      * done on a value with replaced entities anyway.
01354      */
01355         if (!ctxt->replaceEntities) {
01356         xmlChar *val;
01357 
01358         ctxt->depth++;
01359         val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
01360                                   0,0,0);
01361         ctxt->depth--;
01362 
01363         if (val == NULL)
01364         ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
01365                 ctxt->myDoc, ctxt->node, ret, value);
01366         else {
01367         xmlChar *nvalnorm;
01368 
01369         /*
01370          * Do the last stage of the attribute normalization
01371          * It need to be done twice ... it's an extra burden related
01372          * to the ability to keep xmlSAX2References in attributes
01373          */
01374         nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
01375                         ctxt->node, fullname, val);
01376         if (nvalnorm != NULL) {
01377             xmlFree(val);
01378             val = nvalnorm;
01379         }
01380 
01381         ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
01382                     ctxt->myDoc, ctxt->node, ret, val);
01383                 xmlFree(val);
01384         }
01385     } else {
01386         ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
01387                            ctxt->node, ret, value);
01388     }
01389     } else
01390 #endif /* LIBXML_VALID_ENABLED */
01391            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
01392            (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
01393             ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
01394         /*
01395      * when validating, the ID registration is done at the attribute
01396      * validation level. Otherwise we have to do specific handling here.
01397      */
01398     if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
01399         /*
01400          * Add the xml:id value
01401          *
01402          * Open issue: normalization of the value.
01403          */
01404         if (xmlValidateNCName(value, 1) != 0) {
01405             xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
01406               "xml:id : attribute value %s is not an NCName\n",
01407                 (const char *) value, NULL);
01408         }
01409         xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
01410     } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
01411         xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
01412     else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
01413         xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
01414     }
01415 
01416 error:
01417     if (nval != NULL)
01418     xmlFree(nval);
01419     if (ns != NULL)
01420     xmlFree(ns);
01421 }
01422 
01423 /*
01424  * xmlCheckDefaultedAttributes:
01425  *
01426  * Check defaulted attributes from the DTD
01427  */
01428 static void
01429 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
01430     const xmlChar *prefix, const xmlChar **atts) {
01431     xmlElementPtr elemDecl;
01432     const xmlChar *att;
01433     int internal = 1;
01434     int i;
01435 
01436     elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
01437     if (elemDecl == NULL) {
01438     elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
01439     internal = 0;
01440     }
01441 
01442 process_external_subset:
01443 
01444     if (elemDecl != NULL) {
01445     xmlAttributePtr attr = elemDecl->attributes;
01446     /*
01447      * Check against defaulted attributes from the external subset
01448      * if the document is stamped as standalone
01449      */
01450     if ((ctxt->myDoc->standalone == 1) &&
01451         (ctxt->myDoc->extSubset != NULL) &&
01452         (ctxt->validate)) {
01453         while (attr != NULL) {
01454         if ((attr->defaultValue != NULL) &&
01455             (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
01456                     attr->elem, attr->name,
01457                     attr->prefix) == attr) &&
01458             (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
01459                     attr->elem, attr->name,
01460                     attr->prefix) == NULL)) {
01461             xmlChar *fulln;
01462 
01463             if (attr->prefix != NULL) {
01464             fulln = xmlStrdup(attr->prefix);
01465             fulln = xmlStrcat(fulln, BAD_CAST ":");
01466             fulln = xmlStrcat(fulln, attr->name);
01467             } else {
01468             fulln = xmlStrdup(attr->name);
01469             }
01470                     if (fulln == NULL) {
01471                         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01472                         break;
01473                     }
01474 
01475             /*
01476              * Check that the attribute is not declared in the
01477              * serialization
01478              */
01479             att = NULL;
01480             if (atts != NULL) {
01481             i = 0;
01482             att = atts[i];
01483             while (att != NULL) {
01484                 if (xmlStrEqual(att, fulln))
01485                 break;
01486                 i += 2;
01487                 att = atts[i];
01488             }
01489             }
01490             if (att == NULL) {
01491                 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
01492       "standalone: attribute %s on %s defaulted from external subset\n",
01493                     (const char *)fulln,
01494                     (const char *)attr->elem);
01495             }
01496                     xmlFree(fulln);
01497         }
01498         attr = attr->nexth;
01499         }
01500     }
01501 
01502     /*
01503      * Actually insert defaulted values when needed
01504      */
01505     attr = elemDecl->attributes;
01506     while (attr != NULL) {
01507         /*
01508          * Make sure that attributes redefinition occuring in the
01509          * internal subset are not overriden by definitions in the
01510          * external subset.
01511          */
01512         if (attr->defaultValue != NULL) {
01513         /*
01514          * the element should be instantiated in the tree if:
01515          *  - this is a namespace prefix
01516          *  - the user required for completion in the tree
01517          *    like XSLT
01518          *  - there isn't already an attribute definition
01519          *    in the internal subset overriding it.
01520          */
01521         if (((attr->prefix != NULL) &&
01522              (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
01523             ((attr->prefix == NULL) &&
01524              (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
01525             (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
01526             xmlAttributePtr tst;
01527 
01528             tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
01529                          attr->elem, attr->name,
01530                          attr->prefix);
01531             if ((tst == attr) || (tst == NULL)) {
01532                 xmlChar fn[50];
01533             xmlChar *fulln;
01534 
01535                         fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
01536             if (fulln == NULL) {
01537                 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01538                 return;
01539             }
01540 
01541             /*
01542              * Check that the attribute is not declared in the
01543              * serialization
01544              */
01545             att = NULL;
01546             if (atts != NULL) {
01547                 i = 0;
01548                 att = atts[i];
01549                 while (att != NULL) {
01550                 if (xmlStrEqual(att, fulln))
01551                     break;
01552                 i += 2;
01553                 att = atts[i];
01554                 }
01555             }
01556             if (att == NULL) {
01557                 xmlSAX2AttributeInternal(ctxt, fulln,
01558                          attr->defaultValue, prefix);
01559             }
01560             if ((fulln != fn) && (fulln != attr->name))
01561                 xmlFree(fulln);
01562             }
01563         }
01564         }
01565         attr = attr->nexth;
01566     }
01567     if (internal == 1) {
01568         elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
01569                                      name, prefix);
01570         internal = 0;
01571         goto process_external_subset;
01572     }
01573     }
01574 }
01575 
01576 /**
01577  * xmlSAX2StartElement:
01578  * @ctx: the user data (XML parser context)
01579  * @fullname:  The element name, including namespace prefix
01580  * @atts:  An array of name/value attributes pairs, NULL terminated
01581  *
01582  * called when an opening tag has been processed.
01583  */
01584 void
01585 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
01586 {
01587     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
01588     xmlNodePtr ret;
01589     xmlNodePtr parent;
01590     xmlNsPtr ns;
01591     xmlChar *name;
01592     xmlChar *prefix;
01593     const xmlChar *att;
01594     const xmlChar *value;
01595     int i;
01596 
01597     if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
01598     parent = ctxt->node;
01599 #ifdef DEBUG_SAX
01600     xmlGenericError(xmlGenericErrorContext,
01601         "SAX.xmlSAX2StartElement(%s)\n", fullname);
01602 #endif
01603 
01604     /*
01605      * First check on validity:
01606      */
01607     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
01608         ((ctxt->myDoc->intSubset == NULL) ||
01609      ((ctxt->myDoc->intSubset->notations == NULL) &&
01610       (ctxt->myDoc->intSubset->elements == NULL) &&
01611       (ctxt->myDoc->intSubset->attributes == NULL) &&
01612       (ctxt->myDoc->intSubset->entities == NULL)))) {
01613     xmlErrValid(ctxt, XML_ERR_NO_DTD,
01614       "Validation failed: no DTD found !", NULL, NULL);
01615     ctxt->validate = 0;
01616     }
01617 
01618 
01619     /*
01620      * Split the full name into a namespace prefix and the tag name
01621      */
01622     name = xmlSplitQName(ctxt, fullname, &prefix);
01623 
01624 
01625     /*
01626      * Note : the namespace resolution is deferred until the end of the
01627      *        attributes parsing, since local namespace can be defined as
01628      *        an attribute at this level.
01629      */
01630     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
01631     if (ret == NULL) {
01632         if (prefix != NULL)
01633         xmlFree(prefix);
01634     xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
01635         return;
01636     }
01637     if (ctxt->myDoc->children == NULL) {
01638 #ifdef DEBUG_SAX_TREE
01639     xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
01640 #endif
01641         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
01642     } else if (parent == NULL) {
01643         parent = ctxt->myDoc->children;
01644     }
01645     ctxt->nodemem = -1;
01646     if (ctxt->linenumbers) {
01647     if (ctxt->input != NULL) {
01648         if (ctxt->input->line < 65535)
01649         ret->line = (short) ctxt->input->line;
01650         else
01651             ret->line = 65535;
01652     }
01653     }
01654 
01655     /*
01656      * We are parsing a new node.
01657      */
01658 #ifdef DEBUG_SAX_TREE
01659     xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
01660 #endif
01661     nodePush(ctxt, ret);
01662 
01663     /*
01664      * Link the child element
01665      */
01666     if (parent != NULL) {
01667         if (parent->type == XML_ELEMENT_NODE) {
01668 #ifdef DEBUG_SAX_TREE
01669         xmlGenericError(xmlGenericErrorContext,
01670             "adding child %s to %s\n", name, parent->name);
01671 #endif
01672         xmlAddChild(parent, ret);
01673     } else {
01674 #ifdef DEBUG_SAX_TREE
01675         xmlGenericError(xmlGenericErrorContext,
01676             "adding sibling %s to ", name);
01677         xmlDebugDumpOneNode(stderr, parent, 0);
01678 #endif
01679         xmlAddSibling(parent, ret);
01680     }
01681     }
01682 
01683     /*
01684      * Insert all the defaulted attributes from the DTD especially namespaces
01685      */
01686     if ((!ctxt->html) &&
01687     ((ctxt->myDoc->intSubset != NULL) ||
01688      (ctxt->myDoc->extSubset != NULL))) {
01689     xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
01690     }
01691 
01692     /*
01693      * process all the attributes whose name start with "xmlns"
01694      */
01695     if (atts != NULL) {
01696         i = 0;
01697     att = atts[i++];
01698     value = atts[i++];
01699     if (!ctxt->html) {
01700         while ((att != NULL) && (value != NULL)) {
01701         if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
01702             (att[3] == 'n') && (att[4] == 's'))
01703             xmlSAX2AttributeInternal(ctxt, att, value, prefix);
01704 
01705         att = atts[i++];
01706         value = atts[i++];
01707         }
01708     }
01709     }
01710 
01711     /*
01712      * Search the namespace, note that since the attributes have been
01713      * processed, the local namespaces are available.
01714      */
01715     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
01716     if ((ns == NULL) && (parent != NULL))
01717     ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
01718     if ((prefix != NULL) && (ns == NULL)) {
01719     ns = xmlNewNs(ret, NULL, prefix);
01720     xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
01721              "Namespace prefix %s is not defined\n",
01722              prefix, NULL);
01723     }
01724 
01725     /*
01726      * set the namespace node, making sure that if the default namspace
01727      * is unbound on a parent we simply kee it NULL
01728      */
01729     if ((ns != NULL) && (ns->href != NULL) &&
01730     ((ns->href[0] != 0) || (ns->prefix != NULL)))
01731     xmlSetNs(ret, ns);
01732 
01733     /*
01734      * process all the other attributes
01735      */
01736     if (atts != NULL) {
01737         i = 0;
01738     att = atts[i++];
01739     value = atts[i++];
01740     if (ctxt->html) {
01741         while (att != NULL) {
01742         xmlSAX2AttributeInternal(ctxt, att, value, NULL);
01743         att = atts[i++];
01744         value = atts[i++];
01745         }
01746     } else {
01747         while ((att != NULL) && (value != NULL)) {
01748         if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
01749             (att[3] != 'n') || (att[4] != 's'))
01750             xmlSAX2AttributeInternal(ctxt, att, value, NULL);
01751 
01752         /*
01753          * Next ones
01754          */
01755         att = atts[i++];
01756         value = atts[i++];
01757         }
01758     }
01759     }
01760 
01761 #ifdef LIBXML_VALID_ENABLED
01762     /*
01763      * If it's the Document root, finish the DTD validation and
01764      * check the document root element for validity
01765      */
01766     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
01767     int chk;
01768 
01769     chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
01770     if (chk <= 0)
01771         ctxt->valid = 0;
01772     if (chk < 0)
01773         ctxt->wellFormed = 0;
01774     ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
01775     ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
01776     }
01777 #endif /* LIBXML_VALID_ENABLED */
01778 
01779     if (prefix != NULL)
01780     xmlFree(prefix);
01781 
01782 }
01783 
01784 /**
01785  * xmlSAX2EndElement:
01786  * @ctx: the user data (XML parser context)
01787  * @name:  The element name
01788  *
01789  * called when the end of an element has been detected.
01790  */
01791 void
01792 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
01793 {
01794     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
01795     xmlNodePtr cur;
01796 
01797     if (ctx == NULL) return;
01798     cur = ctxt->node;
01799 #ifdef DEBUG_SAX
01800     if (name == NULL)
01801         xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
01802     else
01803     xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
01804 #endif
01805 
01806     /* Capture end position and add node */
01807     if (cur != NULL && ctxt->record_info) {
01808       ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
01809       ctxt->nodeInfo->end_line = ctxt->input->line;
01810       ctxt->nodeInfo->node = cur;
01811       xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
01812     }
01813     ctxt->nodemem = -1;
01814 
01815 #ifdef LIBXML_VALID_ENABLED
01816     if (ctxt->validate && ctxt->wellFormed &&
01817         ctxt->myDoc && ctxt->myDoc->intSubset)
01818         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
01819                          cur);
01820 #endif /* LIBXML_VALID_ENABLED */
01821 
01822 
01823     /*
01824      * end of parsing of this node.
01825      */
01826 #ifdef DEBUG_SAX_TREE
01827     xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
01828 #endif
01829     nodePop(ctxt);
01830 }
01831 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
01832 
01833 /*
01834  * xmlSAX2TextNode:
01835  * @ctxt:  the parser context
01836  * @str:  the input string
01837  * @len: the string length
01838  *
01839  * Callback for a text node
01840  *
01841  * Returns the newly allocated string or NULL if not needed or error
01842  */
01843 static xmlNodePtr
01844 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
01845     xmlNodePtr ret;
01846     const xmlChar *intern = NULL;
01847 
01848     /*
01849      * Allocate
01850      */
01851     if (ctxt->freeElems != NULL) {
01852     ret = ctxt->freeElems;
01853     ctxt->freeElems = ret->next;
01854     ctxt->freeElemsNr--;
01855     } else {
01856     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
01857     }
01858     if (ret == NULL) {
01859         xmlErrMemory(ctxt, "xmlSAX2Characters");
01860     return(NULL);
01861     }
01862     memset(ret, 0, sizeof(xmlNode));
01863     /*
01864      * intern the formatting blanks found between tags, or the
01865      * very short strings
01866      */
01867     if (ctxt->dictNames) {
01868         xmlChar cur = str[len];
01869 
01870     if ((len < (int) (2 * sizeof(void *))) &&
01871         (ctxt->options & XML_PARSE_COMPACT)) {
01872         /* store the string in the node overriding properties and nsDef */
01873         xmlChar *tmp = (xmlChar *) &(ret->properties);
01874         memcpy(tmp, str, len);
01875         tmp[len] = 0;
01876         intern = tmp;
01877     } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
01878         ((cur == '<') && (str[len + 1] != '!')))) {
01879         intern = xmlDictLookup(ctxt->dict, str, len);
01880     } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
01881                (str[len + 1] != '!')) {
01882         int i;
01883 
01884         for (i = 1;i < len;i++) {
01885         if (!IS_BLANK_CH(str[i])) goto skip;
01886         }
01887         intern = xmlDictLookup(ctxt->dict, str, len);
01888     }
01889     }
01890 skip:
01891     ret->type = XML_TEXT_NODE;
01892 
01893     ret->name = xmlStringText;
01894     if (intern == NULL) {
01895     ret->content = xmlStrndup(str, len);
01896     if (ret->content == NULL) {
01897         xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
01898         xmlFree(ret);
01899         return(NULL);
01900     }
01901     } else
01902     ret->content = (xmlChar *) intern;
01903 
01904     if (ctxt->linenumbers) {
01905     if (ctxt->input != NULL) {
01906         if (ctxt->input->line < 65535)
01907         ret->line = (short) ctxt->input->line;
01908         else {
01909             ret->line = 65535;
01910         if (ctxt->options & XML_PARSE_BIG_LINES)
01911             ret->psvi = (void *) (long) ctxt->input->line;
01912         }
01913     }
01914     }
01915 
01916     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
01917     xmlRegisterNodeDefaultValue(ret);
01918     return(ret);
01919 }
01920 
01921 #ifdef LIBXML_VALID_ENABLED
01922 /*
01923  * xmlSAX2DecodeAttrEntities:
01924  * @ctxt:  the parser context
01925  * @str:  the input string
01926  * @len: the string length
01927  *
01928  * Remove the entities from an attribute value
01929  *
01930  * Returns the newly allocated string or NULL if not needed or error
01931  */
01932 static xmlChar *
01933 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
01934                           const xmlChar *end) {
01935     const xmlChar *in;
01936     xmlChar *ret;
01937 
01938     in = str;
01939     while (in < end)
01940         if (*in++ == '&')
01941         goto decode;
01942     return(NULL);
01943 decode:
01944     ctxt->depth++;
01945     ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
01946                      XML_SUBSTITUTE_REF, 0,0,0);
01947     ctxt->depth--;
01948     return(ret);
01949 }
01950 #endif /* LIBXML_VALID_ENABLED */
01951 
01952 /**
01953  * xmlSAX2AttributeNs:
01954  * @ctx: the user data (XML parser context)
01955  * @localname:  the local name of the attribute
01956  * @prefix:  the attribute namespace prefix if available
01957  * @URI:  the attribute namespace name if available
01958  * @value:  Start of the attribute value
01959  * @valueend: end of the attribute value
01960  *
01961  * Handle an attribute that has been read by the parser.
01962  * The default handling is to convert the attribute into an
01963  * DOM subtree and past it in a new xmlAttr element added to
01964  * the element.
01965  */
01966 static void
01967 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
01968                    const xmlChar * localname,
01969                    const xmlChar * prefix,
01970            const xmlChar * value,
01971            const xmlChar * valueend)
01972 {
01973     xmlAttrPtr ret;
01974     xmlNsPtr namespace = NULL;
01975     xmlChar *dup = NULL;
01976 
01977     /*
01978      * Note: if prefix == NULL, the attribute is not in the default namespace
01979      */
01980     if (prefix != NULL)
01981     namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
01982 
01983     /*
01984      * allocate the node
01985      */
01986     if (ctxt->freeAttrs != NULL) {
01987         ret = ctxt->freeAttrs;
01988     ctxt->freeAttrs = ret->next;
01989     ctxt->freeAttrsNr--;
01990     memset(ret, 0, sizeof(xmlAttr));
01991     ret->type = XML_ATTRIBUTE_NODE;
01992 
01993     ret->parent = ctxt->node;
01994     ret->doc = ctxt->myDoc;
01995     ret->ns = namespace;
01996 
01997     if (ctxt->dictNames)
01998         ret->name = localname;
01999     else
02000         ret->name = xmlStrdup(localname);
02001 
02002         /* link at the end to preserv order, TODO speed up with a last */
02003     if (ctxt->node->properties == NULL) {
02004         ctxt->node->properties = ret;
02005     } else {
02006         xmlAttrPtr prev = ctxt->node->properties;
02007 
02008         while (prev->next != NULL) prev = prev->next;
02009         prev->next = ret;
02010         ret->prev = prev;
02011     }
02012 
02013     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
02014         xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
02015     } else {
02016     if (ctxt->dictNames)
02017         ret = xmlNewNsPropEatName(ctxt->node, namespace,
02018                                   (xmlChar *) localname, NULL);
02019     else
02020         ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
02021     if (ret == NULL) {
02022         xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
02023         return;
02024     }
02025     }
02026 
02027     if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
02028     xmlNodePtr tmp;
02029 
02030     /*
02031      * We know that if there is an entity reference, then
02032      * the string has been dup'ed and terminates with 0
02033      * otherwise with ' or "
02034      */
02035     if (*valueend != 0) {
02036         tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
02037         ret->children = tmp;
02038         ret->last = tmp;
02039         if (tmp != NULL) {
02040         tmp->doc = ret->doc;
02041         tmp->parent = (xmlNodePtr) ret;
02042         }
02043     } else {
02044         ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
02045                             valueend - value);
02046         tmp = ret->children;
02047         while (tmp != NULL) {
02048             tmp->doc = ret->doc;
02049         tmp->parent = (xmlNodePtr) ret;
02050         if (tmp->next == NULL)
02051             ret->last = tmp;
02052         tmp = tmp->next;
02053         }
02054     }
02055     } else if (value != NULL) {
02056     xmlNodePtr tmp;
02057 
02058     tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
02059     ret->children = tmp;
02060     ret->last = tmp;
02061     if (tmp != NULL) {
02062         tmp->doc = ret->doc;
02063         tmp->parent = (xmlNodePtr) ret;
02064     }
02065     }
02066 
02067 #ifdef LIBXML_VALID_ENABLED
02068     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
02069         ctxt->myDoc && ctxt->myDoc->intSubset) {
02070     /*
02071      * If we don't substitute entities, the validation should be
02072      * done on a value with replaced entities anyway.
02073      */
02074         if (!ctxt->replaceEntities) {
02075         dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
02076         if (dup == NULL) {
02077             if (*valueend == 0) {
02078             ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
02079                     ctxt->myDoc, ctxt->node, ret, value);
02080         } else {
02081             /*
02082              * That should already be normalized.
02083              * cheaper to finally allocate here than duplicate
02084              * entry points in the full validation code
02085              */
02086             dup = xmlStrndup(value, valueend - value);
02087 
02088             ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
02089                     ctxt->myDoc, ctxt->node, ret, dup);
02090         }
02091         } else {
02092             /*
02093          * dup now contains a string of the flattened attribute
02094          * content with entities substitued. Check if we need to
02095          * apply an extra layer of normalization.
02096          * It need to be done twice ... it's an extra burden related
02097          * to the ability to keep references in attributes
02098          */
02099         if (ctxt->attsSpecial != NULL) {
02100             xmlChar *nvalnorm;
02101             xmlChar fn[50];
02102             xmlChar *fullname;
02103 
02104             fullname = xmlBuildQName(localname, prefix, fn, 50);
02105             if (fullname != NULL) {
02106             ctxt->vctxt.valid = 1;
02107                 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
02108                              &ctxt->vctxt, ctxt->myDoc,
02109                      ctxt->node, fullname, dup);
02110             if (ctxt->vctxt.valid != 1)
02111                 ctxt->valid = 0;
02112 
02113             if ((fullname != fn) && (fullname != localname))
02114                 xmlFree(fullname);
02115             if (nvalnorm != NULL) {
02116                 xmlFree(dup);
02117                 dup = nvalnorm;
02118             }
02119             }
02120         }
02121 
02122         ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
02123                     ctxt->myDoc, ctxt->node, ret, dup);
02124         }
02125     } else {
02126         /*
02127          * if entities already have been substitued, then
02128          * the attribute as passed is already normalized
02129          */
02130         dup = xmlStrndup(value, valueend - value);
02131 
02132         ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
02133                                  ctxt->myDoc, ctxt->node, ret, dup);
02134     }
02135     } else
02136 #endif /* LIBXML_VALID_ENABLED */
02137            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
02138            (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
02139             ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
02140         /*
02141      * when validating, the ID registration is done at the attribute
02142      * validation level. Otherwise we have to do specific handling here.
02143      */
02144         if ((prefix == ctxt->str_xml) &&
02145                (localname[0] == 'i') && (localname[1] == 'd') &&
02146            (localname[2] == 0)) {
02147         /*
02148          * Add the xml:id value
02149          *
02150          * Open issue: normalization of the value.
02151          */
02152         if (dup == NULL)
02153             dup = xmlStrndup(value, valueend - value);
02154 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
02155 #ifdef LIBXML_VALID_ENABLED
02156         if (xmlValidateNCName(dup, 1) != 0) {
02157             xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
02158               "xml:id : attribute value %s is not an NCName\n",
02159                 (const char *) dup, NULL);
02160         }
02161 #endif
02162 #endif
02163         xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
02164     } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
02165         /* might be worth duplicate entry points and not copy */
02166         if (dup == NULL)
02167             dup = xmlStrndup(value, valueend - value);
02168         xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
02169     } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
02170         if (dup == NULL)
02171             dup = xmlStrndup(value, valueend - value);
02172         xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
02173     }
02174     }
02175     if (dup != NULL)
02176     xmlFree(dup);
02177 }
02178 
02179 /**
02180  * xmlSAX2StartElementNs:
02181  * @ctx:  the user data (XML parser context)
02182  * @localname:  the local name of the element
02183  * @prefix:  the element namespace prefix if available
02184  * @URI:  the element namespace name if available
02185  * @nb_namespaces:  number of namespace definitions on that node
02186  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
02187  * @nb_attributes:  the number of attributes on that node
02188  * @nb_defaulted:  the number of defaulted attributes.
02189  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
02190  *               attribute values.
02191  *
02192  * SAX2 callback when an element start has been detected by the parser.
02193  * It provides the namespace informations for the element, as well as
02194  * the new namespace declarations on the element.
02195  */
02196 void
02197 xmlSAX2StartElementNs(void *ctx,
02198                       const xmlChar *localname,
02199               const xmlChar *prefix,
02200               const xmlChar *URI,
02201               int nb_namespaces,
02202               const xmlChar **namespaces,
02203               int nb_attributes,
02204               int nb_defaulted,
02205               const xmlChar **attributes)
02206 {
02207     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02208     xmlNodePtr ret;
02209     xmlNodePtr parent;
02210     xmlNsPtr last = NULL, ns;
02211     const xmlChar *uri, *pref;
02212     xmlChar *lname = NULL;
02213     int i, j;
02214 
02215     if (ctx == NULL) return;
02216     parent = ctxt->node;
02217     /*
02218      * First check on validity:
02219      */
02220     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
02221         ((ctxt->myDoc->intSubset == NULL) ||
02222      ((ctxt->myDoc->intSubset->notations == NULL) &&
02223       (ctxt->myDoc->intSubset->elements == NULL) &&
02224       (ctxt->myDoc->intSubset->attributes == NULL) &&
02225       (ctxt->myDoc->intSubset->entities == NULL)))) {
02226     xmlErrValid(ctxt, XML_DTD_NO_DTD,
02227       "Validation failed: no DTD found !", NULL, NULL);
02228     ctxt->validate = 0;
02229     }
02230 
02231     /*
02232      * Take care of the rare case of an undefined namespace prefix
02233      */
02234     if ((prefix != NULL) && (URI == NULL)) {
02235         if (ctxt->dictNames) {
02236         const xmlChar *fullname;
02237 
02238         fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
02239         if (fullname != NULL)
02240             localname = fullname;
02241     } else {
02242         lname = xmlBuildQName(localname, prefix, NULL, 0);
02243     }
02244     }
02245     /*
02246      * allocate the node
02247      */
02248     if (ctxt->freeElems != NULL) {
02249         ret = ctxt->freeElems;
02250     ctxt->freeElems = ret->next;
02251     ctxt->freeElemsNr--;
02252     memset(ret, 0, sizeof(xmlNode));
02253     ret->type = XML_ELEMENT_NODE;
02254 
02255     if (ctxt->dictNames)
02256         ret->name = localname;
02257     else {
02258         if (lname == NULL)
02259         ret->name = xmlStrdup(localname);
02260         else
02261             ret->name = lname;
02262         if (ret->name == NULL) {
02263             xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
02264         return;
02265         }
02266     }
02267     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
02268         xmlRegisterNodeDefaultValue(ret);
02269     } else {
02270     if (ctxt->dictNames)
02271         ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
02272                                    (xmlChar *) localname, NULL);
02273     else if (lname == NULL)
02274         ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
02275     else
02276         ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
02277                                    (xmlChar *) lname, NULL);
02278     if (ret == NULL) {
02279         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
02280         return;
02281     }
02282     }
02283     if (ctxt->linenumbers) {
02284     if (ctxt->input != NULL) {
02285         if (ctxt->input->line < 65535)
02286         ret->line = (short) ctxt->input->line;
02287         else
02288             ret->line = 65535;
02289     }
02290     }
02291 
02292     if (parent == NULL) {
02293         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
02294     }
02295     /*
02296      * Build the namespace list
02297      */
02298     for (i = 0,j = 0;j < nb_namespaces;j++) {
02299         pref = namespaces[i++];
02300     uri = namespaces[i++];
02301     ns = xmlNewNs(NULL, uri, pref);
02302     if (ns != NULL) {
02303         if (last == NULL) {
02304             ret->nsDef = last = ns;
02305         } else {
02306             last->next = ns;
02307         last = ns;
02308         }
02309         if ((URI != NULL) && (prefix == pref))
02310         ret->ns = ns;
02311     } else {
02312             /*
02313              * any out of memory error would already have been raised
02314              * but we can't be garanteed it's the actual error due to the
02315              * API, best is to skip in this case
02316              */
02317         continue;
02318     }
02319 #ifdef LIBXML_VALID_ENABLED
02320     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
02321         ctxt->myDoc && ctxt->myDoc->intSubset) {
02322         ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
02323                                                ret, prefix, ns, uri);
02324     }
02325 #endif /* LIBXML_VALID_ENABLED */
02326     }
02327     ctxt->nodemem = -1;
02328 
02329     /*
02330      * We are parsing a new node.
02331      */
02332     nodePush(ctxt, ret);
02333 
02334     /*
02335      * Link the child element
02336      */
02337     if (parent != NULL) {
02338         if (parent->type == XML_ELEMENT_NODE) {
02339         xmlAddChild(parent, ret);
02340     } else {
02341         xmlAddSibling(parent, ret);
02342     }
02343     }
02344 
02345     /*
02346      * Insert the defaulted attributes from the DTD only if requested:
02347      */
02348     if ((nb_defaulted != 0) &&
02349         ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
02350     nb_attributes -= nb_defaulted;
02351 
02352     /*
02353      * Search the namespace if it wasn't already found
02354      * Note that, if prefix is NULL, this searches for the default Ns
02355      */
02356     if ((URI != NULL) && (ret->ns == NULL)) {
02357         ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
02358     if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
02359         ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
02360     }
02361     if (ret->ns == NULL) {
02362         ns = xmlNewNs(ret, NULL, prefix);
02363         if (ns == NULL) {
02364 
02365             xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
02366         return;
02367         }
02368             if (prefix != NULL)
02369                 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
02370                              "Namespace prefix %s was not found\n",
02371                              prefix, NULL);
02372             else
02373                 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
02374                              "Namespace default prefix was not found\n",
02375                              NULL, NULL);
02376     }
02377     }
02378 
02379     /*
02380      * process all the other attributes
02381      */
02382     if (nb_attributes > 0) {
02383         for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
02384         /*
02385          * Handle the rare case of an undefined atribute prefix
02386          */
02387         if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
02388         if (ctxt->dictNames) {
02389             const xmlChar *fullname;
02390 
02391             fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
02392                                       attributes[j]);
02393             if (fullname != NULL) {
02394             xmlSAX2AttributeNs(ctxt, fullname, NULL,
02395                                attributes[j+3], attributes[j+4]);
02396                 continue;
02397             }
02398         } else {
02399             lname = xmlBuildQName(attributes[j], attributes[j+1],
02400                                   NULL, 0);
02401             if (lname != NULL) {
02402             xmlSAX2AttributeNs(ctxt, lname, NULL,
02403                                attributes[j+3], attributes[j+4]);
02404             xmlFree(lname);
02405                 continue;
02406             }
02407         }
02408         }
02409         xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
02410                    attributes[j+3], attributes[j+4]);
02411     }
02412     }
02413 
02414 #ifdef LIBXML_VALID_ENABLED
02415     /*
02416      * If it's the Document root, finish the DTD validation and
02417      * check the document root element for validity
02418      */
02419     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
02420     int chk;
02421 
02422     chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
02423     if (chk <= 0)
02424         ctxt->valid = 0;
02425     if (chk < 0)
02426         ctxt->wellFormed = 0;
02427     ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
02428     ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
02429     }
02430 #endif /* LIBXML_VALID_ENABLED */
02431 }
02432 
02433 /**
02434  * xmlSAX2EndElementNs:
02435  * @ctx:  the user data (XML parser context)
02436  * @localname:  the local name of the element
02437  * @prefix:  the element namespace prefix if available
02438  * @URI:  the element namespace name if available
02439  *
02440  * SAX2 callback when an element end has been detected by the parser.
02441  * It provides the namespace informations for the element.
02442  */
02443 void
02444 xmlSAX2EndElementNs(void *ctx,
02445                     const xmlChar * localname ATTRIBUTE_UNUSED,
02446                     const xmlChar * prefix ATTRIBUTE_UNUSED,
02447             const xmlChar * URI ATTRIBUTE_UNUSED)
02448 {
02449     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02450     xmlParserNodeInfo node_info;
02451     xmlNodePtr cur;
02452 
02453     if (ctx == NULL) return;
02454     cur = ctxt->node;
02455     /* Capture end position and add node */
02456     if ((ctxt->record_info) && (cur != NULL)) {
02457         node_info.end_pos = ctxt->input->cur - ctxt->input->base;
02458         node_info.end_line = ctxt->input->line;
02459         node_info.node = cur;
02460         xmlParserAddNodeInfo(ctxt, &node_info);
02461     }
02462     ctxt->nodemem = -1;
02463 
02464 #ifdef LIBXML_VALID_ENABLED
02465     if (ctxt->validate && ctxt->wellFormed &&
02466         ctxt->myDoc && ctxt->myDoc->intSubset)
02467         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
02468 #endif /* LIBXML_VALID_ENABLED */
02469 
02470     /*
02471      * end of parsing of this node.
02472      */
02473     nodePop(ctxt);
02474 }
02475 
02476 /**
02477  * xmlSAX2Reference:
02478  * @ctx: the user data (XML parser context)
02479  * @name:  The entity name
02480  *
02481  * called when an entity xmlSAX2Reference is detected.
02482  */
02483 void
02484 xmlSAX2Reference(void *ctx, const xmlChar *name)
02485 {
02486     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02487     xmlNodePtr ret;
02488 
02489     if (ctx == NULL) return;
02490 #ifdef DEBUG_SAX
02491     xmlGenericError(xmlGenericErrorContext,
02492         "SAX.xmlSAX2Reference(%s)\n", name);
02493 #endif
02494     if (name[0] == '#')
02495     ret = xmlNewCharRef(ctxt->myDoc, name);
02496     else
02497     ret = xmlNewReference(ctxt->myDoc, name);
02498 #ifdef DEBUG_SAX_TREE
02499     xmlGenericError(xmlGenericErrorContext,
02500         "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
02501 #endif
02502     if (xmlAddChild(ctxt->node, ret) == NULL) {
02503         xmlFreeNode(ret);
02504     }
02505 }
02506 
02507 /**
02508  * xmlSAX2Characters:
02509  * @ctx: the user data (XML parser context)
02510  * @ch:  a xmlChar string
02511  * @len: the number of xmlChar
02512  *
02513  * receiving some chars from the parser.
02514  */
02515 void
02516 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
02517 {
02518     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02519     xmlNodePtr lastChild;
02520 
02521     if (ctx == NULL) return;
02522 #ifdef DEBUG_SAX
02523     xmlGenericError(xmlGenericErrorContext,
02524         "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
02525 #endif
02526     /*
02527      * Handle the data if any. If there is no child
02528      * add it as content, otherwise if the last child is text,
02529      * concatenate it, else create a new node of type text.
02530      */
02531 
02532     if (ctxt->node == NULL) {
02533 #ifdef DEBUG_SAX_TREE
02534     xmlGenericError(xmlGenericErrorContext,
02535         "add chars: ctxt->node == NULL !\n");
02536 #endif
02537         return;
02538     }
02539     lastChild = ctxt->node->last;
02540 #ifdef DEBUG_SAX_TREE
02541     xmlGenericError(xmlGenericErrorContext,
02542         "add chars to %s \n", ctxt->node->name);
02543 #endif
02544 
02545     /*
02546      * Here we needed an accelerator mechanism in case of very large
02547      * elements. Use an attribute in the structure !!!
02548      */
02549     if (lastChild == NULL) {
02550         lastChild = xmlSAX2TextNode(ctxt, ch, len);
02551     if (lastChild != NULL) {
02552         ctxt->node->children = lastChild;
02553         ctxt->node->last = lastChild;
02554         lastChild->parent = ctxt->node;
02555         lastChild->doc = ctxt->node->doc;
02556         ctxt->nodelen = len;
02557         ctxt->nodemem = len + 1;
02558     } else {
02559         xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
02560         return;
02561     }
02562     } else {
02563     int coalesceText = (lastChild != NULL) &&
02564         (lastChild->type == XML_TEXT_NODE) &&
02565         (lastChild->name == xmlStringText);
02566     if ((coalesceText) && (ctxt->nodemem != 0)) {
02567         /*
02568          * The whole point of maintaining nodelen and nodemem,
02569          * xmlTextConcat is too costly, i.e. compute length,
02570          * reallocate a new buffer, move data, append ch. Here
02571          * We try to minimaze realloc() uses and avoid copying
02572          * and recomputing length over and over.
02573          */
02574         if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
02575         lastChild->content = xmlStrdup(lastChild->content);
02576         lastChild->properties = NULL;
02577         } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
02578                    (xmlDictOwns(ctxt->dict, lastChild->content))) {
02579         lastChild->content = xmlStrdup(lastChild->content);
02580         }
02581         if (lastChild->content == NULL) {
02582         xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
02583         return;
02584         }
02585             if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
02586                 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
02587                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
02588                 return;
02589             }
02590         if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
02591             (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
02592                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
02593                 return;
02594         }
02595         if (ctxt->nodelen + len >= ctxt->nodemem) {
02596         xmlChar *newbuf;
02597         size_t size;
02598 
02599         size = ctxt->nodemem + len;
02600         size *= 2;
02601                 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
02602         if (newbuf == NULL) {
02603             xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
02604             return;
02605         }
02606         ctxt->nodemem = size;
02607         lastChild->content = newbuf;
02608         }
02609         memcpy(&lastChild->content[ctxt->nodelen], ch, len);
02610         ctxt->nodelen += len;
02611         lastChild->content[ctxt->nodelen] = 0;
02612     } else if (coalesceText) {
02613         if (xmlTextConcat(lastChild, ch, len)) {
02614         xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
02615         }
02616         if (ctxt->node->children != NULL) {
02617         ctxt->nodelen = xmlStrlen(lastChild->content);
02618         ctxt->nodemem = ctxt->nodelen + 1;
02619         }
02620     } else {
02621         /* Mixed content, first time */
02622         lastChild = xmlSAX2TextNode(ctxt, ch, len);
02623         if (lastChild != NULL) {
02624         xmlAddChild(ctxt->node, lastChild);
02625         if (ctxt->node->children != NULL) {
02626             ctxt->nodelen = len;
02627             ctxt->nodemem = len + 1;
02628         }
02629         }
02630     }
02631     }
02632 }
02633 
02634 /**
02635  * xmlSAX2IgnorableWhitespace:
02636  * @ctx: the user data (XML parser context)
02637  * @ch:  a xmlChar string
02638  * @len: the number of xmlChar
02639  *
02640  * receiving some ignorable whitespaces from the parser.
02641  * UNUSED: by default the DOM building will use xmlSAX2Characters
02642  */
02643 void
02644 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
02645 {
02646     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
02647 #ifdef DEBUG_SAX
02648     xmlGenericError(xmlGenericErrorContext,
02649         "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
02650 #endif
02651 }
02652 
02653 /**
02654  * xmlSAX2ProcessingInstruction:
02655  * @ctx: the user data (XML parser context)
02656  * @target:  the target name
02657  * @data: the PI data's
02658  *
02659  * A processing instruction has been parsed.
02660  */
02661 void
02662 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
02663                       const xmlChar *data)
02664 {
02665     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02666     xmlNodePtr ret;
02667     xmlNodePtr parent;
02668 
02669     if (ctx == NULL) return;
02670     parent = ctxt->node;
02671 #ifdef DEBUG_SAX
02672     xmlGenericError(xmlGenericErrorContext,
02673         "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
02674 #endif
02675 
02676     ret = xmlNewDocPI(ctxt->myDoc, target, data);
02677     if (ret == NULL) return;
02678 
02679     if (ctxt->linenumbers) {
02680     if (ctxt->input != NULL) {
02681         if (ctxt->input->line < 65535)
02682         ret->line = (short) ctxt->input->line;
02683         else
02684             ret->line = 65535;
02685     }
02686     }
02687     if (ctxt->inSubset == 1) {
02688     xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
02689     return;
02690     } else if (ctxt->inSubset == 2) {
02691     xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
02692     return;
02693     }
02694     if (parent == NULL) {
02695 #ifdef DEBUG_SAX_TREE
02696         xmlGenericError(xmlGenericErrorContext,
02697             "Setting PI %s as root\n", target);
02698 #endif
02699         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
02700     return;
02701     }
02702     if (parent->type == XML_ELEMENT_NODE) {
02703 #ifdef DEBUG_SAX_TREE
02704     xmlGenericError(xmlGenericErrorContext,
02705         "adding PI %s child to %s\n", target, parent->name);
02706 #endif
02707     xmlAddChild(parent, ret);
02708     } else {
02709 #ifdef DEBUG_SAX_TREE
02710     xmlGenericError(xmlGenericErrorContext,
02711         "adding PI %s sibling to ", target);
02712     xmlDebugDumpOneNode(stderr, parent, 0);
02713 #endif
02714     xmlAddSibling(parent, ret);
02715     }
02716 }
02717 
02718 /**
02719  * xmlSAX2Comment:
02720  * @ctx: the user data (XML parser context)
02721  * @value:  the xmlSAX2Comment content
02722  *
02723  * A xmlSAX2Comment has been parsed.
02724  */
02725 void
02726 xmlSAX2Comment(void *ctx, const xmlChar *value)
02727 {
02728     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02729     xmlNodePtr ret;
02730     xmlNodePtr parent;
02731 
02732     if (ctx == NULL) return;
02733     parent = ctxt->node;
02734 #ifdef DEBUG_SAX
02735     xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
02736 #endif
02737     ret = xmlNewDocComment(ctxt->myDoc, value);
02738     if (ret == NULL) return;
02739     if (ctxt->linenumbers) {
02740     if (ctxt->input != NULL) {
02741         if (ctxt->input->line < 65535)
02742         ret->line = (short) ctxt->input->line;
02743         else
02744             ret->line = 65535;
02745     }
02746     }
02747 
02748     if (ctxt->inSubset == 1) {
02749     xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
02750     return;
02751     } else if (ctxt->inSubset == 2) {
02752     xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
02753     return;
02754     }
02755     if (parent == NULL) {
02756 #ifdef DEBUG_SAX_TREE
02757         xmlGenericError(xmlGenericErrorContext,
02758             "Setting xmlSAX2Comment as root\n");
02759 #endif
02760         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
02761     return;
02762     }
02763     if (parent->type == XML_ELEMENT_NODE) {
02764 #ifdef DEBUG_SAX_TREE
02765     xmlGenericError(xmlGenericErrorContext,
02766         "adding xmlSAX2Comment child to %s\n", parent->name);
02767 #endif
02768     xmlAddChild(parent, ret);
02769     } else {
02770 #ifdef DEBUG_SAX_TREE
02771     xmlGenericError(xmlGenericErrorContext,
02772         "adding xmlSAX2Comment sibling to ");
02773     xmlDebugDumpOneNode(stderr, parent, 0);
02774 #endif
02775     xmlAddSibling(parent, ret);
02776     }
02777 }
02778 
02779 /**
02780  * xmlSAX2CDataBlock:
02781  * @ctx: the user data (XML parser context)
02782  * @value:  The pcdata content
02783  * @len:  the block length
02784  *
02785  * called when a pcdata block has been parsed
02786  */
02787 void
02788 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
02789 {
02790     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
02791     xmlNodePtr ret, lastChild;
02792 
02793     if (ctx == NULL) return;
02794 #ifdef DEBUG_SAX
02795     xmlGenericError(xmlGenericErrorContext,
02796         "SAX.pcdata(%.10s, %d)\n", value, len);
02797 #endif
02798     lastChild = xmlGetLastChild(ctxt->node);
02799 #ifdef DEBUG_SAX_TREE
02800     xmlGenericError(xmlGenericErrorContext,
02801         "add chars to %s \n", ctxt->node->name);
02802 #endif
02803     if ((lastChild != NULL) &&
02804         (lastChild->type == XML_CDATA_SECTION_NODE)) {
02805     xmlTextConcat(lastChild, value, len);
02806     } else {
02807     ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
02808     xmlAddChild(ctxt->node, ret);
02809     }
02810 }
02811 
02812 static int xmlSAX2DefaultVersionValue = 2;
02813 
02814 #ifdef LIBXML_SAX1_ENABLED
02815 /**
02816  * xmlSAXDefaultVersion:
02817  * @version:  the version, 1 or 2
02818  *
02819  * Set the default version of SAX used globally by the library.
02820  * By default, during initialization the default is set to 2.
02821  * Note that it is generally a better coding style to use
02822  * xmlSAXVersion() to set up the version explicitly for a given
02823  * parsing context.
02824  *
02825  * Returns the previous value in case of success and -1 in case of error.
02826  */
02827 int
02828 xmlSAXDefaultVersion(int version)
02829 {
02830     int ret = xmlSAX2DefaultVersionValue;
02831 
02832     if ((version != 1) && (version != 2))
02833         return(-1);
02834     xmlSAX2DefaultVersionValue = version;
02835     return(ret);
02836 }
02837 #endif /* LIBXML_SAX1_ENABLED */
02838 
02839 /**
02840  * xmlSAXVersion:
02841  * @hdlr:  the SAX handler
02842  * @version:  the version, 1 or 2
02843  *
02844  * Initialize the default XML SAX handler according to the version
02845  *
02846  * Returns 0 in case of success and -1 in case of error.
02847  */
02848 int
02849 xmlSAXVersion(xmlSAXHandler *hdlr, int version)
02850 {
02851     if (hdlr == NULL) return(-1);
02852     if (version == 2) {
02853     hdlr->startElement = NULL;
02854     hdlr->endElement = NULL;
02855     hdlr->startElementNs = xmlSAX2StartElementNs;
02856     hdlr->endElementNs = xmlSAX2EndElementNs;
02857     hdlr->serror = NULL;
02858     hdlr->initialized = XML_SAX2_MAGIC;
02859 #ifdef LIBXML_SAX1_ENABLED
02860     } else if (version == 1) {
02861     hdlr->startElement = xmlSAX2StartElement;
02862     hdlr->endElement = xmlSAX2EndElement;
02863     hdlr->initialized = 1;
02864 #endif /* LIBXML_SAX1_ENABLED */
02865     } else
02866         return(-1);
02867     hdlr->internalSubset = xmlSAX2InternalSubset;
02868     hdlr->externalSubset = xmlSAX2ExternalSubset;
02869     hdlr->isStandalone = xmlSAX2IsStandalone;
02870     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
02871     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
02872     hdlr->resolveEntity = xmlSAX2ResolveEntity;
02873     hdlr->getEntity = xmlSAX2GetEntity;
02874     hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
02875     hdlr->entityDecl = xmlSAX2EntityDecl;
02876     hdlr->attributeDecl = xmlSAX2AttributeDecl;
02877     hdlr->elementDecl = xmlSAX2ElementDecl;
02878     hdlr->notationDecl = xmlSAX2NotationDecl;
02879     hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
02880     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
02881     hdlr->startDocument = xmlSAX2StartDocument;
02882     hdlr->endDocument = xmlSAX2EndDocument;
02883     hdlr->reference = xmlSAX2Reference;
02884     hdlr->characters = xmlSAX2Characters;
02885     hdlr->cdataBlock = xmlSAX2CDataBlock;
02886     hdlr->ignorableWhitespace = xmlSAX2Characters;
02887     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
02888     hdlr->comment = xmlSAX2Comment;
02889     hdlr->warning = xmlParserWarning;
02890     hdlr->error = xmlParserError;
02891     hdlr->fatalError = xmlParserError;
02892 
02893     return(0);
02894 }
02895 
02896 /**
02897  * xmlSAX2InitDefaultSAXHandler:
02898  * @hdlr:  the SAX handler
02899  * @warning:  flag if non-zero sets the handler warning procedure
02900  *
02901  * Initialize the default XML SAX2 handler
02902  */
02903 void
02904 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
02905 {
02906     if ((hdlr == NULL) || (hdlr->initialized != 0))
02907     return;
02908 
02909     xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
02910     if (warning == 0)
02911     hdlr->warning = NULL;
02912     else
02913     hdlr->warning = xmlParserWarning;
02914 }
02915 
02916 /**
02917  * xmlDefaultSAXHandlerInit:
02918  *
02919  * Initialize the default SAX2 handler
02920  */
02921 void
02922 xmlDefaultSAXHandlerInit(void)
02923 {
02924 #ifdef LIBXML_SAX1_ENABLED
02925     xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
02926 #endif /* LIBXML_SAX1_ENABLED */
02927 }
02928 
02929 #ifdef LIBXML_HTML_ENABLED
02930 
02931 /**
02932  * xmlSAX2InitHtmlDefaultSAXHandler:
02933  * @hdlr:  the SAX handler
02934  *
02935  * Initialize the default HTML SAX2 handler
02936  */
02937 void
02938 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
02939 {
02940     if ((hdlr == NULL) || (hdlr->initialized != 0))
02941     return;
02942 
02943     hdlr->internalSubset = xmlSAX2InternalSubset;
02944     hdlr->externalSubset = NULL;
02945     hdlr->isStandalone = NULL;
02946     hdlr->hasInternalSubset = NULL;
02947     hdlr->hasExternalSubset = NULL;
02948     hdlr->resolveEntity = NULL;
02949     hdlr->getEntity = xmlSAX2GetEntity;
02950     hdlr->getParameterEntity = NULL;
02951     hdlr->entityDecl = NULL;
02952     hdlr->attributeDecl = NULL;
02953     hdlr->elementDecl = NULL;
02954     hdlr->notationDecl = NULL;
02955     hdlr->unparsedEntityDecl = NULL;
02956     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
02957     hdlr->startDocument = xmlSAX2StartDocument;
02958     hdlr->endDocument = xmlSAX2EndDocument;
02959     hdlr->startElement = xmlSAX2StartElement;
02960     hdlr->endElement = xmlSAX2EndElement;
02961     hdlr->reference = NULL;
02962     hdlr->characters = xmlSAX2Characters;
02963     hdlr->cdataBlock = xmlSAX2CDataBlock;
02964     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
02965     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
02966     hdlr->comment = xmlSAX2Comment;
02967     hdlr->warning = xmlParserWarning;
02968     hdlr->error = xmlParserError;
02969     hdlr->fatalError = xmlParserError;
02970 
02971     hdlr->initialized = 1;
02972 }
02973 
02974 /**
02975  * htmlDefaultSAXHandlerInit:
02976  *
02977  * Initialize the default SAX handler
02978  */
02979 void
02980 htmlDefaultSAXHandlerInit(void)
02981 {
02982     xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
02983 }
02984 
02985 #endif /* LIBXML_HTML_ENABLED */
02986 
02987 #ifdef LIBXML_DOCB_ENABLED
02988 
02989 /**
02990  * xmlSAX2InitDocbDefaultSAXHandler:
02991  * @hdlr:  the SAX handler
02992  *
02993  * Initialize the default DocBook SAX2 handler
02994  */
02995 void
02996 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
02997 {
02998     if ((hdlr == NULL) || (hdlr->initialized != 0))
02999     return;
03000 
03001     hdlr->internalSubset = xmlSAX2InternalSubset;
03002     hdlr->externalSubset = NULL;
03003     hdlr->isStandalone = xmlSAX2IsStandalone;
03004     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
03005     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
03006     hdlr->resolveEntity = xmlSAX2ResolveEntity;
03007     hdlr->getEntity = xmlSAX2GetEntity;
03008     hdlr->getParameterEntity = NULL;
03009     hdlr->entityDecl = xmlSAX2EntityDecl;
03010     hdlr->attributeDecl = NULL;
03011     hdlr->elementDecl = NULL;
03012     hdlr->notationDecl = NULL;
03013     hdlr->unparsedEntityDecl = NULL;
03014     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
03015     hdlr->startDocument = xmlSAX2StartDocument;
03016     hdlr->endDocument = xmlSAX2EndDocument;
03017     hdlr->startElement = xmlSAX2StartElement;
03018     hdlr->endElement = xmlSAX2EndElement;
03019     hdlr->reference = xmlSAX2Reference;
03020     hdlr->characters = xmlSAX2Characters;
03021     hdlr->cdataBlock = NULL;
03022     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
03023     hdlr->processingInstruction = NULL;
03024     hdlr->comment = xmlSAX2Comment;
03025     hdlr->warning = xmlParserWarning;
03026     hdlr->error = xmlParserError;
03027     hdlr->fatalError = xmlParserError;
03028 
03029     hdlr->initialized = 1;
03030 }
03031 
03032 /**
03033  * docbDefaultSAXHandlerInit:
03034  *
03035  * Initialize the default SAX handler
03036  */
03037 void
03038 docbDefaultSAXHandlerInit(void)
03039 {
03040     xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
03041 }
03042 
03043 #endif /* LIBXML_DOCB_ENABLED */
03044 #define bottom_SAX2
03045 #include "elfgcchack.h"
03046