Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * SAX2.c : Default SAX2 handler to build a tree.
      3  *
      4  * See Copyright for the status of this software.
      5  *
      6  * Daniel Veillard <daniel (at) veillard.com>
      7  */
      8 
      9 
     10 #define IN_LIBXML
     11 #include "libxml.h"
     12 #include <stdlib.h>
     13 #include <string.h>
     14 #include <limits.h>
     15 #include <libxml/xmlmemory.h>
     16 #include <libxml/tree.h>
     17 #include <libxml/parser.h>
     18 #include <libxml/parserInternals.h>
     19 #include <libxml/valid.h>
     20 #include <libxml/entities.h>
     21 #include <libxml/xmlerror.h>
     22 #include <libxml/debugXML.h>
     23 #include <libxml/xmlIO.h>
     24 #include <libxml/SAX.h>
     25 #include <libxml/uri.h>
     26 #include <libxml/valid.h>
     27 #include <libxml/HTMLtree.h>
     28 #include <libxml/globals.h>
     29 
     30 /* Define SIZE_T_MAX unless defined through <limits.h>. */
     31 #ifndef SIZE_T_MAX
     32 # define SIZE_T_MAX     ((size_t)-1)
     33 #endif /* !SIZE_T_MAX */
     34 
     35 /* #define DEBUG_SAX2 */
     36 /* #define DEBUG_SAX2_TREE */
     37 
     38 /**
     39  * TODO:
     40  *
     41  * macro to flag unimplemented blocks
     42  * XML_CATALOG_PREFER user env to select between system/public prefered
     43  * option. C.f. Richard Tobin <richard (at) cogsci.ed.ac.uk>
     44  *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
     45  *> values "system" and "public".  I have made the default be "system" to
     46  *> match yours.
     47  */
     48 #define TODO 								\
     49     xmlGenericError(xmlGenericErrorContext,				\
     50 	    "Unimplemented block at %s:%d\n",				\
     51             __FILE__, __LINE__);
     52 
     53 /*
     54  * xmlSAX2ErrMemory:
     55  * @ctxt:  an XML validation parser context
     56  * @msg:   a string to accompany the error message
     57  */
     58 static void
     59 xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
     60     if (ctxt != NULL) {
     61 	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
     62 	    ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
     63 	ctxt->errNo = XML_ERR_NO_MEMORY;
     64 	ctxt->instate = XML_PARSER_EOF;
     65 	ctxt->disableSAX = 1;
     66     }
     67 }
     68 
     69 /**
     70  * xmlValidError:
     71  * @ctxt:  an XML validation parser context
     72  * @error:  the error number
     73  * @msg:  the error message
     74  * @str1:  extra data
     75  * @str2:  extra data
     76  *
     77  * Handle a validation error
     78  */
     79 static void
     80 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
     81             const char *msg, const char *str1, const char *str2)
     82 {
     83     xmlStructuredErrorFunc schannel = NULL;
     84 
     85     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
     86         (ctxt->instate == XML_PARSER_EOF))
     87 	return;
     88     if (ctxt != NULL) {
     89 	ctxt->errNo = error;
     90 	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
     91 	    schannel = ctxt->sax->serror;
     92 	__xmlRaiseError(schannel,
     93 			ctxt->vctxt.error, ctxt->vctxt.userData,
     94 			ctxt, NULL, XML_FROM_DTD, error,
     95 			XML_ERR_ERROR, NULL, 0, (const char *) str1,
     96 			(const char *) str2, NULL, 0, 0,
     97 			msg, (const char *) str1, (const char *) str2);
     98 	ctxt->valid = 0;
     99     } else {
    100 	__xmlRaiseError(schannel,
    101 			NULL, NULL,
    102 			ctxt, NULL, XML_FROM_DTD, error,
    103 			XML_ERR_ERROR, NULL, 0, (const char *) str1,
    104 			(const char *) str2, NULL, 0, 0,
    105 			msg, (const char *) str1, (const char *) str2);
    106     }
    107 }
    108 
    109 /**
    110  * xmlFatalErrMsg:
    111  * @ctxt:  an XML parser context
    112  * @error:  the error number
    113  * @msg:  the error message
    114  * @str1:  an error string
    115  * @str2:  an error string
    116  *
    117  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
    118  */
    119 static void
    120 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    121                const char *msg, const xmlChar *str1, const xmlChar *str2)
    122 {
    123     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
    124         (ctxt->instate == XML_PARSER_EOF))
    125 	return;
    126     if (ctxt != NULL)
    127 	ctxt->errNo = error;
    128     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
    129                     XML_ERR_FATAL, NULL, 0,
    130 		    (const char *) str1, (const char *) str2,
    131 		    NULL, 0, 0, msg, str1, str2);
    132     if (ctxt != NULL) {
    133 	ctxt->wellFormed = 0;
    134 	ctxt->valid = 0;
    135 	if (ctxt->recovery == 0)
    136 	    ctxt->disableSAX = 1;
    137     }
    138 }
    139 
    140 /**
    141  * xmlWarnMsg:
    142  * @ctxt:  an XML parser context
    143  * @error:  the error number
    144  * @msg:  the error message
    145  * @str1:  an error string
    146  * @str2:  an error string
    147  *
    148  * Handle a parser warning
    149  */
    150 static void
    151 xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    152                const char *msg, const xmlChar *str1)
    153 {
    154     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
    155         (ctxt->instate == XML_PARSER_EOF))
    156 	return;
    157     if (ctxt != NULL)
    158 	ctxt->errNo = error;
    159     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
    160                     XML_ERR_WARNING, NULL, 0,
    161 		    (const char *) str1, NULL,
    162 		    NULL, 0, 0, msg, str1);
    163 }
    164 
    165 /**
    166  * xmlNsErrMsg:
    167  * @ctxt:  an XML parser context
    168  * @error:  the error number
    169  * @msg:  the error message
    170  * @str1:  an error string
    171  * @str2:  an error string
    172  *
    173  * Handle a namespace error
    174  */
    175 static void
    176 xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    177             const char *msg, const xmlChar *str1, const xmlChar *str2)
    178 {
    179     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
    180         (ctxt->instate == XML_PARSER_EOF))
    181 	return;
    182     if (ctxt != NULL)
    183 	ctxt->errNo = error;
    184     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
    185                     XML_ERR_ERROR, NULL, 0,
    186 		    (const char *) str1, (const char *) str2,
    187 		    NULL, 0, 0, msg, str1, str2);
    188 }
    189 
    190 /**
    191  * xmlNsWarnMsg:
    192  * @ctxt:  an XML parser context
    193  * @error:  the error number
    194  * @msg:  the error message
    195  * @str1:  an error string
    196  *
    197  * Handle a namespace warning
    198  */
    199 static void
    200 xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
    201              const char *msg, const xmlChar *str1, const xmlChar *str2)
    202 {
    203     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
    204         (ctxt->instate == XML_PARSER_EOF))
    205 	return;
    206     if (ctxt != NULL)
    207 	ctxt->errNo = error;
    208     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
    209                     XML_ERR_WARNING, NULL, 0,
    210 		    (const char *) str1, (const char *) str2,
    211 		    NULL, 0, 0, msg, str1, str2);
    212 }
    213 
    214 /**
    215  * xmlSAX2GetPublicId:
    216  * @ctx: the user data (XML parser context)
    217  *
    218  * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
    219  *
    220  * Returns a xmlChar *
    221  */
    222 const xmlChar *
    223 xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
    224 {
    225     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
    226     return(NULL);
    227 }
    228 
    229 /**
    230  * xmlSAX2GetSystemId:
    231  * @ctx: the user data (XML parser context)
    232  *
    233  * Provides the system ID, basically URL or filename e.g.
    234  * http://www.sgmlsource.com/dtds/memo.dtd
    235  *
    236  * Returns a xmlChar *
    237  */
    238 const xmlChar *
    239 xmlSAX2GetSystemId(void *ctx)
    240 {
    241     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    242     if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
    243     return((const xmlChar *) ctxt->input->filename);
    244 }
    245 
    246 /**
    247  * xmlSAX2GetLineNumber:
    248  * @ctx: the user data (XML parser context)
    249  *
    250  * Provide the line number of the current parsing point.
    251  *
    252  * Returns an int
    253  */
    254 int
    255 xmlSAX2GetLineNumber(void *ctx)
    256 {
    257     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    258     if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
    259     return(ctxt->input->line);
    260 }
    261 
    262 /**
    263  * xmlSAX2GetColumnNumber:
    264  * @ctx: the user data (XML parser context)
    265  *
    266  * Provide the column number of the current parsing point.
    267  *
    268  * Returns an int
    269  */
    270 int
    271 xmlSAX2GetColumnNumber(void *ctx)
    272 {
    273     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    274     if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
    275     return(ctxt->input->col);
    276 }
    277 
    278 /**
    279  * xmlSAX2IsStandalone:
    280  * @ctx: the user data (XML parser context)
    281  *
    282  * Is this document tagged standalone ?
    283  *
    284  * Returns 1 if true
    285  */
    286 int
    287 xmlSAX2IsStandalone(void *ctx)
    288 {
    289     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    290     if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
    291     return(ctxt->myDoc->standalone == 1);
    292 }
    293 
    294 /**
    295  * xmlSAX2HasInternalSubset:
    296  * @ctx: the user data (XML parser context)
    297  *
    298  * Does this document has an internal subset
    299  *
    300  * Returns 1 if true
    301  */
    302 int
    303 xmlSAX2HasInternalSubset(void *ctx)
    304 {
    305     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    306     if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
    307     return(ctxt->myDoc->intSubset != NULL);
    308 }
    309 
    310 /**
    311  * xmlSAX2HasExternalSubset:
    312  * @ctx: the user data (XML parser context)
    313  *
    314  * Does this document has an external subset
    315  *
    316  * Returns 1 if true
    317  */
    318 int
    319 xmlSAX2HasExternalSubset(void *ctx)
    320 {
    321     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    322     if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
    323     return(ctxt->myDoc->extSubset != NULL);
    324 }
    325 
    326 /**
    327  * xmlSAX2InternalSubset:
    328  * @ctx:  the user data (XML parser context)
    329  * @name:  the root element name
    330  * @ExternalID:  the external ID
    331  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
    332  *
    333  * Callback on internal subset declaration.
    334  */
    335 void
    336 xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
    337 	       const xmlChar *ExternalID, const xmlChar *SystemID)
    338 {
    339     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    340     xmlDtdPtr dtd;
    341     if (ctx == NULL) return;
    342 #ifdef DEBUG_SAX
    343     xmlGenericError(xmlGenericErrorContext,
    344 	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
    345             name, ExternalID, SystemID);
    346 #endif
    347 
    348     if (ctxt->myDoc == NULL)
    349 	return;
    350     dtd = xmlGetIntSubset(ctxt->myDoc);
    351     if (dtd != NULL) {
    352 	if (ctxt->html)
    353 	    return;
    354 	xmlUnlinkNode((xmlNodePtr) dtd);
    355 	xmlFreeDtd(dtd);
    356 	ctxt->myDoc->intSubset = NULL;
    357     }
    358     ctxt->myDoc->intSubset =
    359 	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
    360     if (ctxt->myDoc->intSubset == NULL)
    361         xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
    362 }
    363 
    364 /**
    365  * xmlSAX2ExternalSubset:
    366  * @ctx: the user data (XML parser context)
    367  * @name:  the root element name
    368  * @ExternalID:  the external ID
    369  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
    370  *
    371  * Callback on external subset declaration.
    372  */
    373 void
    374 xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
    375 	       const xmlChar *ExternalID, const xmlChar *SystemID)
    376 {
    377     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    378     if (ctx == NULL) return;
    379 #ifdef DEBUG_SAX
    380     xmlGenericError(xmlGenericErrorContext,
    381 	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
    382             name, ExternalID, SystemID);
    383 #endif
    384     if (((ExternalID != NULL) || (SystemID != NULL)) &&
    385         (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
    386 	 (ctxt->wellFormed && ctxt->myDoc))) {
    387 	/*
    388 	 * Try to fetch and parse the external subset.
    389 	 */
    390 	xmlParserInputPtr oldinput;
    391 	int oldinputNr;
    392 	int oldinputMax;
    393 	xmlParserInputPtr *oldinputTab;
    394 	xmlParserInputPtr input = NULL;
    395 	xmlCharEncoding enc;
    396 	int oldcharset;
    397 
    398 	/*
    399 	 * Ask the Entity resolver to load the damn thing
    400 	 */
    401 	if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
    402 	    input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
    403 	                                        SystemID);
    404 	if (input == NULL) {
    405 	    return;
    406 	}
    407 
    408 	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
    409 
    410 	/*
    411 	 * make sure we won't destroy the main document context
    412 	 */
    413 	oldinput = ctxt->input;
    414 	oldinputNr = ctxt->inputNr;
    415 	oldinputMax = ctxt->inputMax;
    416 	oldinputTab = ctxt->inputTab;
    417 	oldcharset = ctxt->charset;
    418 
    419 	ctxt->inputTab = (xmlParserInputPtr *)
    420 	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
    421 	if (ctxt->inputTab == NULL) {
    422 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
    423 	    ctxt->input = oldinput;
    424 	    ctxt->inputNr = oldinputNr;
    425 	    ctxt->inputMax = oldinputMax;
    426 	    ctxt->inputTab = oldinputTab;
    427 	    ctxt->charset = oldcharset;
    428 	    return;
    429 	}
    430 	ctxt->inputNr = 0;
    431 	ctxt->inputMax = 5;
    432 	ctxt->input = NULL;
    433 	xmlPushInput(ctxt, input);
    434 
    435 	/*
    436 	 * On the fly encoding conversion if needed
    437 	 */
    438 	if (ctxt->input->length >= 4) {
    439 	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
    440 	    xmlSwitchEncoding(ctxt, enc);
    441 	}
    442 
    443 	if (input->filename == NULL)
    444 	    input->filename = (char *) xmlCanonicPath(SystemID);
    445 	input->line = 1;
    446 	input->col = 1;
    447 	input->base = ctxt->input->cur;
    448 	input->cur = ctxt->input->cur;
    449 	input->free = NULL;
    450 
    451 	/*
    452 	 * let's parse that entity knowing it's an external subset.
    453 	 */
    454 	xmlParseExternalSubset(ctxt, ExternalID, SystemID);
    455 
    456         /*
    457 	 * Free up the external entities
    458 	 */
    459 
    460 	while (ctxt->inputNr > 1)
    461 	    xmlPopInput(ctxt);
    462 	xmlFreeInputStream(ctxt->input);
    463         xmlFree(ctxt->inputTab);
    464 
    465 	/*
    466 	 * Restore the parsing context of the main entity
    467 	 */
    468 	ctxt->input = oldinput;
    469 	ctxt->inputNr = oldinputNr;
    470 	ctxt->inputMax = oldinputMax;
    471 	ctxt->inputTab = oldinputTab;
    472 	ctxt->charset = oldcharset;
    473 	/* ctxt->wellFormed = oldwellFormed; */
    474     }
    475 }
    476 
    477 /**
    478  * xmlSAX2ResolveEntity:
    479  * @ctx: the user data (XML parser context)
    480  * @publicId: The public ID of the entity
    481  * @systemId: The system ID of the entity
    482  *
    483  * The entity loader, to control the loading of external entities,
    484  * the application can either:
    485  *    - override this xmlSAX2ResolveEntity() callback in the SAX block
    486  *    - or better use the xmlSetExternalEntityLoader() function to
    487  *      set up it's own entity resolution routine
    488  *
    489  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
    490  */
    491 xmlParserInputPtr
    492 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
    493 {
    494     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    495     xmlParserInputPtr ret;
    496     xmlChar *URI;
    497     const char *base = NULL;
    498 
    499     if (ctx == NULL) return(NULL);
    500     if (ctxt->input != NULL)
    501 	base = ctxt->input->filename;
    502     if (base == NULL)
    503 	base = ctxt->directory;
    504 
    505     URI = xmlBuildURI(systemId, (const xmlChar *) base);
    506 
    507 #ifdef DEBUG_SAX
    508     xmlGenericError(xmlGenericErrorContext,
    509 	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
    510 #endif
    511 
    512     ret = xmlLoadExternalEntity((const char *) URI,
    513 				(const char *) publicId, ctxt);
    514     if (URI != NULL)
    515 	xmlFree(URI);
    516     return(ret);
    517 }
    518 
    519 /**
    520  * xmlSAX2GetEntity:
    521  * @ctx: the user data (XML parser context)
    522  * @name: The entity name
    523  *
    524  * Get an entity by name
    525  *
    526  * Returns the xmlEntityPtr if found.
    527  */
    528 xmlEntityPtr
    529 xmlSAX2GetEntity(void *ctx, const xmlChar *name)
    530 {
    531     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    532     xmlEntityPtr ret = NULL;
    533 
    534     if (ctx == NULL) return(NULL);
    535 #ifdef DEBUG_SAX
    536     xmlGenericError(xmlGenericErrorContext,
    537 	    "SAX.xmlSAX2GetEntity(%s)\n", name);
    538 #endif
    539 
    540     if (ctxt->inSubset == 0) {
    541 	ret = xmlGetPredefinedEntity(name);
    542 	if (ret != NULL)
    543 	    return(ret);
    544     }
    545     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
    546 	if (ctxt->inSubset == 2) {
    547 	    ctxt->myDoc->standalone = 0;
    548 	    ret = xmlGetDocEntity(ctxt->myDoc, name);
    549 	    ctxt->myDoc->standalone = 1;
    550 	} else {
    551 	    ret = xmlGetDocEntity(ctxt->myDoc, name);
    552 	    if (ret == NULL) {
    553 		ctxt->myDoc->standalone = 0;
    554 		ret = xmlGetDocEntity(ctxt->myDoc, name);
    555 		if (ret != NULL) {
    556 		    xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
    557 	 "Entity(%s) document marked standalone but requires external subset\n",
    558 				   name, NULL);
    559 		}
    560 		ctxt->myDoc->standalone = 1;
    561 	    }
    562 	}
    563     } else {
    564 	ret = xmlGetDocEntity(ctxt->myDoc, name);
    565     }
    566     if ((ret != NULL) &&
    567 	((ctxt->validate) || (ctxt->replaceEntities)) &&
    568 	(ret->children == NULL) &&
    569 	(ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
    570 	int val;
    571 
    572 	/*
    573 	 * for validation purposes we really need to fetch and
    574 	 * parse the external entity
    575 	 */
    576 	xmlNodePtr children;
    577 
    578         val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
    579 		                         ret->ExternalID, &children);
    580 	if (val == 0) {
    581 	    xmlAddChildList((xmlNodePtr) ret, children);
    582 	} else {
    583 	    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
    584 		           "Failure to process entity %s\n", name, NULL);
    585 	    ctxt->validate = 0;
    586 	    return(NULL);
    587 	}
    588 	ret->owner = 1;
    589 	if (ret->checked == 0)
    590 	    ret->checked = 1;
    591     }
    592     return(ret);
    593 }
    594 
    595 /**
    596  * xmlSAX2GetParameterEntity:
    597  * @ctx: the user data (XML parser context)
    598  * @name: The entity name
    599  *
    600  * Get a parameter entity by name
    601  *
    602  * Returns the xmlEntityPtr if found.
    603  */
    604 xmlEntityPtr
    605 xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
    606 {
    607     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    608     xmlEntityPtr ret;
    609 
    610     if (ctx == NULL) return(NULL);
    611 #ifdef DEBUG_SAX
    612     xmlGenericError(xmlGenericErrorContext,
    613 	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
    614 #endif
    615 
    616     ret = xmlGetParameterEntity(ctxt->myDoc, name);
    617     return(ret);
    618 }
    619 
    620 
    621 /**
    622  * xmlSAX2EntityDecl:
    623  * @ctx: the user data (XML parser context)
    624  * @name:  the entity name
    625  * @type:  the entity type
    626  * @publicId: The public ID of the entity
    627  * @systemId: The system ID of the entity
    628  * @content: the entity value (without processing).
    629  *
    630  * An entity definition has been parsed
    631  */
    632 void
    633 xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
    634           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
    635 {
    636     xmlEntityPtr ent;
    637     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    638 
    639     if (ctx == NULL) return;
    640 #ifdef DEBUG_SAX
    641     xmlGenericError(xmlGenericErrorContext,
    642 	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
    643             name, type, publicId, systemId, content);
    644 #endif
    645     if (ctxt->inSubset == 1) {
    646 	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
    647 		              systemId, content);
    648 	if ((ent == NULL) && (ctxt->pedantic))
    649 	    xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
    650 	     "Entity(%s) already defined in the internal subset\n",
    651 	               name);
    652 	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
    653 	    xmlChar *URI;
    654 	    const char *base = NULL;
    655 
    656 	    if (ctxt->input != NULL)
    657 		base = ctxt->input->filename;
    658 	    if (base == NULL)
    659 		base = ctxt->directory;
    660 
    661 	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
    662 	    ent->URI = URI;
    663 	}
    664     } else if (ctxt->inSubset == 2) {
    665 	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
    666 		              systemId, content);
    667 	if ((ent == NULL) && (ctxt->pedantic) &&
    668 	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
    669 	    ctxt->sax->warning(ctxt->userData,
    670 	     "Entity(%s) already defined in the external subset\n", name);
    671 	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
    672 	    xmlChar *URI;
    673 	    const char *base = NULL;
    674 
    675 	    if (ctxt->input != NULL)
    676 		base = ctxt->input->filename;
    677 	    if (base == NULL)
    678 		base = ctxt->directory;
    679 
    680 	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
    681 	    ent->URI = URI;
    682 	}
    683     } else {
    684 	xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
    685 	               "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
    686 		       name, NULL);
    687     }
    688 }
    689 
    690 /**
    691  * xmlSAX2AttributeDecl:
    692  * @ctx: the user data (XML parser context)
    693  * @elem:  the name of the element
    694  * @fullname:  the attribute name
    695  * @type:  the attribute type
    696  * @def:  the type of default value
    697  * @defaultValue: the attribute default value
    698  * @tree:  the tree of enumerated value set
    699  *
    700  * An attribute definition has been parsed
    701  */
    702 void
    703 xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
    704               int type, int def, const xmlChar *defaultValue,
    705 	      xmlEnumerationPtr tree)
    706 {
    707     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    708     xmlAttributePtr attr;
    709     xmlChar *name = NULL, *prefix = NULL;
    710 
    711     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
    712         return;
    713 
    714 #ifdef DEBUG_SAX
    715     xmlGenericError(xmlGenericErrorContext,
    716 	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
    717             elem, fullname, type, def, defaultValue);
    718 #endif
    719     if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
    720         (type != XML_ATTRIBUTE_ID)) {
    721 	/*
    722 	 * Raise the error but keep the validity flag
    723 	 */
    724 	int tmp = ctxt->valid;
    725 	xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
    726 	      "xml:id : attribute type should be ID\n", NULL, NULL);
    727 	ctxt->valid = tmp;
    728     }
    729     /* TODO: optimize name/prefix allocation */
    730     name = xmlSplitQName(ctxt, fullname, &prefix);
    731     ctxt->vctxt.valid = 1;
    732     if (ctxt->inSubset == 1)
    733 	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
    734 	       name, prefix, (xmlAttributeType) type,
    735 	       (xmlAttributeDefault) def, defaultValue, tree);
    736     else if (ctxt->inSubset == 2)
    737 	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
    738 	   name, prefix, (xmlAttributeType) type,
    739 	   (xmlAttributeDefault) def, defaultValue, tree);
    740     else {
    741         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
    742 	     "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
    743 	               name, NULL);
    744 	xmlFreeEnumeration(tree);
    745 	return;
    746     }
    747 #ifdef LIBXML_VALID_ENABLED
    748     if (ctxt->vctxt.valid == 0)
    749 	ctxt->valid = 0;
    750     if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
    751         (ctxt->myDoc->intSubset != NULL))
    752 	ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
    753 	                                        attr);
    754 #endif /* LIBXML_VALID_ENABLED */
    755     if (prefix != NULL)
    756 	xmlFree(prefix);
    757     if (name != NULL)
    758 	xmlFree(name);
    759 }
    760 
    761 /**
    762  * xmlSAX2ElementDecl:
    763  * @ctx: the user data (XML parser context)
    764  * @name:  the element name
    765  * @type:  the element type
    766  * @content: the element value tree
    767  *
    768  * An element definition has been parsed
    769  */
    770 void
    771 xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
    772             xmlElementContentPtr content)
    773 {
    774     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    775     xmlElementPtr elem = NULL;
    776 
    777     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
    778         return;
    779 
    780 #ifdef DEBUG_SAX
    781     xmlGenericError(xmlGenericErrorContext,
    782                     "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
    783 #endif
    784 
    785     if (ctxt->inSubset == 1)
    786         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
    787                                  name, (xmlElementTypeVal) type, content);
    788     else if (ctxt->inSubset == 2)
    789         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
    790                                  name, (xmlElementTypeVal) type, content);
    791     else {
    792         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
    793 	     "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
    794 	               name, NULL);
    795         return;
    796     }
    797 #ifdef LIBXML_VALID_ENABLED
    798     if (elem == NULL)
    799         ctxt->valid = 0;
    800     if (ctxt->validate && ctxt->wellFormed &&
    801         ctxt->myDoc && ctxt->myDoc->intSubset)
    802         ctxt->valid &=
    803             xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
    804 #endif /* LIBXML_VALID_ENABLED */
    805 }
    806 
    807 /**
    808  * xmlSAX2NotationDecl:
    809  * @ctx: the user data (XML parser context)
    810  * @name: The name of the notation
    811  * @publicId: The public ID of the entity
    812  * @systemId: The system ID of the entity
    813  *
    814  * What to do when a notation declaration has been parsed.
    815  */
    816 void
    817 xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
    818 	     const xmlChar *publicId, const xmlChar *systemId)
    819 {
    820     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    821     xmlNotationPtr nota = NULL;
    822 
    823     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
    824         return;
    825 
    826 #ifdef DEBUG_SAX
    827     xmlGenericError(xmlGenericErrorContext,
    828 	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
    829 #endif
    830 
    831     if ((publicId == NULL) && (systemId == NULL)) {
    832 	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
    833 	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
    834 	               name, NULL);
    835 	return;
    836     } else if (ctxt->inSubset == 1)
    837 	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
    838                               publicId, systemId);
    839     else if (ctxt->inSubset == 2)
    840 	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
    841                               publicId, systemId);
    842     else {
    843 	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
    844 	     "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
    845 	               name, NULL);
    846 	return;
    847     }
    848 #ifdef LIBXML_VALID_ENABLED
    849     if (nota == NULL) ctxt->valid = 0;
    850     if ((ctxt->validate) && (ctxt->wellFormed) &&
    851         (ctxt->myDoc->intSubset != NULL))
    852 	ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
    853 	                                       nota);
    854 #endif /* LIBXML_VALID_ENABLED */
    855 }
    856 
    857 /**
    858  * xmlSAX2UnparsedEntityDecl:
    859  * @ctx: the user data (XML parser context)
    860  * @name: The name of the entity
    861  * @publicId: The public ID of the entity
    862  * @systemId: The system ID of the entity
    863  * @notationName: the name of the notation
    864  *
    865  * What to do when an unparsed entity declaration is parsed
    866  */
    867 void
    868 xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
    869 		   const xmlChar *publicId, const xmlChar *systemId,
    870 		   const xmlChar *notationName)
    871 {
    872     xmlEntityPtr ent;
    873     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    874     if (ctx == NULL) return;
    875 #ifdef DEBUG_SAX
    876     xmlGenericError(xmlGenericErrorContext,
    877 	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
    878             name, publicId, systemId, notationName);
    879 #endif
    880     if (ctxt->inSubset == 1) {
    881 	ent = xmlAddDocEntity(ctxt->myDoc, name,
    882 			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
    883 			publicId, systemId, notationName);
    884 	if ((ent == NULL) && (ctxt->pedantic) &&
    885 	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
    886 	    ctxt->sax->warning(ctxt->userData,
    887 	     "Entity(%s) already defined in the internal subset\n", name);
    888 	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
    889 	    xmlChar *URI;
    890 	    const char *base = NULL;
    891 
    892 	    if (ctxt->input != NULL)
    893 		base = ctxt->input->filename;
    894 	    if (base == NULL)
    895 		base = ctxt->directory;
    896 
    897 	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
    898 	    ent->URI = URI;
    899 	}
    900     } else if (ctxt->inSubset == 2) {
    901 	ent = xmlAddDtdEntity(ctxt->myDoc, name,
    902 			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
    903 			publicId, systemId, notationName);
    904 	if ((ent == NULL) && (ctxt->pedantic) &&
    905 	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
    906 	    ctxt->sax->warning(ctxt->userData,
    907 	     "Entity(%s) already defined in the external subset\n", name);
    908 	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
    909 	    xmlChar *URI;
    910 	    const char *base = NULL;
    911 
    912 	    if (ctxt->input != NULL)
    913 		base = ctxt->input->filename;
    914 	    if (base == NULL)
    915 		base = ctxt->directory;
    916 
    917 	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
    918 	    ent->URI = URI;
    919 	}
    920     } else {
    921         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
    922 	     "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
    923 	               name, NULL);
    924     }
    925 }
    926 
    927 /**
    928  * xmlSAX2SetDocumentLocator:
    929  * @ctx: the user data (XML parser context)
    930  * @loc: A SAX Locator
    931  *
    932  * Receive the document locator at startup, actually xmlDefaultSAXLocator
    933  * Everything is available on the context, so this is useless in our case.
    934  */
    935 void
    936 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
    937 {
    938     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
    939 #ifdef DEBUG_SAX
    940     xmlGenericError(xmlGenericErrorContext,
    941 	    "SAX.xmlSAX2SetDocumentLocator()\n");
    942 #endif
    943 }
    944 
    945 /**
    946  * xmlSAX2StartDocument:
    947  * @ctx: the user data (XML parser context)
    948  *
    949  * called when the document start being processed.
    950  */
    951 void
    952 xmlSAX2StartDocument(void *ctx)
    953 {
    954     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    955     xmlDocPtr doc;
    956 
    957     if (ctx == NULL) return;
    958 
    959 #ifdef DEBUG_SAX
    960     xmlGenericError(xmlGenericErrorContext,
    961 	    "SAX.xmlSAX2StartDocument()\n");
    962 #endif
    963     if (ctxt->html) {
    964 #ifdef LIBXML_HTML_ENABLED
    965 	if (ctxt->myDoc == NULL)
    966 	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
    967 	ctxt->myDoc->properties = XML_DOC_HTML;
    968 	ctxt->myDoc->parseFlags = ctxt->options;
    969 	if (ctxt->myDoc == NULL) {
    970 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
    971 	    return;
    972 	}
    973 #else
    974         xmlGenericError(xmlGenericErrorContext,
    975 		"libxml2 built without HTML support\n");
    976 	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
    977 	ctxt->instate = XML_PARSER_EOF;
    978 	ctxt->disableSAX = 1;
    979 	return;
    980 #endif
    981     } else {
    982 	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
    983 	if (doc != NULL) {
    984 	    doc->properties = 0;
    985 	    if (ctxt->options & XML_PARSE_OLD10)
    986 	        doc->properties |= XML_DOC_OLD10;
    987 	    doc->parseFlags = ctxt->options;
    988 	    if (ctxt->encoding != NULL)
    989 		doc->encoding = xmlStrdup(ctxt->encoding);
    990 	    else
    991 		doc->encoding = NULL;
    992 	    doc->standalone = ctxt->standalone;
    993 	} else {
    994 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
    995 	    return;
    996 	}
    997 	if ((ctxt->dictNames) && (doc != NULL)) {
    998 	    doc->dict = ctxt->dict;
    999 	    xmlDictReference(doc->dict);
   1000 	}
   1001     }
   1002     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
   1003 	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
   1004 	ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
   1005 	if (ctxt->myDoc->URL == NULL)
   1006 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
   1007     }
   1008 }
   1009 
   1010 /**
   1011  * xmlSAX2EndDocument:
   1012  * @ctx: the user data (XML parser context)
   1013  *
   1014  * called when the document end has been detected.
   1015  */
   1016 void
   1017 xmlSAX2EndDocument(void *ctx)
   1018 {
   1019     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1020 #ifdef DEBUG_SAX
   1021     xmlGenericError(xmlGenericErrorContext,
   1022 	    "SAX.xmlSAX2EndDocument()\n");
   1023 #endif
   1024     if (ctx == NULL) return;
   1025 #ifdef LIBXML_VALID_ENABLED
   1026     if (ctxt->validate && ctxt->wellFormed &&
   1027         ctxt->myDoc && ctxt->myDoc->intSubset)
   1028 	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
   1029 #endif /* LIBXML_VALID_ENABLED */
   1030 
   1031     /*
   1032      * Grab the encoding if it was added on-the-fly
   1033      */
   1034     if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
   1035 	(ctxt->myDoc->encoding == NULL)) {
   1036 	ctxt->myDoc->encoding = ctxt->encoding;
   1037 	ctxt->encoding = NULL;
   1038     }
   1039     if ((ctxt->inputTab != NULL) &&
   1040         (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
   1041         (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
   1042 	(ctxt->myDoc->encoding == NULL)) {
   1043 	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
   1044     }
   1045     if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
   1046 	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
   1047 	ctxt->myDoc->charset = ctxt->charset;
   1048     }
   1049 }
   1050 
   1051 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
   1052 /**
   1053  * xmlSAX2AttributeInternal:
   1054  * @ctx: the user data (XML parser context)
   1055  * @fullname:  The attribute name, including namespace prefix
   1056  * @value:  The attribute value
   1057  * @prefix: the prefix on the element node
   1058  *
   1059  * Handle an attribute that has been read by the parser.
   1060  * The default handling is to convert the attribute into an
   1061  * DOM subtree and past it in a new xmlAttr element added to
   1062  * the element.
   1063  */
   1064 static void
   1065 xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
   1066              const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
   1067 {
   1068     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1069     xmlAttrPtr ret;
   1070     xmlChar *name;
   1071     xmlChar *ns;
   1072     xmlChar *nval;
   1073     xmlNsPtr namespace;
   1074 
   1075     if (ctxt->html) {
   1076 	name = xmlStrdup(fullname);
   1077 	ns = NULL;
   1078 	namespace = NULL;
   1079     } else {
   1080 	/*
   1081 	 * Split the full name into a namespace prefix and the tag name
   1082 	 */
   1083 	name = xmlSplitQName(ctxt, fullname, &ns);
   1084 	if ((name != NULL) && (name[0] == 0)) {
   1085 	    if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
   1086 		xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
   1087 			    "invalid namespace declaration '%s'\n",
   1088 			    fullname, NULL);
   1089 	    } else {
   1090 		xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
   1091 			     "Avoid attribute ending with ':' like '%s'\n",
   1092 			     fullname, NULL);
   1093 	    }
   1094 	    if (ns != NULL)
   1095 		xmlFree(ns);
   1096 	    ns = NULL;
   1097 	    xmlFree(name);
   1098 	    name = xmlStrdup(fullname);
   1099 	}
   1100     }
   1101     if (name == NULL) {
   1102         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1103 	if (ns != NULL)
   1104 	    xmlFree(ns);
   1105 	return;
   1106     }
   1107 
   1108 #ifdef LIBXML_VALID_ENABLED
   1109     /*
   1110      * Do the last stage of the attribute normalization
   1111      * Needed for HTML too:
   1112      *   http://www.w3.org/TR/html4/types.html#h-6.2
   1113      */
   1114     ctxt->vctxt.valid = 1;
   1115     nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
   1116 	                                   ctxt->myDoc, ctxt->node,
   1117 					   fullname, value);
   1118     if (ctxt->vctxt.valid != 1) {
   1119 	ctxt->valid = 0;
   1120     }
   1121     if (nval != NULL)
   1122 	value = nval;
   1123 #else
   1124     nval = NULL;
   1125 #endif /* LIBXML_VALID_ENABLED */
   1126 
   1127     /*
   1128      * Check whether it's a namespace definition
   1129      */
   1130     if ((!ctxt->html) && (ns == NULL) &&
   1131         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
   1132         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
   1133 	xmlNsPtr nsret;
   1134 	xmlChar *val;
   1135 
   1136         if (!ctxt->replaceEntities) {
   1137 	    ctxt->depth++;
   1138 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1139 		                          0,0,0);
   1140 	    ctxt->depth--;
   1141 	} else {
   1142 	    val = (xmlChar *) value;
   1143 	}
   1144 
   1145 	if (val[0] != 0) {
   1146 	    xmlURIPtr uri;
   1147 
   1148 	    uri = xmlParseURI((const char *)val);
   1149 	    if (uri == NULL) {
   1150 		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
   1151 		    ctxt->sax->warning(ctxt->userData,
   1152 			 "xmlns: %s not a valid URI\n", val);
   1153 	    } else {
   1154 		if (uri->scheme == NULL) {
   1155 		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
   1156 			ctxt->sax->warning(ctxt->userData,
   1157 			     "xmlns: URI %s is not absolute\n", val);
   1158 		}
   1159 		xmlFreeURI(uri);
   1160 	    }
   1161 	}
   1162 
   1163 	/* a default namespace definition */
   1164 	nsret = xmlNewNs(ctxt->node, val, NULL);
   1165 
   1166 #ifdef LIBXML_VALID_ENABLED
   1167 	/*
   1168 	 * Validate also for namespace decls, they are attributes from
   1169 	 * an XML-1.0 perspective
   1170 	 */
   1171         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
   1172 	    ctxt->myDoc && ctxt->myDoc->intSubset)
   1173 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   1174 					   ctxt->node, prefix, nsret, val);
   1175 #endif /* LIBXML_VALID_ENABLED */
   1176 	if (name != NULL)
   1177 	    xmlFree(name);
   1178 	if (nval != NULL)
   1179 	    xmlFree(nval);
   1180 	if (val != value)
   1181 	    xmlFree(val);
   1182 	return;
   1183     }
   1184     if ((!ctxt->html) &&
   1185 	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
   1186         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
   1187 	xmlNsPtr nsret;
   1188 	xmlChar *val;
   1189 
   1190         if (!ctxt->replaceEntities) {
   1191 	    ctxt->depth++;
   1192 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1193 		                          0,0,0);
   1194 	    ctxt->depth--;
   1195 	    if (val == NULL) {
   1196 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1197 	        xmlFree(ns);
   1198 		if (name != NULL)
   1199 		    xmlFree(name);
   1200 		return;
   1201 	    }
   1202 	} else {
   1203 	    val = (xmlChar *) value;
   1204 	}
   1205 
   1206 	if (val[0] == 0) {
   1207 	    xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
   1208 		        "Empty namespace name for prefix %s\n", name, NULL);
   1209 	}
   1210 	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
   1211 	    xmlURIPtr uri;
   1212 
   1213 	    uri = xmlParseURI((const char *)val);
   1214 	    if (uri == NULL) {
   1215 	        xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
   1216 			 "xmlns:%s: %s not a valid URI\n", name, value);
   1217 	    } else {
   1218 		if (uri->scheme == NULL) {
   1219 		    xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
   1220 			   "xmlns:%s: URI %s is not absolute\n", name, value);
   1221 		}
   1222 		xmlFreeURI(uri);
   1223 	    }
   1224 	}
   1225 
   1226 	/* a standard namespace definition */
   1227 	nsret = xmlNewNs(ctxt->node, val, name);
   1228 	xmlFree(ns);
   1229 #ifdef LIBXML_VALID_ENABLED
   1230 	/*
   1231 	 * Validate also for namespace decls, they are attributes from
   1232 	 * an XML-1.0 perspective
   1233 	 */
   1234         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
   1235 	    ctxt->myDoc && ctxt->myDoc->intSubset)
   1236 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   1237 					   ctxt->node, prefix, nsret, value);
   1238 #endif /* LIBXML_VALID_ENABLED */
   1239 	if (name != NULL)
   1240 	    xmlFree(name);
   1241 	if (nval != NULL)
   1242 	    xmlFree(nval);
   1243 	if (val != value)
   1244 	    xmlFree(val);
   1245 	return;
   1246     }
   1247 
   1248     if (ns != NULL) {
   1249 	xmlAttrPtr prop;
   1250 	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
   1251 	if (namespace == NULL) {
   1252 	    xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   1253 		    "Namespace prefix %s of attribute %s is not defined\n",
   1254 		             ns, name);
   1255 	}
   1256 
   1257 	prop = ctxt->node->properties;
   1258 	while (prop != NULL) {
   1259 	    if (prop->ns != NULL) {
   1260 		if ((xmlStrEqual(name, prop->name)) &&
   1261 		    ((namespace == prop->ns) ||
   1262 		     (xmlStrEqual(namespace->href, prop->ns->href)))) {
   1263 			xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
   1264 			        "Attribute %s in %s redefined\n",
   1265 			                 name, namespace->href);
   1266 		    ctxt->wellFormed = 0;
   1267 		    if (ctxt->recovery == 0) ctxt->disableSAX = 1;
   1268 		    goto error;
   1269 		}
   1270 	    }
   1271 	    prop = prop->next;
   1272 	}
   1273     } else {
   1274 	namespace = NULL;
   1275     }
   1276 
   1277     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
   1278     ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
   1279 
   1280     if (ret != NULL) {
   1281         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
   1282 	    xmlNodePtr tmp;
   1283 
   1284 	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
   1285 	    tmp = ret->children;
   1286 	    while (tmp != NULL) {
   1287 		tmp->parent = (xmlNodePtr) ret;
   1288 		if (tmp->next == NULL)
   1289 		    ret->last = tmp;
   1290 		tmp = tmp->next;
   1291 	    }
   1292 	} else if (value != NULL) {
   1293 	    ret->children = xmlNewDocText(ctxt->myDoc, value);
   1294 	    ret->last = ret->children;
   1295 	    if (ret->children != NULL)
   1296 		ret->children->parent = (xmlNodePtr) ret;
   1297 	}
   1298     }
   1299 
   1300 #ifdef LIBXML_VALID_ENABLED
   1301     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   1302         ctxt->myDoc && ctxt->myDoc->intSubset) {
   1303 
   1304 	/*
   1305 	 * If we don't substitute entities, the validation should be
   1306 	 * done on a value with replaced entities anyway.
   1307 	 */
   1308         if (!ctxt->replaceEntities) {
   1309 	    xmlChar *val;
   1310 
   1311 	    ctxt->depth++;
   1312 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1313 		                          0,0,0);
   1314 	    ctxt->depth--;
   1315 
   1316 	    if (val == NULL)
   1317 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   1318 				ctxt->myDoc, ctxt->node, ret, value);
   1319 	    else {
   1320 		xmlChar *nvalnorm;
   1321 
   1322 		/*
   1323 		 * Do the last stage of the attribute normalization
   1324 		 * It need to be done twice ... it's an extra burden related
   1325 		 * to the ability to keep xmlSAX2References in attributes
   1326 		 */
   1327 		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
   1328 					    ctxt->node, fullname, val);
   1329 		if (nvalnorm != NULL) {
   1330 		    xmlFree(val);
   1331 		    val = nvalnorm;
   1332 		}
   1333 
   1334 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   1335 			        ctxt->myDoc, ctxt->node, ret, val);
   1336                 xmlFree(val);
   1337 	    }
   1338 	} else {
   1339 	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
   1340 					       ctxt->node, ret, value);
   1341 	}
   1342     } else
   1343 #endif /* LIBXML_VALID_ENABLED */
   1344            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
   1345 	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
   1346 	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
   1347         /*
   1348 	 * when validating, the ID registration is done at the attribute
   1349 	 * validation level. Otherwise we have to do specific handling here.
   1350 	 */
   1351 	if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
   1352 	    /*
   1353 	     * Add the xml:id value
   1354 	     *
   1355 	     * Open issue: normalization of the value.
   1356 	     */
   1357 	    if (xmlValidateNCName(value, 1) != 0) {
   1358 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
   1359 		      "xml:id : attribute value %s is not an NCName\n",
   1360 			    (const char *) value, NULL);
   1361 	    }
   1362 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1363 	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
   1364 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1365 	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
   1366 	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1367     }
   1368 
   1369 error:
   1370     if (nval != NULL)
   1371 	xmlFree(nval);
   1372     if (ns != NULL)
   1373 	xmlFree(ns);
   1374 }
   1375 
   1376 /*
   1377  * xmlCheckDefaultedAttributes:
   1378  *
   1379  * Check defaulted attributes from the DTD
   1380  */
   1381 static void
   1382 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
   1383 	const xmlChar *prefix, const xmlChar **atts) {
   1384     xmlElementPtr elemDecl;
   1385     const xmlChar *att;
   1386     int internal = 1;
   1387     int i;
   1388 
   1389     elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
   1390     if (elemDecl == NULL) {
   1391 	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
   1392 	internal = 0;
   1393     }
   1394 
   1395 process_external_subset:
   1396 
   1397     if (elemDecl != NULL) {
   1398 	xmlAttributePtr attr = elemDecl->attributes;
   1399 	/*
   1400 	 * Check against defaulted attributes from the external subset
   1401 	 * if the document is stamped as standalone
   1402 	 */
   1403 	if ((ctxt->myDoc->standalone == 1) &&
   1404 	    (ctxt->myDoc->extSubset != NULL) &&
   1405 	    (ctxt->validate)) {
   1406 	    while (attr != NULL) {
   1407 		if ((attr->defaultValue != NULL) &&
   1408 		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
   1409 					attr->elem, attr->name,
   1410 					attr->prefix) == attr) &&
   1411 		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
   1412 					attr->elem, attr->name,
   1413 					attr->prefix) == NULL)) {
   1414 		    xmlChar *fulln;
   1415 
   1416 		    if (attr->prefix != NULL) {
   1417 			fulln = xmlStrdup(attr->prefix);
   1418 			fulln = xmlStrcat(fulln, BAD_CAST ":");
   1419 			fulln = xmlStrcat(fulln, attr->name);
   1420 		    } else {
   1421 			fulln = xmlStrdup(attr->name);
   1422 		    }
   1423 
   1424 		    /*
   1425 		     * Check that the attribute is not declared in the
   1426 		     * serialization
   1427 		     */
   1428 		    att = NULL;
   1429 		    if (atts != NULL) {
   1430 			i = 0;
   1431 			att = atts[i];
   1432 			while (att != NULL) {
   1433 			    if (xmlStrEqual(att, fulln))
   1434 				break;
   1435 			    i += 2;
   1436 			    att = atts[i];
   1437 			}
   1438 		    }
   1439 		    if (att == NULL) {
   1440 		        xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
   1441       "standalone: attribute %s on %s defaulted from external subset\n",
   1442 				    (const char *)fulln,
   1443 				    (const char *)attr->elem);
   1444 		    }
   1445 		}
   1446 		attr = attr->nexth;
   1447 	    }
   1448 	}
   1449 
   1450 	/*
   1451 	 * Actually insert defaulted values when needed
   1452 	 */
   1453 	attr = elemDecl->attributes;
   1454 	while (attr != NULL) {
   1455 	    /*
   1456 	     * Make sure that attributes redefinition occuring in the
   1457 	     * internal subset are not overriden by definitions in the
   1458 	     * external subset.
   1459 	     */
   1460 	    if (attr->defaultValue != NULL) {
   1461 		/*
   1462 		 * the element should be instantiated in the tree if:
   1463 		 *  - this is a namespace prefix
   1464 		 *  - the user required for completion in the tree
   1465 		 *    like XSLT
   1466 		 *  - there isn't already an attribute definition
   1467 		 *    in the internal subset overriding it.
   1468 		 */
   1469 		if (((attr->prefix != NULL) &&
   1470 		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
   1471 		    ((attr->prefix == NULL) &&
   1472 		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
   1473 		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
   1474 		    xmlAttributePtr tst;
   1475 
   1476 		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
   1477 					     attr->elem, attr->name,
   1478 					     attr->prefix);
   1479 		    if ((tst == attr) || (tst == NULL)) {
   1480 		        xmlChar fn[50];
   1481 			xmlChar *fulln;
   1482 
   1483                         fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
   1484 			if (fulln == NULL) {
   1485 			    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1486 			    return;
   1487 			}
   1488 
   1489 			/*
   1490 			 * Check that the attribute is not declared in the
   1491 			 * serialization
   1492 			 */
   1493 			att = NULL;
   1494 			if (atts != NULL) {
   1495 			    i = 0;
   1496 			    att = atts[i];
   1497 			    while (att != NULL) {
   1498 				if (xmlStrEqual(att, fulln))
   1499 				    break;
   1500 				i += 2;
   1501 				att = atts[i];
   1502 			    }
   1503 			}
   1504 			if (att == NULL) {
   1505 			    xmlSAX2AttributeInternal(ctxt, fulln,
   1506 						 attr->defaultValue, prefix);
   1507 			}
   1508 			if ((fulln != fn) && (fulln != attr->name))
   1509 			    xmlFree(fulln);
   1510 		    }
   1511 		}
   1512 	    }
   1513 	    attr = attr->nexth;
   1514 	}
   1515 	if (internal == 1) {
   1516 	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
   1517 		                             name, prefix);
   1518 	    internal = 0;
   1519 	    goto process_external_subset;
   1520 	}
   1521     }
   1522 }
   1523 
   1524 /**
   1525  * xmlSAX2StartElement:
   1526  * @ctx: the user data (XML parser context)
   1527  * @fullname:  The element name, including namespace prefix
   1528  * @atts:  An array of name/value attributes pairs, NULL terminated
   1529  *
   1530  * called when an opening tag has been processed.
   1531  */
   1532 void
   1533 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
   1534 {
   1535     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1536     xmlNodePtr ret;
   1537     xmlNodePtr parent;
   1538     xmlNsPtr ns;
   1539     xmlChar *name;
   1540     xmlChar *prefix;
   1541     const xmlChar *att;
   1542     const xmlChar *value;
   1543     int i;
   1544 
   1545     if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
   1546     parent = ctxt->node;
   1547 #ifdef DEBUG_SAX
   1548     xmlGenericError(xmlGenericErrorContext,
   1549 	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
   1550 #endif
   1551 
   1552     /*
   1553      * First check on validity:
   1554      */
   1555     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
   1556         ((ctxt->myDoc->intSubset == NULL) ||
   1557 	 ((ctxt->myDoc->intSubset->notations == NULL) &&
   1558 	  (ctxt->myDoc->intSubset->elements == NULL) &&
   1559 	  (ctxt->myDoc->intSubset->attributes == NULL) &&
   1560 	  (ctxt->myDoc->intSubset->entities == NULL)))) {
   1561 	xmlErrValid(ctxt, XML_ERR_NO_DTD,
   1562 	  "Validation failed: no DTD found !", NULL, NULL);
   1563 	ctxt->validate = 0;
   1564     }
   1565 
   1566 
   1567     /*
   1568      * Split the full name into a namespace prefix and the tag name
   1569      */
   1570     name = xmlSplitQName(ctxt, fullname, &prefix);
   1571 
   1572 
   1573     /*
   1574      * Note : the namespace resolution is deferred until the end of the
   1575      *        attributes parsing, since local namespace can be defined as
   1576      *        an attribute at this level.
   1577      */
   1578     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
   1579     if (ret == NULL) {
   1580         if (prefix != NULL)
   1581 	    xmlFree(prefix);
   1582 	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1583         return;
   1584     }
   1585     if (ctxt->myDoc->children == NULL) {
   1586 #ifdef DEBUG_SAX_TREE
   1587 	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
   1588 #endif
   1589         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   1590     } else if (parent == NULL) {
   1591         parent = ctxt->myDoc->children;
   1592     }
   1593     ctxt->nodemem = -1;
   1594     if (ctxt->linenumbers) {
   1595 	if (ctxt->input != NULL) {
   1596 	    if (ctxt->input->line < 65535)
   1597 		ret->line = (short) ctxt->input->line;
   1598 	    else
   1599 	        ret->line = 65535;
   1600 	}
   1601     }
   1602 
   1603     /*
   1604      * We are parsing a new node.
   1605      */
   1606 #ifdef DEBUG_SAX_TREE
   1607     xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
   1608 #endif
   1609     nodePush(ctxt, ret);
   1610 
   1611     /*
   1612      * Link the child element
   1613      */
   1614     if (parent != NULL) {
   1615         if (parent->type == XML_ELEMENT_NODE) {
   1616 #ifdef DEBUG_SAX_TREE
   1617 	    xmlGenericError(xmlGenericErrorContext,
   1618 		    "adding child %s to %s\n", name, parent->name);
   1619 #endif
   1620 	    xmlAddChild(parent, ret);
   1621 	} else {
   1622 #ifdef DEBUG_SAX_TREE
   1623 	    xmlGenericError(xmlGenericErrorContext,
   1624 		    "adding sibling %s to ", name);
   1625 	    xmlDebugDumpOneNode(stderr, parent, 0);
   1626 #endif
   1627 	    xmlAddSibling(parent, ret);
   1628 	}
   1629     }
   1630 
   1631     /*
   1632      * Insert all the defaulted attributes from the DTD especially namespaces
   1633      */
   1634     if ((!ctxt->html) &&
   1635 	((ctxt->myDoc->intSubset != NULL) ||
   1636 	 (ctxt->myDoc->extSubset != NULL))) {
   1637 	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
   1638     }
   1639 
   1640     /*
   1641      * process all the attributes whose name start with "xmlns"
   1642      */
   1643     if (atts != NULL) {
   1644         i = 0;
   1645 	att = atts[i++];
   1646 	value = atts[i++];
   1647 	if (!ctxt->html) {
   1648 	    while ((att != NULL) && (value != NULL)) {
   1649 		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
   1650 		    (att[3] == 'n') && (att[4] == 's'))
   1651 		    xmlSAX2AttributeInternal(ctxt, att, value, prefix);
   1652 
   1653 		att = atts[i++];
   1654 		value = atts[i++];
   1655 	    }
   1656 	}
   1657     }
   1658 
   1659     /*
   1660      * Search the namespace, note that since the attributes have been
   1661      * processed, the local namespaces are available.
   1662      */
   1663     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
   1664     if ((ns == NULL) && (parent != NULL))
   1665 	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
   1666     if ((prefix != NULL) && (ns == NULL)) {
   1667 	ns = xmlNewNs(ret, NULL, prefix);
   1668 	xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   1669 		     "Namespace prefix %s is not defined\n",
   1670 		     prefix, NULL);
   1671     }
   1672 
   1673     /*
   1674      * set the namespace node, making sure that if the default namspace
   1675      * is unbound on a parent we simply kee it NULL
   1676      */
   1677     if ((ns != NULL) && (ns->href != NULL) &&
   1678 	((ns->href[0] != 0) || (ns->prefix != NULL)))
   1679 	xmlSetNs(ret, ns);
   1680 
   1681     /*
   1682      * process all the other attributes
   1683      */
   1684     if (atts != NULL) {
   1685         i = 0;
   1686 	att = atts[i++];
   1687 	value = atts[i++];
   1688 	if (ctxt->html) {
   1689 	    while (att != NULL) {
   1690 		xmlSAX2AttributeInternal(ctxt, att, value, NULL);
   1691 		att = atts[i++];
   1692 		value = atts[i++];
   1693 	    }
   1694 	} else {
   1695 	    while ((att != NULL) && (value != NULL)) {
   1696 		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
   1697 		    (att[3] != 'n') || (att[4] != 's'))
   1698 		    xmlSAX2AttributeInternal(ctxt, att, value, NULL);
   1699 
   1700 		/*
   1701 		 * Next ones
   1702 		 */
   1703 		att = atts[i++];
   1704 		value = atts[i++];
   1705 	    }
   1706 	}
   1707     }
   1708 
   1709 #ifdef LIBXML_VALID_ENABLED
   1710     /*
   1711      * If it's the Document root, finish the DTD validation and
   1712      * check the document root element for validity
   1713      */
   1714     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
   1715 	int chk;
   1716 
   1717 	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
   1718 	if (chk <= 0)
   1719 	    ctxt->valid = 0;
   1720 	if (chk < 0)
   1721 	    ctxt->wellFormed = 0;
   1722 	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
   1723 	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
   1724     }
   1725 #endif /* LIBXML_VALID_ENABLED */
   1726 
   1727     if (prefix != NULL)
   1728 	xmlFree(prefix);
   1729 
   1730 }
   1731 
   1732 /**
   1733  * xmlSAX2EndElement:
   1734  * @ctx: the user data (XML parser context)
   1735  * @name:  The element name
   1736  *
   1737  * called when the end of an element has been detected.
   1738  */
   1739 void
   1740 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
   1741 {
   1742     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1743     xmlParserNodeInfo node_info;
   1744     xmlNodePtr cur;
   1745 
   1746     if (ctx == NULL) return;
   1747     cur = ctxt->node;
   1748 #ifdef DEBUG_SAX
   1749     if (name == NULL)
   1750         xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
   1751     else
   1752 	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
   1753 #endif
   1754 
   1755     /* Capture end position and add node */
   1756     if (cur != NULL && ctxt->record_info) {
   1757       node_info.end_pos = ctxt->input->cur - ctxt->input->base;
   1758       node_info.end_line = ctxt->input->line;
   1759       node_info.node = cur;
   1760       xmlParserAddNodeInfo(ctxt, &node_info);
   1761     }
   1762     ctxt->nodemem = -1;
   1763 
   1764 #ifdef LIBXML_VALID_ENABLED
   1765     if (ctxt->validate && ctxt->wellFormed &&
   1766         ctxt->myDoc && ctxt->myDoc->intSubset)
   1767         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
   1768 					     cur);
   1769 #endif /* LIBXML_VALID_ENABLED */
   1770 
   1771 
   1772     /*
   1773      * end of parsing of this node.
   1774      */
   1775 #ifdef DEBUG_SAX_TREE
   1776     xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
   1777 #endif
   1778     nodePop(ctxt);
   1779 }
   1780 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
   1781 
   1782 /*
   1783  * xmlSAX2TextNode:
   1784  * @ctxt:  the parser context
   1785  * @str:  the input string
   1786  * @len: the string length
   1787  *
   1788  * Remove the entities from an attribute value
   1789  *
   1790  * Returns the newly allocated string or NULL if not needed or error
   1791  */
   1792 static xmlNodePtr
   1793 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
   1794     xmlNodePtr ret;
   1795     const xmlChar *intern = NULL;
   1796 
   1797     /*
   1798      * Allocate
   1799      */
   1800     if (ctxt->freeElems != NULL) {
   1801 	ret = ctxt->freeElems;
   1802 	ctxt->freeElems = ret->next;
   1803 	ctxt->freeElemsNr--;
   1804     } else {
   1805 	ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
   1806     }
   1807     if (ret == NULL) {
   1808         xmlErrMemory(ctxt, "xmlSAX2Characters");
   1809 	return(NULL);
   1810     }
   1811     memset(ret, 0, sizeof(xmlNode));
   1812     /*
   1813      * intern the formatting blanks found between tags, or the
   1814      * very short strings
   1815      */
   1816     if (ctxt->dictNames) {
   1817         xmlChar cur = str[len];
   1818 
   1819 	if ((len < (int) (2 * sizeof(void *))) &&
   1820 	    (ctxt->options & XML_PARSE_COMPACT)) {
   1821 	    /* store the string in the node overrithing properties and nsDef */
   1822 	    xmlChar *tmp = (xmlChar *) &(ret->properties);
   1823 	    memcpy(tmp, str, len);
   1824 	    tmp[len] = 0;
   1825 	    intern = tmp;
   1826 	} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
   1827 	    ((cur == '<') && (str[len + 1] != '!')))) {
   1828 	    intern = xmlDictLookup(ctxt->dict, str, len);
   1829 	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
   1830 	           (str[len + 1] != '!')) {
   1831 	    int i;
   1832 
   1833 	    for (i = 1;i < len;i++) {
   1834 		if (!IS_BLANK_CH(str[i])) goto skip;
   1835 	    }
   1836 	    intern = xmlDictLookup(ctxt->dict, str, len);
   1837 	}
   1838     }
   1839 skip:
   1840     ret->type = XML_TEXT_NODE;
   1841 
   1842     ret->name = xmlStringText;
   1843     if (intern == NULL) {
   1844 	ret->content = xmlStrndup(str, len);
   1845 	if (ret->content == NULL) {
   1846 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
   1847 	    xmlFree(ret);
   1848 	    return(NULL);
   1849 	}
   1850     } else
   1851 	ret->content = (xmlChar *) intern;
   1852 
   1853     if (ctxt->input != NULL)
   1854         ret->line = ctxt->input->line;
   1855 
   1856     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   1857 	xmlRegisterNodeDefaultValue(ret);
   1858     return(ret);
   1859 }
   1860 
   1861 #ifdef LIBXML_VALID_ENABLED
   1862 /*
   1863  * xmlSAX2DecodeAttrEntities:
   1864  * @ctxt:  the parser context
   1865  * @str:  the input string
   1866  * @len: the string length
   1867  *
   1868  * Remove the entities from an attribute value
   1869  *
   1870  * Returns the newly allocated string or NULL if not needed or error
   1871  */
   1872 static xmlChar *
   1873 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
   1874                           const xmlChar *end) {
   1875     const xmlChar *in;
   1876     xmlChar *ret;
   1877 
   1878     in = str;
   1879     while (in < end)
   1880         if (*in++ == '&')
   1881 	    goto decode;
   1882     return(NULL);
   1883 decode:
   1884     ctxt->depth++;
   1885     ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
   1886 				     XML_SUBSTITUTE_REF, 0,0,0);
   1887     ctxt->depth--;
   1888     return(ret);
   1889 }
   1890 #endif /* LIBXML_VALID_ENABLED */
   1891 
   1892 /**
   1893  * xmlSAX2AttributeNs:
   1894  * @ctx: the user data (XML parser context)
   1895  * @localname:  the local name of the attribute
   1896  * @prefix:  the attribute namespace prefix if available
   1897  * @URI:  the attribute namespace name if available
   1898  * @value:  Start of the attribute value
   1899  * @valueend: end of the attribute value
   1900  *
   1901  * Handle an attribute that has been read by the parser.
   1902  * The default handling is to convert the attribute into an
   1903  * DOM subtree and past it in a new xmlAttr element added to
   1904  * the element.
   1905  */
   1906 static void
   1907 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
   1908                    const xmlChar * localname,
   1909                    const xmlChar * prefix,
   1910 		   const xmlChar * value,
   1911 		   const xmlChar * valueend)
   1912 {
   1913     xmlAttrPtr ret;
   1914     xmlNsPtr namespace = NULL;
   1915     xmlChar *dup = NULL;
   1916 
   1917     /*
   1918      * Note: if prefix == NULL, the attribute is not in the default namespace
   1919      */
   1920     if (prefix != NULL)
   1921 	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
   1922 
   1923     /*
   1924      * allocate the node
   1925      */
   1926     if (ctxt->freeAttrs != NULL) {
   1927         ret = ctxt->freeAttrs;
   1928 	ctxt->freeAttrs = ret->next;
   1929 	ctxt->freeAttrsNr--;
   1930 	memset(ret, 0, sizeof(xmlAttr));
   1931 	ret->type = XML_ATTRIBUTE_NODE;
   1932 
   1933 	ret->parent = ctxt->node;
   1934 	ret->doc = ctxt->myDoc;
   1935 	ret->ns = namespace;
   1936 
   1937 	if (ctxt->dictNames)
   1938 	    ret->name = localname;
   1939 	else
   1940 	    ret->name = xmlStrdup(localname);
   1941 
   1942         /* link at the end to preserv order, TODO speed up with a last */
   1943 	if (ctxt->node->properties == NULL) {
   1944 	    ctxt->node->properties = ret;
   1945 	} else {
   1946 	    xmlAttrPtr prev = ctxt->node->properties;
   1947 
   1948 	    while (prev->next != NULL) prev = prev->next;
   1949 	    prev->next = ret;
   1950 	    ret->prev = prev;
   1951 	}
   1952 
   1953 	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   1954 	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
   1955     } else {
   1956 	if (ctxt->dictNames)
   1957 	    ret = xmlNewNsPropEatName(ctxt->node, namespace,
   1958 	                              (xmlChar *) localname, NULL);
   1959 	else
   1960 	    ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
   1961 	if (ret == NULL) {
   1962 	    xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
   1963 	    return;
   1964 	}
   1965     }
   1966 
   1967     if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
   1968 	xmlNodePtr tmp;
   1969 
   1970 	/*
   1971 	 * We know that if there is an entity reference, then
   1972 	 * the string has been dup'ed and terminates with 0
   1973 	 * otherwise with ' or "
   1974 	 */
   1975 	if (*valueend != 0) {
   1976 	    tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
   1977 	    ret->children = tmp;
   1978 	    ret->last = tmp;
   1979 	    if (tmp != NULL) {
   1980 		tmp->doc = ret->doc;
   1981 		tmp->parent = (xmlNodePtr) ret;
   1982 	    }
   1983 	} else {
   1984 	    ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
   1985 						    valueend - value);
   1986 	    tmp = ret->children;
   1987 	    while (tmp != NULL) {
   1988 	        tmp->doc = ret->doc;
   1989 		tmp->parent = (xmlNodePtr) ret;
   1990 		if (tmp->next == NULL)
   1991 		    ret->last = tmp;
   1992 		tmp = tmp->next;
   1993 	    }
   1994 	}
   1995     } else if (value != NULL) {
   1996 	xmlNodePtr tmp;
   1997 
   1998 	tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
   1999 	ret->children = tmp;
   2000 	ret->last = tmp;
   2001 	if (tmp != NULL) {
   2002 	    tmp->doc = ret->doc;
   2003 	    tmp->parent = (xmlNodePtr) ret;
   2004 	}
   2005     }
   2006 
   2007 #ifdef LIBXML_VALID_ENABLED
   2008     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   2009         ctxt->myDoc && ctxt->myDoc->intSubset) {
   2010 	/*
   2011 	 * If we don't substitute entities, the validation should be
   2012 	 * done on a value with replaced entities anyway.
   2013 	 */
   2014         if (!ctxt->replaceEntities) {
   2015 	    dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
   2016 	    if (dup == NULL) {
   2017 	        if (*valueend == 0) {
   2018 		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2019 				    ctxt->myDoc, ctxt->node, ret, value);
   2020 		} else {
   2021 		    /*
   2022 		     * That should already be normalized.
   2023 		     * cheaper to finally allocate here than duplicate
   2024 		     * entry points in the full validation code
   2025 		     */
   2026 		    dup = xmlStrndup(value, valueend - value);
   2027 
   2028 		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2029 				    ctxt->myDoc, ctxt->node, ret, dup);
   2030 		}
   2031 	    } else {
   2032 	        /*
   2033 		 * dup now contains a string of the flattened attribute
   2034 		 * content with entities substitued. Check if we need to
   2035 		 * apply an extra layer of normalization.
   2036 		 * It need to be done twice ... it's an extra burden related
   2037 		 * to the ability to keep references in attributes
   2038 		 */
   2039 		if (ctxt->attsSpecial != NULL) {
   2040 		    xmlChar *nvalnorm;
   2041 		    xmlChar fn[50];
   2042 		    xmlChar *fullname;
   2043 
   2044 		    fullname = xmlBuildQName(localname, prefix, fn, 50);
   2045 		    if (fullname != NULL) {
   2046 			ctxt->vctxt.valid = 1;
   2047 		        nvalnorm = xmlValidCtxtNormalizeAttributeValue(
   2048 			                 &ctxt->vctxt, ctxt->myDoc,
   2049 					 ctxt->node, fullname, dup);
   2050 			if (ctxt->vctxt.valid != 1)
   2051 			    ctxt->valid = 0;
   2052 
   2053 			if ((fullname != fn) && (fullname != localname))
   2054 			    xmlFree(fullname);
   2055 			if (nvalnorm != NULL) {
   2056 			    xmlFree(dup);
   2057 			    dup = nvalnorm;
   2058 			}
   2059 		    }
   2060 		}
   2061 
   2062 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2063 			        ctxt->myDoc, ctxt->node, ret, dup);
   2064 	    }
   2065 	} else {
   2066 	    /*
   2067 	     * if entities already have been substitued, then
   2068 	     * the attribute as passed is already normalized
   2069 	     */
   2070 	    dup = xmlStrndup(value, valueend - value);
   2071 
   2072 	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2073 	                             ctxt->myDoc, ctxt->node, ret, dup);
   2074 	}
   2075     } else
   2076 #endif /* LIBXML_VALID_ENABLED */
   2077            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
   2078 	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
   2079 	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
   2080         /*
   2081 	 * when validating, the ID registration is done at the attribute
   2082 	 * validation level. Otherwise we have to do specific handling here.
   2083 	 */
   2084         if ((prefix == ctxt->str_xml) &&
   2085 	           (localname[0] == 'i') && (localname[1] == 'd') &&
   2086 		   (localname[2] == 0)) {
   2087 	    /*
   2088 	     * Add the xml:id value
   2089 	     *
   2090 	     * Open issue: normalization of the value.
   2091 	     */
   2092 	    if (dup == NULL)
   2093 	        dup = xmlStrndup(value, valueend - value);
   2094 #ifdef LIBXML_VALID_ENABLED
   2095 	    if (xmlValidateNCName(dup, 1) != 0) {
   2096 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
   2097 		      "xml:id : attribute value %s is not an NCName\n",
   2098 			    (const char *) dup, NULL);
   2099 	    }
   2100 #endif
   2101 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2102 	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
   2103 	    /* might be worth duplicate entry points and not copy */
   2104 	    if (dup == NULL)
   2105 	        dup = xmlStrndup(value, valueend - value);
   2106 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2107 	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
   2108 	    if (dup == NULL)
   2109 	        dup = xmlStrndup(value, valueend - value);
   2110 	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2111 	}
   2112     }
   2113     if (dup != NULL)
   2114 	xmlFree(dup);
   2115 }
   2116 
   2117 /**
   2118  * xmlSAX2StartElementNs:
   2119  * @ctx:  the user data (XML parser context)
   2120  * @localname:  the local name of the element
   2121  * @prefix:  the element namespace prefix if available
   2122  * @URI:  the element namespace name if available
   2123  * @nb_namespaces:  number of namespace definitions on that node
   2124  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
   2125  * @nb_attributes:  the number of attributes on that node
   2126  * @nb_defaulted:  the number of defaulted attributes.
   2127  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
   2128  *               attribute values.
   2129  *
   2130  * SAX2 callback when an element start has been detected by the parser.
   2131  * It provides the namespace informations for the element, as well as
   2132  * the new namespace declarations on the element.
   2133  */
   2134 void
   2135 xmlSAX2StartElementNs(void *ctx,
   2136                       const xmlChar *localname,
   2137 		      const xmlChar *prefix,
   2138 		      const xmlChar *URI,
   2139 		      int nb_namespaces,
   2140 		      const xmlChar **namespaces,
   2141 		      int nb_attributes,
   2142 		      int nb_defaulted,
   2143 		      const xmlChar **attributes)
   2144 {
   2145     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2146     xmlNodePtr ret;
   2147     xmlNodePtr parent;
   2148     xmlNsPtr last = NULL, ns;
   2149     const xmlChar *uri, *pref;
   2150     int i, j;
   2151 
   2152     if (ctx == NULL) return;
   2153     parent = ctxt->node;
   2154     /*
   2155      * First check on validity:
   2156      */
   2157     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
   2158         ((ctxt->myDoc->intSubset == NULL) ||
   2159 	 ((ctxt->myDoc->intSubset->notations == NULL) &&
   2160 	  (ctxt->myDoc->intSubset->elements == NULL) &&
   2161 	  (ctxt->myDoc->intSubset->attributes == NULL) &&
   2162 	  (ctxt->myDoc->intSubset->entities == NULL)))) {
   2163 	xmlErrValid(ctxt, XML_ERR_NO_DTD,
   2164 	  "Validation failed: no DTD found !", NULL, NULL);
   2165 	ctxt->validate = 0;
   2166     }
   2167 
   2168     /*
   2169      * allocate the node
   2170      */
   2171     if (ctxt->freeElems != NULL) {
   2172         ret = ctxt->freeElems;
   2173 	ctxt->freeElems = ret->next;
   2174 	ctxt->freeElemsNr--;
   2175 	memset(ret, 0, sizeof(xmlNode));
   2176 	ret->type = XML_ELEMENT_NODE;
   2177 
   2178 	if (ctxt->dictNames)
   2179 	    ret->name = localname;
   2180 	else {
   2181 	    ret->name = xmlStrdup(localname);
   2182 	    if (ret->name == NULL) {
   2183 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2184 		return;
   2185 	    }
   2186 	}
   2187 	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   2188 	    xmlRegisterNodeDefaultValue(ret);
   2189     } else {
   2190 	if (ctxt->dictNames)
   2191 	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
   2192 	                               (xmlChar *) localname, NULL);
   2193 	else
   2194 	    ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
   2195 	if (ret == NULL) {
   2196 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2197 	    return;
   2198 	}
   2199     }
   2200     if (ctxt->linenumbers) {
   2201 	if (ctxt->input != NULL) {
   2202 	    if (ctxt->input->line < 65535)
   2203 		ret->line = (short) ctxt->input->line;
   2204 	    else
   2205 	        ret->line = 65535;
   2206 	}
   2207     }
   2208 
   2209     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2210         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2211     }
   2212     /*
   2213      * Build the namespace list
   2214      */
   2215     for (i = 0,j = 0;j < nb_namespaces;j++) {
   2216         pref = namespaces[i++];
   2217 	uri = namespaces[i++];
   2218 	ns = xmlNewNs(NULL, uri, pref);
   2219 	if (ns != NULL) {
   2220 	    if (last == NULL) {
   2221 	        ret->nsDef = last = ns;
   2222 	    } else {
   2223 	        last->next = ns;
   2224 		last = ns;
   2225 	    }
   2226 	    if ((URI != NULL) && (prefix == pref))
   2227 		ret->ns = ns;
   2228 	} else {
   2229 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2230 	    return;
   2231 	}
   2232 #ifdef LIBXML_VALID_ENABLED
   2233 	if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   2234 	    ctxt->myDoc && ctxt->myDoc->intSubset) {
   2235 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   2236 	                                           ret, prefix, ns, uri);
   2237 	}
   2238 #endif /* LIBXML_VALID_ENABLED */
   2239     }
   2240     ctxt->nodemem = -1;
   2241 
   2242     /*
   2243      * We are parsing a new node.
   2244      */
   2245     nodePush(ctxt, ret);
   2246 
   2247     /*
   2248      * Link the child element
   2249      */
   2250     if (parent != NULL) {
   2251         if (parent->type == XML_ELEMENT_NODE) {
   2252 	    xmlAddChild(parent, ret);
   2253 	} else {
   2254 	    xmlAddSibling(parent, ret);
   2255 	}
   2256     }
   2257 
   2258     /*
   2259      * Insert the defaulted attributes from the DTD only if requested:
   2260      */
   2261     if ((nb_defaulted != 0) &&
   2262         ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
   2263 	nb_attributes -= nb_defaulted;
   2264 
   2265     /*
   2266      * Search the namespace if it wasn't already found
   2267      * Note that, if prefix is NULL, this searches for the default Ns
   2268      */
   2269     if ((URI != NULL) && (ret->ns == NULL)) {
   2270         ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
   2271 	if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
   2272 	    ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
   2273 	}
   2274 	if (ret->ns == NULL) {
   2275 	    ns = xmlNewNs(ret, NULL, prefix);
   2276 	    if (ns == NULL) {
   2277 
   2278 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2279 		return;
   2280 	    }
   2281 	    xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   2282 			"Namespace prefix %s was not found\n",
   2283 			prefix, NULL);
   2284 	}
   2285     }
   2286 
   2287     /*
   2288      * process all the other attributes
   2289      */
   2290     if (nb_attributes > 0) {
   2291         for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
   2292 	    xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
   2293 	                       attributes[j+3], attributes[j+4]);
   2294 	}
   2295     }
   2296 
   2297 #ifdef LIBXML_VALID_ENABLED
   2298     /*
   2299      * If it's the Document root, finish the DTD validation and
   2300      * check the document root element for validity
   2301      */
   2302     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
   2303 	int chk;
   2304 
   2305 	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
   2306 	if (chk <= 0)
   2307 	    ctxt->valid = 0;
   2308 	if (chk < 0)
   2309 	    ctxt->wellFormed = 0;
   2310 	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
   2311 	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
   2312     }
   2313 #endif /* LIBXML_VALID_ENABLED */
   2314 }
   2315 
   2316 /**
   2317  * xmlSAX2EndElementNs:
   2318  * @ctx:  the user data (XML parser context)
   2319  * @localname:  the local name of the element
   2320  * @prefix:  the element namespace prefix if available
   2321  * @URI:  the element namespace name if available
   2322  *
   2323  * SAX2 callback when an element end has been detected by the parser.
   2324  * It provides the namespace informations for the element.
   2325  */
   2326 void
   2327 xmlSAX2EndElementNs(void *ctx,
   2328                     const xmlChar * localname ATTRIBUTE_UNUSED,
   2329                     const xmlChar * prefix ATTRIBUTE_UNUSED,
   2330 		    const xmlChar * URI ATTRIBUTE_UNUSED)
   2331 {
   2332     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2333     xmlParserNodeInfo node_info;
   2334     xmlNodePtr cur;
   2335 
   2336     if (ctx == NULL) return;
   2337     cur = ctxt->node;
   2338     /* Capture end position and add node */
   2339     if ((ctxt->record_info) && (cur != NULL)) {
   2340         node_info.end_pos = ctxt->input->cur - ctxt->input->base;
   2341         node_info.end_line = ctxt->input->line;
   2342         node_info.node = cur;
   2343         xmlParserAddNodeInfo(ctxt, &node_info);
   2344     }
   2345     ctxt->nodemem = -1;
   2346 
   2347 #ifdef LIBXML_VALID_ENABLED
   2348     if (ctxt->validate && ctxt->wellFormed &&
   2349         ctxt->myDoc && ctxt->myDoc->intSubset)
   2350         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
   2351 #endif /* LIBXML_VALID_ENABLED */
   2352 
   2353     /*
   2354      * end of parsing of this node.
   2355      */
   2356     nodePop(ctxt);
   2357 }
   2358 
   2359 /**
   2360  * xmlSAX2Reference:
   2361  * @ctx: the user data (XML parser context)
   2362  * @name:  The entity name
   2363  *
   2364  * called when an entity xmlSAX2Reference is detected.
   2365  */
   2366 void
   2367 xmlSAX2Reference(void *ctx, const xmlChar *name)
   2368 {
   2369     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2370     xmlNodePtr ret;
   2371 
   2372     if (ctx == NULL) return;
   2373 #ifdef DEBUG_SAX
   2374     xmlGenericError(xmlGenericErrorContext,
   2375 	    "SAX.xmlSAX2Reference(%s)\n", name);
   2376 #endif
   2377     if (name[0] == '#')
   2378 	ret = xmlNewCharRef(ctxt->myDoc, name);
   2379     else
   2380 	ret = xmlNewReference(ctxt->myDoc, name);
   2381 #ifdef DEBUG_SAX_TREE
   2382     xmlGenericError(xmlGenericErrorContext,
   2383 	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
   2384 #endif
   2385     if (xmlAddChild(ctxt->node, ret) == NULL) {
   2386         xmlFreeNode(ret);
   2387     }
   2388 }
   2389 
   2390 /**
   2391  * xmlSAX2Characters:
   2392  * @ctx: the user data (XML parser context)
   2393  * @ch:  a xmlChar string
   2394  * @len: the number of xmlChar
   2395  *
   2396  * receiving some chars from the parser.
   2397  */
   2398 void
   2399 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
   2400 {
   2401     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2402     xmlNodePtr lastChild;
   2403 
   2404     if (ctx == NULL) return;
   2405 #ifdef DEBUG_SAX
   2406     xmlGenericError(xmlGenericErrorContext,
   2407 	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
   2408 #endif
   2409     /*
   2410      * Handle the data if any. If there is no child
   2411      * add it as content, otherwise if the last child is text,
   2412      * concatenate it, else create a new node of type text.
   2413      */
   2414 
   2415     if (ctxt->node == NULL) {
   2416 #ifdef DEBUG_SAX_TREE
   2417 	xmlGenericError(xmlGenericErrorContext,
   2418 		"add chars: ctxt->node == NULL !\n");
   2419 #endif
   2420         return;
   2421     }
   2422     lastChild = ctxt->node->last;
   2423 #ifdef DEBUG_SAX_TREE
   2424     xmlGenericError(xmlGenericErrorContext,
   2425 	    "add chars to %s \n", ctxt->node->name);
   2426 #endif
   2427 
   2428     /*
   2429      * Here we needed an accelerator mechanism in case of very large
   2430      * elements. Use an attribute in the structure !!!
   2431      */
   2432     if (lastChild == NULL) {
   2433         lastChild = xmlSAX2TextNode(ctxt, ch, len);
   2434 	if (lastChild != NULL) {
   2435 	    ctxt->node->children = lastChild;
   2436 	    ctxt->node->last = lastChild;
   2437 	    lastChild->parent = ctxt->node;
   2438 	    lastChild->doc = ctxt->node->doc;
   2439 	    ctxt->nodelen = len;
   2440 	    ctxt->nodemem = len + 1;
   2441 	} else {
   2442 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2443 	    return;
   2444 	}
   2445     } else {
   2446 	int coalesceText = (lastChild != NULL) &&
   2447 	    (lastChild->type == XML_TEXT_NODE) &&
   2448 	    (lastChild->name == xmlStringText);
   2449 	if ((coalesceText) && (ctxt->nodemem != 0)) {
   2450 	    /*
   2451 	     * The whole point of maintaining nodelen and nodemem,
   2452 	     * xmlTextConcat is too costly, i.e. compute length,
   2453 	     * reallocate a new buffer, move data, append ch. Here
   2454 	     * We try to minimaze realloc() uses and avoid copying
   2455 	     * and recomputing length over and over.
   2456 	     */
   2457 	    if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
   2458 		lastChild->content = xmlStrdup(lastChild->content);
   2459 		lastChild->properties = NULL;
   2460 	    } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
   2461 	               (xmlDictOwns(ctxt->dict, lastChild->content))) {
   2462 		lastChild->content = xmlStrdup(lastChild->content);
   2463 	    }
   2464             if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
   2465                 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
   2466                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
   2467                 return;
   2468             }
   2469 	    if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
   2470 	        (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
   2471                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
   2472                 return;
   2473 	    }
   2474 	    if (ctxt->nodelen + len >= ctxt->nodemem) {
   2475 		xmlChar *newbuf;
   2476 		size_t size;
   2477 
   2478 		size = ctxt->nodemem + len;
   2479 		size *= 2;
   2480                 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
   2481 		if (newbuf == NULL) {
   2482 		    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2483 		    return;
   2484 		}
   2485 		ctxt->nodemem = size;
   2486 		lastChild->content = newbuf;
   2487 	    }
   2488 	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
   2489 	    ctxt->nodelen += len;
   2490 	    lastChild->content[ctxt->nodelen] = 0;
   2491 	} else if (coalesceText) {
   2492 	    if (xmlTextConcat(lastChild, ch, len)) {
   2493 		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2494 	    }
   2495 	    if (ctxt->node->children != NULL) {
   2496 		ctxt->nodelen = xmlStrlen(lastChild->content);
   2497 		ctxt->nodemem = ctxt->nodelen + 1;
   2498 	    }
   2499 	} else {
   2500 	    /* Mixed content, first time */
   2501 	    lastChild = xmlSAX2TextNode(ctxt, ch, len);
   2502 	    if (lastChild != NULL) {
   2503 		xmlAddChild(ctxt->node, lastChild);
   2504 		if (ctxt->node->children != NULL) {
   2505 		    ctxt->nodelen = len;
   2506 		    ctxt->nodemem = len + 1;
   2507 		}
   2508 	    }
   2509 	}
   2510     }
   2511 }
   2512 
   2513 /**
   2514  * xmlSAX2IgnorableWhitespace:
   2515  * @ctx: the user data (XML parser context)
   2516  * @ch:  a xmlChar string
   2517  * @len: the number of xmlChar
   2518  *
   2519  * receiving some ignorable whitespaces from the parser.
   2520  * UNUSED: by default the DOM building will use xmlSAX2Characters
   2521  */
   2522 void
   2523 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
   2524 {
   2525     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
   2526 #ifdef DEBUG_SAX
   2527     xmlGenericError(xmlGenericErrorContext,
   2528 	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
   2529 #endif
   2530 }
   2531 
   2532 /**
   2533  * xmlSAX2ProcessingInstruction:
   2534  * @ctx: the user data (XML parser context)
   2535  * @target:  the target name
   2536  * @data: the PI data's
   2537  *
   2538  * A processing instruction has been parsed.
   2539  */
   2540 void
   2541 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
   2542                       const xmlChar *data)
   2543 {
   2544     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2545     xmlNodePtr ret;
   2546     xmlNodePtr parent;
   2547 
   2548     if (ctx == NULL) return;
   2549     parent = ctxt->node;
   2550 #ifdef DEBUG_SAX
   2551     xmlGenericError(xmlGenericErrorContext,
   2552 	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
   2553 #endif
   2554 
   2555     ret = xmlNewDocPI(ctxt->myDoc, target, data);
   2556     if (ret == NULL) return;
   2557     parent = ctxt->node;
   2558 
   2559     if (ctxt->linenumbers) {
   2560 	if (ctxt->input != NULL) {
   2561 	    if (ctxt->input->line < 65535)
   2562 		ret->line = (short) ctxt->input->line;
   2563 	    else
   2564 	        ret->line = 65535;
   2565 	}
   2566     }
   2567     if (ctxt->inSubset == 1) {
   2568 	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
   2569 	return;
   2570     } else if (ctxt->inSubset == 2) {
   2571 	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
   2572 	return;
   2573     }
   2574     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2575 #ifdef DEBUG_SAX_TREE
   2576 	    xmlGenericError(xmlGenericErrorContext,
   2577 		    "Setting PI %s as root\n", target);
   2578 #endif
   2579         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2580 	return;
   2581     }
   2582     if (parent->type == XML_ELEMENT_NODE) {
   2583 #ifdef DEBUG_SAX_TREE
   2584 	xmlGenericError(xmlGenericErrorContext,
   2585 		"adding PI %s child to %s\n", target, parent->name);
   2586 #endif
   2587 	xmlAddChild(parent, ret);
   2588     } else {
   2589 #ifdef DEBUG_SAX_TREE
   2590 	xmlGenericError(xmlGenericErrorContext,
   2591 		"adding PI %s sibling to ", target);
   2592 	xmlDebugDumpOneNode(stderr, parent, 0);
   2593 #endif
   2594 	xmlAddSibling(parent, ret);
   2595     }
   2596 }
   2597 
   2598 /**
   2599  * xmlSAX2Comment:
   2600  * @ctx: the user data (XML parser context)
   2601  * @value:  the xmlSAX2Comment content
   2602  *
   2603  * A xmlSAX2Comment has been parsed.
   2604  */
   2605 void
   2606 xmlSAX2Comment(void *ctx, const xmlChar *value)
   2607 {
   2608     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2609     xmlNodePtr ret;
   2610     xmlNodePtr parent;
   2611 
   2612     if (ctx == NULL) return;
   2613     parent = ctxt->node;
   2614 #ifdef DEBUG_SAX
   2615     xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
   2616 #endif
   2617     ret = xmlNewDocComment(ctxt->myDoc, value);
   2618     if (ret == NULL) return;
   2619     if (ctxt->linenumbers) {
   2620 	if (ctxt->input != NULL) {
   2621 	    if (ctxt->input->line < 65535)
   2622 		ret->line = (short) ctxt->input->line;
   2623 	    else
   2624 	        ret->line = 65535;
   2625 	}
   2626     }
   2627 
   2628     if (ctxt->inSubset == 1) {
   2629 	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
   2630 	return;
   2631     } else if (ctxt->inSubset == 2) {
   2632 	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
   2633 	return;
   2634     }
   2635     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2636 #ifdef DEBUG_SAX_TREE
   2637 	    xmlGenericError(xmlGenericErrorContext,
   2638 		    "Setting xmlSAX2Comment as root\n");
   2639 #endif
   2640         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2641 	return;
   2642     }
   2643     if (parent->type == XML_ELEMENT_NODE) {
   2644 #ifdef DEBUG_SAX_TREE
   2645 	xmlGenericError(xmlGenericErrorContext,
   2646 		"adding xmlSAX2Comment child to %s\n", parent->name);
   2647 #endif
   2648 	xmlAddChild(parent, ret);
   2649     } else {
   2650 #ifdef DEBUG_SAX_TREE
   2651 	xmlGenericError(xmlGenericErrorContext,
   2652 		"adding xmlSAX2Comment sibling to ");
   2653 	xmlDebugDumpOneNode(stderr, parent, 0);
   2654 #endif
   2655 	xmlAddSibling(parent, ret);
   2656     }
   2657 }
   2658 
   2659 /**
   2660  * xmlSAX2CDataBlock:
   2661  * @ctx: the user data (XML parser context)
   2662  * @value:  The pcdata content
   2663  * @len:  the block length
   2664  *
   2665  * called when a pcdata block has been parsed
   2666  */
   2667 void
   2668 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
   2669 {
   2670     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2671     xmlNodePtr ret, lastChild;
   2672 
   2673     if (ctx == NULL) return;
   2674 #ifdef DEBUG_SAX
   2675     xmlGenericError(xmlGenericErrorContext,
   2676 	    "SAX.pcdata(%.10s, %d)\n", value, len);
   2677 #endif
   2678     lastChild = xmlGetLastChild(ctxt->node);
   2679 #ifdef DEBUG_SAX_TREE
   2680     xmlGenericError(xmlGenericErrorContext,
   2681 	    "add chars to %s \n", ctxt->node->name);
   2682 #endif
   2683     if ((lastChild != NULL) &&
   2684         (lastChild->type == XML_CDATA_SECTION_NODE)) {
   2685 	xmlTextConcat(lastChild, value, len);
   2686     } else {
   2687 	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
   2688 	xmlAddChild(ctxt->node, ret);
   2689     }
   2690 }
   2691 
   2692 static int xmlSAX2DefaultVersionValue = 2;
   2693 
   2694 #ifdef LIBXML_SAX1_ENABLED
   2695 /**
   2696  * xmlSAXDefaultVersion:
   2697  * @version:  the version, 1 or 2
   2698  *
   2699  * Set the default version of SAX used globally by the library.
   2700  * By default, during initialization the default is set to 2.
   2701  * Note that it is generally a better coding style to use
   2702  * xmlSAXVersion() to set up the version explicitly for a given
   2703  * parsing context.
   2704  *
   2705  * Returns the previous value in case of success and -1 in case of error.
   2706  */
   2707 int
   2708 xmlSAXDefaultVersion(int version)
   2709 {
   2710     int ret = xmlSAX2DefaultVersionValue;
   2711 
   2712     if ((version != 1) && (version != 2))
   2713         return(-1);
   2714     xmlSAX2DefaultVersionValue = version;
   2715     return(ret);
   2716 }
   2717 #endif /* LIBXML_SAX1_ENABLED */
   2718 
   2719 /**
   2720  * xmlSAXVersion:
   2721  * @hdlr:  the SAX handler
   2722  * @version:  the version, 1 or 2
   2723  *
   2724  * Initialize the default XML SAX handler according to the version
   2725  *
   2726  * Returns 0 in case of success and -1 in case of error.
   2727  */
   2728 int
   2729 xmlSAXVersion(xmlSAXHandler *hdlr, int version)
   2730 {
   2731     if (hdlr == NULL) return(-1);
   2732     if (version == 2) {
   2733 	hdlr->startElement = NULL;
   2734 	hdlr->endElement = NULL;
   2735 	hdlr->startElementNs = xmlSAX2StartElementNs;
   2736 	hdlr->endElementNs = xmlSAX2EndElementNs;
   2737 	hdlr->serror = NULL;
   2738 	hdlr->initialized = XML_SAX2_MAGIC;
   2739 #ifdef LIBXML_SAX1_ENABLED
   2740     } else if (version == 1) {
   2741 	hdlr->startElement = xmlSAX2StartElement;
   2742 	hdlr->endElement = xmlSAX2EndElement;
   2743 	hdlr->initialized = 1;
   2744 #endif /* LIBXML_SAX1_ENABLED */
   2745     } else
   2746         return(-1);
   2747     hdlr->internalSubset = xmlSAX2InternalSubset;
   2748     hdlr->externalSubset = xmlSAX2ExternalSubset;
   2749     hdlr->isStandalone = xmlSAX2IsStandalone;
   2750     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
   2751     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
   2752     hdlr->resolveEntity = xmlSAX2ResolveEntity;
   2753     hdlr->getEntity = xmlSAX2GetEntity;
   2754     hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
   2755     hdlr->entityDecl = xmlSAX2EntityDecl;
   2756     hdlr->attributeDecl = xmlSAX2AttributeDecl;
   2757     hdlr->elementDecl = xmlSAX2ElementDecl;
   2758     hdlr->notationDecl = xmlSAX2NotationDecl;
   2759     hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
   2760     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2761     hdlr->startDocument = xmlSAX2StartDocument;
   2762     hdlr->endDocument = xmlSAX2EndDocument;
   2763     hdlr->reference = xmlSAX2Reference;
   2764     hdlr->characters = xmlSAX2Characters;
   2765     hdlr->cdataBlock = xmlSAX2CDataBlock;
   2766     hdlr->ignorableWhitespace = xmlSAX2Characters;
   2767     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
   2768     hdlr->comment = xmlSAX2Comment;
   2769     hdlr->warning = xmlParserWarning;
   2770     hdlr->error = xmlParserError;
   2771     hdlr->fatalError = xmlParserError;
   2772 
   2773     return(0);
   2774 }
   2775 
   2776 /**
   2777  * xmlSAX2InitDefaultSAXHandler:
   2778  * @hdlr:  the SAX handler
   2779  * @warning:  flag if non-zero sets the handler warning procedure
   2780  *
   2781  * Initialize the default XML SAX2 handler
   2782  */
   2783 void
   2784 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
   2785 {
   2786     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2787 	return;
   2788 
   2789     xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
   2790     if (warning == 0)
   2791 	hdlr->warning = NULL;
   2792     else
   2793 	hdlr->warning = xmlParserWarning;
   2794 }
   2795 
   2796 /**
   2797  * xmlDefaultSAXHandlerInit:
   2798  *
   2799  * Initialize the default SAX2 handler
   2800  */
   2801 void
   2802 xmlDefaultSAXHandlerInit(void)
   2803 {
   2804 #ifdef LIBXML_SAX1_ENABLED
   2805     xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
   2806 #endif /* LIBXML_SAX1_ENABLED */
   2807 }
   2808 
   2809 #ifdef LIBXML_HTML_ENABLED
   2810 
   2811 /**
   2812  * xmlSAX2InitHtmlDefaultSAXHandler:
   2813  * @hdlr:  the SAX handler
   2814  *
   2815  * Initialize the default HTML SAX2 handler
   2816  */
   2817 void
   2818 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
   2819 {
   2820     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2821 	return;
   2822 
   2823     hdlr->internalSubset = xmlSAX2InternalSubset;
   2824     hdlr->externalSubset = NULL;
   2825     hdlr->isStandalone = NULL;
   2826     hdlr->hasInternalSubset = NULL;
   2827     hdlr->hasExternalSubset = NULL;
   2828     hdlr->resolveEntity = NULL;
   2829     hdlr->getEntity = xmlSAX2GetEntity;
   2830     hdlr->getParameterEntity = NULL;
   2831     hdlr->entityDecl = NULL;
   2832     hdlr->attributeDecl = NULL;
   2833     hdlr->elementDecl = NULL;
   2834     hdlr->notationDecl = NULL;
   2835     hdlr->unparsedEntityDecl = NULL;
   2836     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2837     hdlr->startDocument = xmlSAX2StartDocument;
   2838     hdlr->endDocument = xmlSAX2EndDocument;
   2839     hdlr->startElement = xmlSAX2StartElement;
   2840     hdlr->endElement = xmlSAX2EndElement;
   2841     hdlr->reference = NULL;
   2842     hdlr->characters = xmlSAX2Characters;
   2843     hdlr->cdataBlock = xmlSAX2CDataBlock;
   2844     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
   2845     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
   2846     hdlr->comment = xmlSAX2Comment;
   2847     hdlr->warning = xmlParserWarning;
   2848     hdlr->error = xmlParserError;
   2849     hdlr->fatalError = xmlParserError;
   2850 
   2851     hdlr->initialized = 1;
   2852 }
   2853 
   2854 /**
   2855  * htmlDefaultSAXHandlerInit:
   2856  *
   2857  * Initialize the default SAX handler
   2858  */
   2859 void
   2860 htmlDefaultSAXHandlerInit(void)
   2861 {
   2862     xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
   2863 }
   2864 
   2865 #endif /* LIBXML_HTML_ENABLED */
   2866 
   2867 #ifdef LIBXML_DOCB_ENABLED
   2868 
   2869 /**
   2870  * xmlSAX2InitDocbDefaultSAXHandler:
   2871  * @hdlr:  the SAX handler
   2872  *
   2873  * Initialize the default DocBook SAX2 handler
   2874  */
   2875 void
   2876 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
   2877 {
   2878     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2879 	return;
   2880 
   2881     hdlr->internalSubset = xmlSAX2InternalSubset;
   2882     hdlr->externalSubset = NULL;
   2883     hdlr->isStandalone = xmlSAX2IsStandalone;
   2884     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
   2885     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
   2886     hdlr->resolveEntity = xmlSAX2ResolveEntity;
   2887     hdlr->getEntity = xmlSAX2GetEntity;
   2888     hdlr->getParameterEntity = NULL;
   2889     hdlr->entityDecl = xmlSAX2EntityDecl;
   2890     hdlr->attributeDecl = NULL;
   2891     hdlr->elementDecl = NULL;
   2892     hdlr->notationDecl = NULL;
   2893     hdlr->unparsedEntityDecl = NULL;
   2894     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2895     hdlr->startDocument = xmlSAX2StartDocument;
   2896     hdlr->endDocument = xmlSAX2EndDocument;
   2897     hdlr->startElement = xmlSAX2StartElement;
   2898     hdlr->endElement = xmlSAX2EndElement;
   2899     hdlr->reference = xmlSAX2Reference;
   2900     hdlr->characters = xmlSAX2Characters;
   2901     hdlr->cdataBlock = NULL;
   2902     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
   2903     hdlr->processingInstruction = NULL;
   2904     hdlr->comment = xmlSAX2Comment;
   2905     hdlr->warning = xmlParserWarning;
   2906     hdlr->error = xmlParserError;
   2907     hdlr->fatalError = xmlParserError;
   2908 
   2909     hdlr->initialized = 1;
   2910 }
   2911 
   2912 /**
   2913  * docbDefaultSAXHandlerInit:
   2914  *
   2915  * Initialize the default SAX handler
   2916  */
   2917 void
   2918 docbDefaultSAXHandlerInit(void)
   2919 {
   2920     xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
   2921 }
   2922 
   2923 #endif /* LIBXML_DOCB_ENABLED */
   2924 #define bottom_SAX2
   2925 #include "elfgcchack.h"
   2926