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_HTML_ENABLED
   1109     if ((ctxt->html) &&
   1110         (value == NULL) && (htmlIsBooleanAttr(fullname))) {
   1111             nval = xmlStrdup(fullname);
   1112             value = (const xmlChar *) nval;
   1113     } else
   1114 #endif
   1115     {
   1116 #ifdef LIBXML_VALID_ENABLED
   1117         /*
   1118          * Do the last stage of the attribute normalization
   1119          * Needed for HTML too:
   1120          *   http://www.w3.org/TR/html4/types.html#h-6.2
   1121          */
   1122         ctxt->vctxt.valid = 1;
   1123         nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
   1124                                                ctxt->myDoc, ctxt->node,
   1125                                                fullname, value);
   1126         if (ctxt->vctxt.valid != 1) {
   1127             ctxt->valid = 0;
   1128         }
   1129         if (nval != NULL)
   1130             value = nval;
   1131 #else
   1132         nval = NULL;
   1133 #endif /* LIBXML_VALID_ENABLED */
   1134     }
   1135 
   1136     /*
   1137      * Check whether it's a namespace definition
   1138      */
   1139     if ((!ctxt->html) && (ns == NULL) &&
   1140         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
   1141         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
   1142 	xmlNsPtr nsret;
   1143 	xmlChar *val;
   1144 
   1145         if (!ctxt->replaceEntities) {
   1146 	    ctxt->depth++;
   1147 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1148 		                          0,0,0);
   1149 	    ctxt->depth--;
   1150 	} else {
   1151 	    val = (xmlChar *) value;
   1152 	}
   1153 
   1154 	if (val[0] != 0) {
   1155 	    xmlURIPtr uri;
   1156 
   1157 	    uri = xmlParseURI((const char *)val);
   1158 	    if (uri == NULL) {
   1159 		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
   1160 		    ctxt->sax->warning(ctxt->userData,
   1161 			 "xmlns: %s not a valid URI\n", val);
   1162 	    } else {
   1163 		if (uri->scheme == NULL) {
   1164 		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
   1165 			ctxt->sax->warning(ctxt->userData,
   1166 			     "xmlns: URI %s is not absolute\n", val);
   1167 		}
   1168 		xmlFreeURI(uri);
   1169 	    }
   1170 	}
   1171 
   1172 	/* a default namespace definition */
   1173 	nsret = xmlNewNs(ctxt->node, val, NULL);
   1174 
   1175 #ifdef LIBXML_VALID_ENABLED
   1176 	/*
   1177 	 * Validate also for namespace decls, they are attributes from
   1178 	 * an XML-1.0 perspective
   1179 	 */
   1180         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
   1181 	    ctxt->myDoc && ctxt->myDoc->intSubset)
   1182 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   1183 					   ctxt->node, prefix, nsret, val);
   1184 #endif /* LIBXML_VALID_ENABLED */
   1185 	if (name != NULL)
   1186 	    xmlFree(name);
   1187 	if (nval != NULL)
   1188 	    xmlFree(nval);
   1189 	if (val != value)
   1190 	    xmlFree(val);
   1191 	return;
   1192     }
   1193     if ((!ctxt->html) &&
   1194 	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
   1195         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
   1196 	xmlNsPtr nsret;
   1197 	xmlChar *val;
   1198 
   1199         if (!ctxt->replaceEntities) {
   1200 	    ctxt->depth++;
   1201 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1202 		                          0,0,0);
   1203 	    ctxt->depth--;
   1204 	    if (val == NULL) {
   1205 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1206 	        xmlFree(ns);
   1207 		if (name != NULL)
   1208 		    xmlFree(name);
   1209 		return;
   1210 	    }
   1211 	} else {
   1212 	    val = (xmlChar *) value;
   1213 	}
   1214 
   1215 	if (val[0] == 0) {
   1216 	    xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
   1217 		        "Empty namespace name for prefix %s\n", name, NULL);
   1218 	}
   1219 	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
   1220 	    xmlURIPtr uri;
   1221 
   1222 	    uri = xmlParseURI((const char *)val);
   1223 	    if (uri == NULL) {
   1224 	        xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
   1225 			 "xmlns:%s: %s not a valid URI\n", name, value);
   1226 	    } else {
   1227 		if (uri->scheme == NULL) {
   1228 		    xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
   1229 			   "xmlns:%s: URI %s is not absolute\n", name, value);
   1230 		}
   1231 		xmlFreeURI(uri);
   1232 	    }
   1233 	}
   1234 
   1235 	/* a standard namespace definition */
   1236 	nsret = xmlNewNs(ctxt->node, val, name);
   1237 	xmlFree(ns);
   1238 #ifdef LIBXML_VALID_ENABLED
   1239 	/*
   1240 	 * Validate also for namespace decls, they are attributes from
   1241 	 * an XML-1.0 perspective
   1242 	 */
   1243         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
   1244 	    ctxt->myDoc && ctxt->myDoc->intSubset)
   1245 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   1246 					   ctxt->node, prefix, nsret, value);
   1247 #endif /* LIBXML_VALID_ENABLED */
   1248 	if (name != NULL)
   1249 	    xmlFree(name);
   1250 	if (nval != NULL)
   1251 	    xmlFree(nval);
   1252 	if (val != value)
   1253 	    xmlFree(val);
   1254 	return;
   1255     }
   1256 
   1257     if (ns != NULL) {
   1258 	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
   1259 
   1260 	if (namespace == NULL) {
   1261 	    xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   1262 		    "Namespace prefix %s of attribute %s is not defined\n",
   1263 		             ns, name);
   1264 	} else {
   1265             xmlAttrPtr prop;
   1266 
   1267             prop = ctxt->node->properties;
   1268             while (prop != NULL) {
   1269                 if (prop->ns != NULL) {
   1270                     if ((xmlStrEqual(name, prop->name)) &&
   1271                         ((namespace == prop->ns) ||
   1272                          (xmlStrEqual(namespace->href, prop->ns->href)))) {
   1273                             xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
   1274                                     "Attribute %s in %s redefined\n",
   1275                                              name, namespace->href);
   1276                         ctxt->wellFormed = 0;
   1277                         if (ctxt->recovery == 0) ctxt->disableSAX = 1;
   1278                         goto error;
   1279                     }
   1280                 }
   1281                 prop = prop->next;
   1282             }
   1283         }
   1284     } else {
   1285 	namespace = NULL;
   1286     }
   1287 
   1288     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
   1289     ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
   1290 
   1291     if (ret != NULL) {
   1292         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
   1293 	    xmlNodePtr tmp;
   1294 
   1295 	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
   1296 	    tmp = ret->children;
   1297 	    while (tmp != NULL) {
   1298 		tmp->parent = (xmlNodePtr) ret;
   1299 		if (tmp->next == NULL)
   1300 		    ret->last = tmp;
   1301 		tmp = tmp->next;
   1302 	    }
   1303 	} else if (value != NULL) {
   1304 	    ret->children = xmlNewDocText(ctxt->myDoc, value);
   1305 	    ret->last = ret->children;
   1306 	    if (ret->children != NULL)
   1307 		ret->children->parent = (xmlNodePtr) ret;
   1308 	}
   1309     }
   1310 
   1311 #ifdef LIBXML_VALID_ENABLED
   1312     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   1313         ctxt->myDoc && ctxt->myDoc->intSubset) {
   1314 
   1315 	/*
   1316 	 * If we don't substitute entities, the validation should be
   1317 	 * done on a value with replaced entities anyway.
   1318 	 */
   1319         if (!ctxt->replaceEntities) {
   1320 	    xmlChar *val;
   1321 
   1322 	    ctxt->depth++;
   1323 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
   1324 		                          0,0,0);
   1325 	    ctxt->depth--;
   1326 
   1327 	    if (val == NULL)
   1328 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   1329 				ctxt->myDoc, ctxt->node, ret, value);
   1330 	    else {
   1331 		xmlChar *nvalnorm;
   1332 
   1333 		/*
   1334 		 * Do the last stage of the attribute normalization
   1335 		 * It need to be done twice ... it's an extra burden related
   1336 		 * to the ability to keep xmlSAX2References in attributes
   1337 		 */
   1338 		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
   1339 					    ctxt->node, fullname, val);
   1340 		if (nvalnorm != NULL) {
   1341 		    xmlFree(val);
   1342 		    val = nvalnorm;
   1343 		}
   1344 
   1345 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   1346 			        ctxt->myDoc, ctxt->node, ret, val);
   1347                 xmlFree(val);
   1348 	    }
   1349 	} else {
   1350 	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
   1351 					       ctxt->node, ret, value);
   1352 	}
   1353     } else
   1354 #endif /* LIBXML_VALID_ENABLED */
   1355            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
   1356 	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
   1357 	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
   1358         /*
   1359 	 * when validating, the ID registration is done at the attribute
   1360 	 * validation level. Otherwise we have to do specific handling here.
   1361 	 */
   1362 	if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
   1363 	    /*
   1364 	     * Add the xml:id value
   1365 	     *
   1366 	     * Open issue: normalization of the value.
   1367 	     */
   1368 	    if (xmlValidateNCName(value, 1) != 0) {
   1369 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
   1370 		      "xml:id : attribute value %s is not an NCName\n",
   1371 			    (const char *) value, NULL);
   1372 	    }
   1373 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1374 	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
   1375 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1376 	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
   1377 	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
   1378     }
   1379 
   1380 error:
   1381     if (nval != NULL)
   1382 	xmlFree(nval);
   1383     if (ns != NULL)
   1384 	xmlFree(ns);
   1385 }
   1386 
   1387 /*
   1388  * xmlCheckDefaultedAttributes:
   1389  *
   1390  * Check defaulted attributes from the DTD
   1391  */
   1392 static void
   1393 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
   1394 	const xmlChar *prefix, const xmlChar **atts) {
   1395     xmlElementPtr elemDecl;
   1396     const xmlChar *att;
   1397     int internal = 1;
   1398     int i;
   1399 
   1400     elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
   1401     if (elemDecl == NULL) {
   1402 	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
   1403 	internal = 0;
   1404     }
   1405 
   1406 process_external_subset:
   1407 
   1408     if (elemDecl != NULL) {
   1409 	xmlAttributePtr attr = elemDecl->attributes;
   1410 	/*
   1411 	 * Check against defaulted attributes from the external subset
   1412 	 * if the document is stamped as standalone
   1413 	 */
   1414 	if ((ctxt->myDoc->standalone == 1) &&
   1415 	    (ctxt->myDoc->extSubset != NULL) &&
   1416 	    (ctxt->validate)) {
   1417 	    while (attr != NULL) {
   1418 		if ((attr->defaultValue != NULL) &&
   1419 		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
   1420 					attr->elem, attr->name,
   1421 					attr->prefix) == attr) &&
   1422 		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
   1423 					attr->elem, attr->name,
   1424 					attr->prefix) == NULL)) {
   1425 		    xmlChar *fulln;
   1426 
   1427 		    if (attr->prefix != NULL) {
   1428 			fulln = xmlStrdup(attr->prefix);
   1429 			fulln = xmlStrcat(fulln, BAD_CAST ":");
   1430 			fulln = xmlStrcat(fulln, attr->name);
   1431 		    } else {
   1432 			fulln = xmlStrdup(attr->name);
   1433 		    }
   1434                     if (fulln == NULL) {
   1435                         xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1436                         break;
   1437                     }
   1438 
   1439 		    /*
   1440 		     * Check that the attribute is not declared in the
   1441 		     * serialization
   1442 		     */
   1443 		    att = NULL;
   1444 		    if (atts != NULL) {
   1445 			i = 0;
   1446 			att = atts[i];
   1447 			while (att != NULL) {
   1448 			    if (xmlStrEqual(att, fulln))
   1449 				break;
   1450 			    i += 2;
   1451 			    att = atts[i];
   1452 			}
   1453 		    }
   1454 		    if (att == NULL) {
   1455 		        xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
   1456       "standalone: attribute %s on %s defaulted from external subset\n",
   1457 				    (const char *)fulln,
   1458 				    (const char *)attr->elem);
   1459 		    }
   1460                     xmlFree(fulln);
   1461 		}
   1462 		attr = attr->nexth;
   1463 	    }
   1464 	}
   1465 
   1466 	/*
   1467 	 * Actually insert defaulted values when needed
   1468 	 */
   1469 	attr = elemDecl->attributes;
   1470 	while (attr != NULL) {
   1471 	    /*
   1472 	     * Make sure that attributes redefinition occuring in the
   1473 	     * internal subset are not overriden by definitions in the
   1474 	     * external subset.
   1475 	     */
   1476 	    if (attr->defaultValue != NULL) {
   1477 		/*
   1478 		 * the element should be instantiated in the tree if:
   1479 		 *  - this is a namespace prefix
   1480 		 *  - the user required for completion in the tree
   1481 		 *    like XSLT
   1482 		 *  - there isn't already an attribute definition
   1483 		 *    in the internal subset overriding it.
   1484 		 */
   1485 		if (((attr->prefix != NULL) &&
   1486 		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
   1487 		    ((attr->prefix == NULL) &&
   1488 		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
   1489 		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
   1490 		    xmlAttributePtr tst;
   1491 
   1492 		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
   1493 					     attr->elem, attr->name,
   1494 					     attr->prefix);
   1495 		    if ((tst == attr) || (tst == NULL)) {
   1496 		        xmlChar fn[50];
   1497 			xmlChar *fulln;
   1498 
   1499                         fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
   1500 			if (fulln == NULL) {
   1501 			    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1502 			    return;
   1503 			}
   1504 
   1505 			/*
   1506 			 * Check that the attribute is not declared in the
   1507 			 * serialization
   1508 			 */
   1509 			att = NULL;
   1510 			if (atts != NULL) {
   1511 			    i = 0;
   1512 			    att = atts[i];
   1513 			    while (att != NULL) {
   1514 				if (xmlStrEqual(att, fulln))
   1515 				    break;
   1516 				i += 2;
   1517 				att = atts[i];
   1518 			    }
   1519 			}
   1520 			if (att == NULL) {
   1521 			    xmlSAX2AttributeInternal(ctxt, fulln,
   1522 						 attr->defaultValue, prefix);
   1523 			}
   1524 			if ((fulln != fn) && (fulln != attr->name))
   1525 			    xmlFree(fulln);
   1526 		    }
   1527 		}
   1528 	    }
   1529 	    attr = attr->nexth;
   1530 	}
   1531 	if (internal == 1) {
   1532 	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
   1533 		                             name, prefix);
   1534 	    internal = 0;
   1535 	    goto process_external_subset;
   1536 	}
   1537     }
   1538 }
   1539 
   1540 /**
   1541  * xmlSAX2StartElement:
   1542  * @ctx: the user data (XML parser context)
   1543  * @fullname:  The element name, including namespace prefix
   1544  * @atts:  An array of name/value attributes pairs, NULL terminated
   1545  *
   1546  * called when an opening tag has been processed.
   1547  */
   1548 void
   1549 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
   1550 {
   1551     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1552     xmlNodePtr ret;
   1553     xmlNodePtr parent;
   1554     xmlNsPtr ns;
   1555     xmlChar *name;
   1556     xmlChar *prefix;
   1557     const xmlChar *att;
   1558     const xmlChar *value;
   1559     int i;
   1560 
   1561     if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
   1562     parent = ctxt->node;
   1563 #ifdef DEBUG_SAX
   1564     xmlGenericError(xmlGenericErrorContext,
   1565 	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
   1566 #endif
   1567 
   1568     /*
   1569      * First check on validity:
   1570      */
   1571     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
   1572         ((ctxt->myDoc->intSubset == NULL) ||
   1573 	 ((ctxt->myDoc->intSubset->notations == NULL) &&
   1574 	  (ctxt->myDoc->intSubset->elements == NULL) &&
   1575 	  (ctxt->myDoc->intSubset->attributes == NULL) &&
   1576 	  (ctxt->myDoc->intSubset->entities == NULL)))) {
   1577 	xmlErrValid(ctxt, XML_ERR_NO_DTD,
   1578 	  "Validation failed: no DTD found !", NULL, NULL);
   1579 	ctxt->validate = 0;
   1580     }
   1581 
   1582 
   1583     /*
   1584      * Split the full name into a namespace prefix and the tag name
   1585      */
   1586     name = xmlSplitQName(ctxt, fullname, &prefix);
   1587 
   1588 
   1589     /*
   1590      * Note : the namespace resolution is deferred until the end of the
   1591      *        attributes parsing, since local namespace can be defined as
   1592      *        an attribute at this level.
   1593      */
   1594     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
   1595     if (ret == NULL) {
   1596         if (prefix != NULL)
   1597 	    xmlFree(prefix);
   1598 	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
   1599         return;
   1600     }
   1601     if (ctxt->myDoc->children == NULL) {
   1602 #ifdef DEBUG_SAX_TREE
   1603 	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
   1604 #endif
   1605         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   1606     } else if (parent == NULL) {
   1607         parent = ctxt->myDoc->children;
   1608     }
   1609     ctxt->nodemem = -1;
   1610     if (ctxt->linenumbers) {
   1611 	if (ctxt->input != NULL) {
   1612 	    if (ctxt->input->line < 65535)
   1613 		ret->line = (short) ctxt->input->line;
   1614 	    else
   1615 	        ret->line = 65535;
   1616 	}
   1617     }
   1618 
   1619     /*
   1620      * We are parsing a new node.
   1621      */
   1622 #ifdef DEBUG_SAX_TREE
   1623     xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
   1624 #endif
   1625     nodePush(ctxt, ret);
   1626 
   1627     /*
   1628      * Link the child element
   1629      */
   1630     if (parent != NULL) {
   1631         if (parent->type == XML_ELEMENT_NODE) {
   1632 #ifdef DEBUG_SAX_TREE
   1633 	    xmlGenericError(xmlGenericErrorContext,
   1634 		    "adding child %s to %s\n", name, parent->name);
   1635 #endif
   1636 	    xmlAddChild(parent, ret);
   1637 	} else {
   1638 #ifdef DEBUG_SAX_TREE
   1639 	    xmlGenericError(xmlGenericErrorContext,
   1640 		    "adding sibling %s to ", name);
   1641 	    xmlDebugDumpOneNode(stderr, parent, 0);
   1642 #endif
   1643 	    xmlAddSibling(parent, ret);
   1644 	}
   1645     }
   1646 
   1647     /*
   1648      * Insert all the defaulted attributes from the DTD especially namespaces
   1649      */
   1650     if ((!ctxt->html) &&
   1651 	((ctxt->myDoc->intSubset != NULL) ||
   1652 	 (ctxt->myDoc->extSubset != NULL))) {
   1653 	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
   1654     }
   1655 
   1656     /*
   1657      * process all the attributes whose name start with "xmlns"
   1658      */
   1659     if (atts != NULL) {
   1660         i = 0;
   1661 	att = atts[i++];
   1662 	value = atts[i++];
   1663 	if (!ctxt->html) {
   1664 	    while ((att != NULL) && (value != NULL)) {
   1665 		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
   1666 		    (att[3] == 'n') && (att[4] == 's'))
   1667 		    xmlSAX2AttributeInternal(ctxt, att, value, prefix);
   1668 
   1669 		att = atts[i++];
   1670 		value = atts[i++];
   1671 	    }
   1672 	}
   1673     }
   1674 
   1675     /*
   1676      * Search the namespace, note that since the attributes have been
   1677      * processed, the local namespaces are available.
   1678      */
   1679     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
   1680     if ((ns == NULL) && (parent != NULL))
   1681 	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
   1682     if ((prefix != NULL) && (ns == NULL)) {
   1683 	ns = xmlNewNs(ret, NULL, prefix);
   1684 	xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   1685 		     "Namespace prefix %s is not defined\n",
   1686 		     prefix, NULL);
   1687     }
   1688 
   1689     /*
   1690      * set the namespace node, making sure that if the default namspace
   1691      * is unbound on a parent we simply kee it NULL
   1692      */
   1693     if ((ns != NULL) && (ns->href != NULL) &&
   1694 	((ns->href[0] != 0) || (ns->prefix != NULL)))
   1695 	xmlSetNs(ret, ns);
   1696 
   1697     /*
   1698      * process all the other attributes
   1699      */
   1700     if (atts != NULL) {
   1701         i = 0;
   1702 	att = atts[i++];
   1703 	value = atts[i++];
   1704 	if (ctxt->html) {
   1705 	    while (att != NULL) {
   1706 		xmlSAX2AttributeInternal(ctxt, att, value, NULL);
   1707 		att = atts[i++];
   1708 		value = atts[i++];
   1709 	    }
   1710 	} else {
   1711 	    while ((att != NULL) && (value != NULL)) {
   1712 		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
   1713 		    (att[3] != 'n') || (att[4] != 's'))
   1714 		    xmlSAX2AttributeInternal(ctxt, att, value, NULL);
   1715 
   1716 		/*
   1717 		 * Next ones
   1718 		 */
   1719 		att = atts[i++];
   1720 		value = atts[i++];
   1721 	    }
   1722 	}
   1723     }
   1724 
   1725 #ifdef LIBXML_VALID_ENABLED
   1726     /*
   1727      * If it's the Document root, finish the DTD validation and
   1728      * check the document root element for validity
   1729      */
   1730     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
   1731 	int chk;
   1732 
   1733 	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
   1734 	if (chk <= 0)
   1735 	    ctxt->valid = 0;
   1736 	if (chk < 0)
   1737 	    ctxt->wellFormed = 0;
   1738 	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
   1739 	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
   1740     }
   1741 #endif /* LIBXML_VALID_ENABLED */
   1742 
   1743     if (prefix != NULL)
   1744 	xmlFree(prefix);
   1745 
   1746 }
   1747 
   1748 /**
   1749  * xmlSAX2EndElement:
   1750  * @ctx: the user data (XML parser context)
   1751  * @name:  The element name
   1752  *
   1753  * called when the end of an element has been detected.
   1754  */
   1755 void
   1756 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
   1757 {
   1758     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   1759     xmlParserNodeInfo node_info;
   1760     xmlNodePtr cur;
   1761 
   1762     if (ctx == NULL) return;
   1763     cur = ctxt->node;
   1764 #ifdef DEBUG_SAX
   1765     if (name == NULL)
   1766         xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
   1767     else
   1768 	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
   1769 #endif
   1770 
   1771     /* Capture end position and add node */
   1772     if (cur != NULL && ctxt->record_info) {
   1773       node_info.end_pos = ctxt->input->cur - ctxt->input->base;
   1774       node_info.end_line = ctxt->input->line;
   1775       node_info.node = cur;
   1776       xmlParserAddNodeInfo(ctxt, &node_info);
   1777     }
   1778     ctxt->nodemem = -1;
   1779 
   1780 #ifdef LIBXML_VALID_ENABLED
   1781     if (ctxt->validate && ctxt->wellFormed &&
   1782         ctxt->myDoc && ctxt->myDoc->intSubset)
   1783         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
   1784 					     cur);
   1785 #endif /* LIBXML_VALID_ENABLED */
   1786 
   1787 
   1788     /*
   1789      * end of parsing of this node.
   1790      */
   1791 #ifdef DEBUG_SAX_TREE
   1792     xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
   1793 #endif
   1794     nodePop(ctxt);
   1795 }
   1796 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
   1797 
   1798 /*
   1799  * xmlSAX2TextNode:
   1800  * @ctxt:  the parser context
   1801  * @str:  the input string
   1802  * @len: the string length
   1803  *
   1804  * Remove the entities from an attribute value
   1805  *
   1806  * Returns the newly allocated string or NULL if not needed or error
   1807  */
   1808 static xmlNodePtr
   1809 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
   1810     xmlNodePtr ret;
   1811     const xmlChar *intern = NULL;
   1812 
   1813     /*
   1814      * Allocate
   1815      */
   1816     if (ctxt->freeElems != NULL) {
   1817 	ret = ctxt->freeElems;
   1818 	ctxt->freeElems = ret->next;
   1819 	ctxt->freeElemsNr--;
   1820     } else {
   1821 	ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
   1822     }
   1823     if (ret == NULL) {
   1824         xmlErrMemory(ctxt, "xmlSAX2Characters");
   1825 	return(NULL);
   1826     }
   1827     memset(ret, 0, sizeof(xmlNode));
   1828     /*
   1829      * intern the formatting blanks found between tags, or the
   1830      * very short strings
   1831      */
   1832     if (ctxt->dictNames) {
   1833         xmlChar cur = str[len];
   1834 
   1835 	if ((len < (int) (2 * sizeof(void *))) &&
   1836 	    (ctxt->options & XML_PARSE_COMPACT)) {
   1837 	    /* store the string in the node overrithing properties and nsDef */
   1838 	    xmlChar *tmp = (xmlChar *) &(ret->properties);
   1839 	    memcpy(tmp, str, len);
   1840 	    tmp[len] = 0;
   1841 	    intern = tmp;
   1842 	} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
   1843 	    ((cur == '<') && (str[len + 1] != '!')))) {
   1844 	    intern = xmlDictLookup(ctxt->dict, str, len);
   1845 	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
   1846 	           (str[len + 1] != '!')) {
   1847 	    int i;
   1848 
   1849 	    for (i = 1;i < len;i++) {
   1850 		if (!IS_BLANK_CH(str[i])) goto skip;
   1851 	    }
   1852 	    intern = xmlDictLookup(ctxt->dict, str, len);
   1853 	}
   1854     }
   1855 skip:
   1856     ret->type = XML_TEXT_NODE;
   1857 
   1858     ret->name = xmlStringText;
   1859     if (intern == NULL) {
   1860 	ret->content = xmlStrndup(str, len);
   1861 	if (ret->content == NULL) {
   1862 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
   1863 	    xmlFree(ret);
   1864 	    return(NULL);
   1865 	}
   1866     } else
   1867 	ret->content = (xmlChar *) intern;
   1868 
   1869     if (ctxt->input != NULL)
   1870         ret->line = ctxt->input->line;
   1871 
   1872     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   1873 	xmlRegisterNodeDefaultValue(ret);
   1874     return(ret);
   1875 }
   1876 
   1877 #ifdef LIBXML_VALID_ENABLED
   1878 /*
   1879  * xmlSAX2DecodeAttrEntities:
   1880  * @ctxt:  the parser context
   1881  * @str:  the input string
   1882  * @len: the string length
   1883  *
   1884  * Remove the entities from an attribute value
   1885  *
   1886  * Returns the newly allocated string or NULL if not needed or error
   1887  */
   1888 static xmlChar *
   1889 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
   1890                           const xmlChar *end) {
   1891     const xmlChar *in;
   1892     xmlChar *ret;
   1893 
   1894     in = str;
   1895     while (in < end)
   1896         if (*in++ == '&')
   1897 	    goto decode;
   1898     return(NULL);
   1899 decode:
   1900     ctxt->depth++;
   1901     ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
   1902 				     XML_SUBSTITUTE_REF, 0,0,0);
   1903     ctxt->depth--;
   1904     return(ret);
   1905 }
   1906 #endif /* LIBXML_VALID_ENABLED */
   1907 
   1908 /**
   1909  * xmlSAX2AttributeNs:
   1910  * @ctx: the user data (XML parser context)
   1911  * @localname:  the local name of the attribute
   1912  * @prefix:  the attribute namespace prefix if available
   1913  * @URI:  the attribute namespace name if available
   1914  * @value:  Start of the attribute value
   1915  * @valueend: end of the attribute value
   1916  *
   1917  * Handle an attribute that has been read by the parser.
   1918  * The default handling is to convert the attribute into an
   1919  * DOM subtree and past it in a new xmlAttr element added to
   1920  * the element.
   1921  */
   1922 static void
   1923 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
   1924                    const xmlChar * localname,
   1925                    const xmlChar * prefix,
   1926 		   const xmlChar * value,
   1927 		   const xmlChar * valueend)
   1928 {
   1929     xmlAttrPtr ret;
   1930     xmlNsPtr namespace = NULL;
   1931     xmlChar *dup = NULL;
   1932 
   1933     /*
   1934      * Note: if prefix == NULL, the attribute is not in the default namespace
   1935      */
   1936     if (prefix != NULL)
   1937 	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
   1938 
   1939     /*
   1940      * allocate the node
   1941      */
   1942     if (ctxt->freeAttrs != NULL) {
   1943         ret = ctxt->freeAttrs;
   1944 	ctxt->freeAttrs = ret->next;
   1945 	ctxt->freeAttrsNr--;
   1946 	memset(ret, 0, sizeof(xmlAttr));
   1947 	ret->type = XML_ATTRIBUTE_NODE;
   1948 
   1949 	ret->parent = ctxt->node;
   1950 	ret->doc = ctxt->myDoc;
   1951 	ret->ns = namespace;
   1952 
   1953 	if (ctxt->dictNames)
   1954 	    ret->name = localname;
   1955 	else
   1956 	    ret->name = xmlStrdup(localname);
   1957 
   1958         /* link at the end to preserv order, TODO speed up with a last */
   1959 	if (ctxt->node->properties == NULL) {
   1960 	    ctxt->node->properties = ret;
   1961 	} else {
   1962 	    xmlAttrPtr prev = ctxt->node->properties;
   1963 
   1964 	    while (prev->next != NULL) prev = prev->next;
   1965 	    prev->next = ret;
   1966 	    ret->prev = prev;
   1967 	}
   1968 
   1969 	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   1970 	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
   1971     } else {
   1972 	if (ctxt->dictNames)
   1973 	    ret = xmlNewNsPropEatName(ctxt->node, namespace,
   1974 	                              (xmlChar *) localname, NULL);
   1975 	else
   1976 	    ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
   1977 	if (ret == NULL) {
   1978 	    xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
   1979 	    return;
   1980 	}
   1981     }
   1982 
   1983     if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
   1984 	xmlNodePtr tmp;
   1985 
   1986 	/*
   1987 	 * We know that if there is an entity reference, then
   1988 	 * the string has been dup'ed and terminates with 0
   1989 	 * otherwise with ' or "
   1990 	 */
   1991 	if (*valueend != 0) {
   1992 	    tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
   1993 	    ret->children = tmp;
   1994 	    ret->last = tmp;
   1995 	    if (tmp != NULL) {
   1996 		tmp->doc = ret->doc;
   1997 		tmp->parent = (xmlNodePtr) ret;
   1998 	    }
   1999 	} else {
   2000 	    ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
   2001 						    valueend - value);
   2002 	    tmp = ret->children;
   2003 	    while (tmp != NULL) {
   2004 	        tmp->doc = ret->doc;
   2005 		tmp->parent = (xmlNodePtr) ret;
   2006 		if (tmp->next == NULL)
   2007 		    ret->last = tmp;
   2008 		tmp = tmp->next;
   2009 	    }
   2010 	}
   2011     } else if (value != NULL) {
   2012 	xmlNodePtr tmp;
   2013 
   2014 	tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
   2015 	ret->children = tmp;
   2016 	ret->last = tmp;
   2017 	if (tmp != NULL) {
   2018 	    tmp->doc = ret->doc;
   2019 	    tmp->parent = (xmlNodePtr) ret;
   2020 	}
   2021     }
   2022 
   2023 #ifdef LIBXML_VALID_ENABLED
   2024     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   2025         ctxt->myDoc && ctxt->myDoc->intSubset) {
   2026 	/*
   2027 	 * If we don't substitute entities, the validation should be
   2028 	 * done on a value with replaced entities anyway.
   2029 	 */
   2030         if (!ctxt->replaceEntities) {
   2031 	    dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
   2032 	    if (dup == NULL) {
   2033 	        if (*valueend == 0) {
   2034 		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2035 				    ctxt->myDoc, ctxt->node, ret, value);
   2036 		} else {
   2037 		    /*
   2038 		     * That should already be normalized.
   2039 		     * cheaper to finally allocate here than duplicate
   2040 		     * entry points in the full validation code
   2041 		     */
   2042 		    dup = xmlStrndup(value, valueend - value);
   2043 
   2044 		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2045 				    ctxt->myDoc, ctxt->node, ret, dup);
   2046 		}
   2047 	    } else {
   2048 	        /*
   2049 		 * dup now contains a string of the flattened attribute
   2050 		 * content with entities substitued. Check if we need to
   2051 		 * apply an extra layer of normalization.
   2052 		 * It need to be done twice ... it's an extra burden related
   2053 		 * to the ability to keep references in attributes
   2054 		 */
   2055 		if (ctxt->attsSpecial != NULL) {
   2056 		    xmlChar *nvalnorm;
   2057 		    xmlChar fn[50];
   2058 		    xmlChar *fullname;
   2059 
   2060 		    fullname = xmlBuildQName(localname, prefix, fn, 50);
   2061 		    if (fullname != NULL) {
   2062 			ctxt->vctxt.valid = 1;
   2063 		        nvalnorm = xmlValidCtxtNormalizeAttributeValue(
   2064 			                 &ctxt->vctxt, ctxt->myDoc,
   2065 					 ctxt->node, fullname, dup);
   2066 			if (ctxt->vctxt.valid != 1)
   2067 			    ctxt->valid = 0;
   2068 
   2069 			if ((fullname != fn) && (fullname != localname))
   2070 			    xmlFree(fullname);
   2071 			if (nvalnorm != NULL) {
   2072 			    xmlFree(dup);
   2073 			    dup = nvalnorm;
   2074 			}
   2075 		    }
   2076 		}
   2077 
   2078 		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2079 			        ctxt->myDoc, ctxt->node, ret, dup);
   2080 	    }
   2081 	} else {
   2082 	    /*
   2083 	     * if entities already have been substitued, then
   2084 	     * the attribute as passed is already normalized
   2085 	     */
   2086 	    dup = xmlStrndup(value, valueend - value);
   2087 
   2088 	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
   2089 	                             ctxt->myDoc, ctxt->node, ret, dup);
   2090 	}
   2091     } else
   2092 #endif /* LIBXML_VALID_ENABLED */
   2093            if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
   2094 	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
   2095 	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
   2096         /*
   2097 	 * when validating, the ID registration is done at the attribute
   2098 	 * validation level. Otherwise we have to do specific handling here.
   2099 	 */
   2100         if ((prefix == ctxt->str_xml) &&
   2101 	           (localname[0] == 'i') && (localname[1] == 'd') &&
   2102 		   (localname[2] == 0)) {
   2103 	    /*
   2104 	     * Add the xml:id value
   2105 	     *
   2106 	     * Open issue: normalization of the value.
   2107 	     */
   2108 	    if (dup == NULL)
   2109 	        dup = xmlStrndup(value, valueend - value);
   2110 #ifdef LIBXML_VALID_ENABLED
   2111 	    if (xmlValidateNCName(dup, 1) != 0) {
   2112 	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
   2113 		      "xml:id : attribute value %s is not an NCName\n",
   2114 			    (const char *) dup, NULL);
   2115 	    }
   2116 #endif
   2117 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2118 	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
   2119 	    /* might be worth duplicate entry points and not copy */
   2120 	    if (dup == NULL)
   2121 	        dup = xmlStrndup(value, valueend - value);
   2122 	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2123 	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
   2124 	    if (dup == NULL)
   2125 	        dup = xmlStrndup(value, valueend - value);
   2126 	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
   2127 	}
   2128     }
   2129     if (dup != NULL)
   2130 	xmlFree(dup);
   2131 }
   2132 
   2133 /**
   2134  * xmlSAX2StartElementNs:
   2135  * @ctx:  the user data (XML parser context)
   2136  * @localname:  the local name of the element
   2137  * @prefix:  the element namespace prefix if available
   2138  * @URI:  the element namespace name if available
   2139  * @nb_namespaces:  number of namespace definitions on that node
   2140  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
   2141  * @nb_attributes:  the number of attributes on that node
   2142  * @nb_defaulted:  the number of defaulted attributes.
   2143  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
   2144  *               attribute values.
   2145  *
   2146  * SAX2 callback when an element start has been detected by the parser.
   2147  * It provides the namespace informations for the element, as well as
   2148  * the new namespace declarations on the element.
   2149  */
   2150 void
   2151 xmlSAX2StartElementNs(void *ctx,
   2152                       const xmlChar *localname,
   2153 		      const xmlChar *prefix,
   2154 		      const xmlChar *URI,
   2155 		      int nb_namespaces,
   2156 		      const xmlChar **namespaces,
   2157 		      int nb_attributes,
   2158 		      int nb_defaulted,
   2159 		      const xmlChar **attributes)
   2160 {
   2161     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2162     xmlNodePtr ret;
   2163     xmlNodePtr parent;
   2164     xmlNsPtr last = NULL, ns;
   2165     const xmlChar *uri, *pref;
   2166     xmlChar *lname = NULL;
   2167     int i, j;
   2168 
   2169     if (ctx == NULL) return;
   2170     parent = ctxt->node;
   2171     /*
   2172      * First check on validity:
   2173      */
   2174     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
   2175         ((ctxt->myDoc->intSubset == NULL) ||
   2176 	 ((ctxt->myDoc->intSubset->notations == NULL) &&
   2177 	  (ctxt->myDoc->intSubset->elements == NULL) &&
   2178 	  (ctxt->myDoc->intSubset->attributes == NULL) &&
   2179 	  (ctxt->myDoc->intSubset->entities == NULL)))) {
   2180 	xmlErrValid(ctxt, XML_ERR_NO_DTD,
   2181 	  "Validation failed: no DTD found !", NULL, NULL);
   2182 	ctxt->validate = 0;
   2183     }
   2184 
   2185     /*
   2186      * Take care of the rare case of an undefined namespace prefix
   2187      */
   2188     if ((prefix != NULL) && (URI == NULL)) {
   2189         if (ctxt->dictNames) {
   2190 	    const xmlChar *fullname;
   2191 
   2192 	    fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
   2193 	    if (fullname != NULL)
   2194 	        localname = fullname;
   2195 	} else {
   2196 	    lname = xmlBuildQName(localname, prefix, NULL, 0);
   2197 	}
   2198     }
   2199     /*
   2200      * allocate the node
   2201      */
   2202     if (ctxt->freeElems != NULL) {
   2203         ret = ctxt->freeElems;
   2204 	ctxt->freeElems = ret->next;
   2205 	ctxt->freeElemsNr--;
   2206 	memset(ret, 0, sizeof(xmlNode));
   2207 	ret->type = XML_ELEMENT_NODE;
   2208 
   2209 	if (ctxt->dictNames)
   2210 	    ret->name = localname;
   2211 	else {
   2212 	    if (lname == NULL)
   2213 		ret->name = xmlStrdup(localname);
   2214 	    else
   2215 	        ret->name = lname;
   2216 	    if (ret->name == NULL) {
   2217 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2218 		return;
   2219 	    }
   2220 	}
   2221 	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
   2222 	    xmlRegisterNodeDefaultValue(ret);
   2223     } else {
   2224 	if (ctxt->dictNames)
   2225 	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
   2226 	                               (xmlChar *) localname, NULL);
   2227 	else if (lname == NULL)
   2228 	    ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
   2229 	else
   2230 	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
   2231 	                               (xmlChar *) lname, NULL);
   2232 	if (ret == NULL) {
   2233 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2234 	    return;
   2235 	}
   2236     }
   2237     if (ctxt->linenumbers) {
   2238 	if (ctxt->input != NULL) {
   2239 	    if (ctxt->input->line < 65535)
   2240 		ret->line = (short) ctxt->input->line;
   2241 	    else
   2242 	        ret->line = 65535;
   2243 	}
   2244     }
   2245 
   2246     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2247         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2248     }
   2249     /*
   2250      * Build the namespace list
   2251      */
   2252     for (i = 0,j = 0;j < nb_namespaces;j++) {
   2253         pref = namespaces[i++];
   2254 	uri = namespaces[i++];
   2255 	ns = xmlNewNs(NULL, uri, pref);
   2256 	if (ns != NULL) {
   2257 	    if (last == NULL) {
   2258 	        ret->nsDef = last = ns;
   2259 	    } else {
   2260 	        last->next = ns;
   2261 		last = ns;
   2262 	    }
   2263 	    if ((URI != NULL) && (prefix == pref))
   2264 		ret->ns = ns;
   2265 	} else {
   2266             /*
   2267              * any out of memory error would already have been raised
   2268              * but we can't be garanteed it's the actual error due to the
   2269              * API, best is to skip in this case
   2270              */
   2271 	    continue;
   2272 	}
   2273 #ifdef LIBXML_VALID_ENABLED
   2274 	if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
   2275 	    ctxt->myDoc && ctxt->myDoc->intSubset) {
   2276 	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
   2277 	                                           ret, prefix, ns, uri);
   2278 	}
   2279 #endif /* LIBXML_VALID_ENABLED */
   2280     }
   2281     ctxt->nodemem = -1;
   2282 
   2283     /*
   2284      * We are parsing a new node.
   2285      */
   2286     nodePush(ctxt, ret);
   2287 
   2288     /*
   2289      * Link the child element
   2290      */
   2291     if (parent != NULL) {
   2292         if (parent->type == XML_ELEMENT_NODE) {
   2293 	    xmlAddChild(parent, ret);
   2294 	} else {
   2295 	    xmlAddSibling(parent, ret);
   2296 	}
   2297     }
   2298 
   2299     /*
   2300      * Insert the defaulted attributes from the DTD only if requested:
   2301      */
   2302     if ((nb_defaulted != 0) &&
   2303         ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
   2304 	nb_attributes -= nb_defaulted;
   2305 
   2306     /*
   2307      * Search the namespace if it wasn't already found
   2308      * Note that, if prefix is NULL, this searches for the default Ns
   2309      */
   2310     if ((URI != NULL) && (ret->ns == NULL)) {
   2311         ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
   2312 	if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
   2313 	    ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
   2314 	}
   2315 	if (ret->ns == NULL) {
   2316 	    ns = xmlNewNs(ret, NULL, prefix);
   2317 	    if (ns == NULL) {
   2318 
   2319 	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
   2320 		return;
   2321 	    }
   2322             if (prefix != NULL)
   2323                 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   2324                              "Namespace prefix %s was not found\n",
   2325                              prefix, NULL);
   2326             else
   2327                 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
   2328                              "Namespace default prefix was not found\n",
   2329                              NULL, NULL);
   2330 	}
   2331     }
   2332 
   2333     /*
   2334      * process all the other attributes
   2335      */
   2336     if (nb_attributes > 0) {
   2337         for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
   2338 	    /*
   2339 	     * Handle the rare case of an undefined atribute prefix
   2340 	     */
   2341 	    if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
   2342 		if (ctxt->dictNames) {
   2343 		    const xmlChar *fullname;
   2344 
   2345 		    fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
   2346 		                              attributes[j]);
   2347 		    if (fullname != NULL) {
   2348 			xmlSAX2AttributeNs(ctxt, fullname, NULL,
   2349 			                   attributes[j+3], attributes[j+4]);
   2350 		        continue;
   2351 		    }
   2352 		} else {
   2353 		    lname = xmlBuildQName(attributes[j], attributes[j+1],
   2354 		                          NULL, 0);
   2355 		    if (lname != NULL) {
   2356 			xmlSAX2AttributeNs(ctxt, lname, NULL,
   2357 			                   attributes[j+3], attributes[j+4]);
   2358 			xmlFree(lname);
   2359 		        continue;
   2360 		    }
   2361 		}
   2362 	    }
   2363 	    xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
   2364 			       attributes[j+3], attributes[j+4]);
   2365 	}
   2366     }
   2367 
   2368 #ifdef LIBXML_VALID_ENABLED
   2369     /*
   2370      * If it's the Document root, finish the DTD validation and
   2371      * check the document root element for validity
   2372      */
   2373     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
   2374 	int chk;
   2375 
   2376 	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
   2377 	if (chk <= 0)
   2378 	    ctxt->valid = 0;
   2379 	if (chk < 0)
   2380 	    ctxt->wellFormed = 0;
   2381 	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
   2382 	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
   2383     }
   2384 #endif /* LIBXML_VALID_ENABLED */
   2385 }
   2386 
   2387 /**
   2388  * xmlSAX2EndElementNs:
   2389  * @ctx:  the user data (XML parser context)
   2390  * @localname:  the local name of the element
   2391  * @prefix:  the element namespace prefix if available
   2392  * @URI:  the element namespace name if available
   2393  *
   2394  * SAX2 callback when an element end has been detected by the parser.
   2395  * It provides the namespace informations for the element.
   2396  */
   2397 void
   2398 xmlSAX2EndElementNs(void *ctx,
   2399                     const xmlChar * localname ATTRIBUTE_UNUSED,
   2400                     const xmlChar * prefix ATTRIBUTE_UNUSED,
   2401 		    const xmlChar * URI ATTRIBUTE_UNUSED)
   2402 {
   2403     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2404     xmlParserNodeInfo node_info;
   2405     xmlNodePtr cur;
   2406 
   2407     if (ctx == NULL) return;
   2408     cur = ctxt->node;
   2409     /* Capture end position and add node */
   2410     if ((ctxt->record_info) && (cur != NULL)) {
   2411         node_info.end_pos = ctxt->input->cur - ctxt->input->base;
   2412         node_info.end_line = ctxt->input->line;
   2413         node_info.node = cur;
   2414         xmlParserAddNodeInfo(ctxt, &node_info);
   2415     }
   2416     ctxt->nodemem = -1;
   2417 
   2418 #ifdef LIBXML_VALID_ENABLED
   2419     if (ctxt->validate && ctxt->wellFormed &&
   2420         ctxt->myDoc && ctxt->myDoc->intSubset)
   2421         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
   2422 #endif /* LIBXML_VALID_ENABLED */
   2423 
   2424     /*
   2425      * end of parsing of this node.
   2426      */
   2427     nodePop(ctxt);
   2428 }
   2429 
   2430 /**
   2431  * xmlSAX2Reference:
   2432  * @ctx: the user data (XML parser context)
   2433  * @name:  The entity name
   2434  *
   2435  * called when an entity xmlSAX2Reference is detected.
   2436  */
   2437 void
   2438 xmlSAX2Reference(void *ctx, const xmlChar *name)
   2439 {
   2440     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2441     xmlNodePtr ret;
   2442 
   2443     if (ctx == NULL) return;
   2444 #ifdef DEBUG_SAX
   2445     xmlGenericError(xmlGenericErrorContext,
   2446 	    "SAX.xmlSAX2Reference(%s)\n", name);
   2447 #endif
   2448     if (name[0] == '#')
   2449 	ret = xmlNewCharRef(ctxt->myDoc, name);
   2450     else
   2451 	ret = xmlNewReference(ctxt->myDoc, name);
   2452 #ifdef DEBUG_SAX_TREE
   2453     xmlGenericError(xmlGenericErrorContext,
   2454 	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
   2455 #endif
   2456     if (xmlAddChild(ctxt->node, ret) == NULL) {
   2457         xmlFreeNode(ret);
   2458     }
   2459 }
   2460 
   2461 /**
   2462  * xmlSAX2Characters:
   2463  * @ctx: the user data (XML parser context)
   2464  * @ch:  a xmlChar string
   2465  * @len: the number of xmlChar
   2466  *
   2467  * receiving some chars from the parser.
   2468  */
   2469 void
   2470 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
   2471 {
   2472     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2473     xmlNodePtr lastChild;
   2474 
   2475     if (ctx == NULL) return;
   2476 #ifdef DEBUG_SAX
   2477     xmlGenericError(xmlGenericErrorContext,
   2478 	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
   2479 #endif
   2480     /*
   2481      * Handle the data if any. If there is no child
   2482      * add it as content, otherwise if the last child is text,
   2483      * concatenate it, else create a new node of type text.
   2484      */
   2485 
   2486     if (ctxt->node == NULL) {
   2487 #ifdef DEBUG_SAX_TREE
   2488 	xmlGenericError(xmlGenericErrorContext,
   2489 		"add chars: ctxt->node == NULL !\n");
   2490 #endif
   2491         return;
   2492     }
   2493     lastChild = ctxt->node->last;
   2494 #ifdef DEBUG_SAX_TREE
   2495     xmlGenericError(xmlGenericErrorContext,
   2496 	    "add chars to %s \n", ctxt->node->name);
   2497 #endif
   2498 
   2499     /*
   2500      * Here we needed an accelerator mechanism in case of very large
   2501      * elements. Use an attribute in the structure !!!
   2502      */
   2503     if (lastChild == NULL) {
   2504         lastChild = xmlSAX2TextNode(ctxt, ch, len);
   2505 	if (lastChild != NULL) {
   2506 	    ctxt->node->children = lastChild;
   2507 	    ctxt->node->last = lastChild;
   2508 	    lastChild->parent = ctxt->node;
   2509 	    lastChild->doc = ctxt->node->doc;
   2510 	    ctxt->nodelen = len;
   2511 	    ctxt->nodemem = len + 1;
   2512 	} else {
   2513 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2514 	    return;
   2515 	}
   2516     } else {
   2517 	int coalesceText = (lastChild != NULL) &&
   2518 	    (lastChild->type == XML_TEXT_NODE) &&
   2519 	    (lastChild->name == xmlStringText);
   2520 	if ((coalesceText) && (ctxt->nodemem != 0)) {
   2521 	    /*
   2522 	     * The whole point of maintaining nodelen and nodemem,
   2523 	     * xmlTextConcat is too costly, i.e. compute length,
   2524 	     * reallocate a new buffer, move data, append ch. Here
   2525 	     * We try to minimaze realloc() uses and avoid copying
   2526 	     * and recomputing length over and over.
   2527 	     */
   2528 	    if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
   2529 		lastChild->content = xmlStrdup(lastChild->content);
   2530 		lastChild->properties = NULL;
   2531 	    } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
   2532 	               (xmlDictOwns(ctxt->dict, lastChild->content))) {
   2533 		lastChild->content = xmlStrdup(lastChild->content);
   2534 	    }
   2535             if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
   2536                 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
   2537                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
   2538                 return;
   2539             }
   2540 	    if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
   2541 	        (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
   2542                 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
   2543                 return;
   2544 	    }
   2545 	    if (ctxt->nodelen + len >= ctxt->nodemem) {
   2546 		xmlChar *newbuf;
   2547 		size_t size;
   2548 
   2549 		size = ctxt->nodemem + len;
   2550 		size *= 2;
   2551                 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
   2552 		if (newbuf == NULL) {
   2553 		    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2554 		    return;
   2555 		}
   2556 		ctxt->nodemem = size;
   2557 		lastChild->content = newbuf;
   2558 	    }
   2559 	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
   2560 	    ctxt->nodelen += len;
   2561 	    lastChild->content[ctxt->nodelen] = 0;
   2562 	} else if (coalesceText) {
   2563 	    if (xmlTextConcat(lastChild, ch, len)) {
   2564 		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
   2565 	    }
   2566 	    if (ctxt->node->children != NULL) {
   2567 		ctxt->nodelen = xmlStrlen(lastChild->content);
   2568 		ctxt->nodemem = ctxt->nodelen + 1;
   2569 	    }
   2570 	} else {
   2571 	    /* Mixed content, first time */
   2572 	    lastChild = xmlSAX2TextNode(ctxt, ch, len);
   2573 	    if (lastChild != NULL) {
   2574 		xmlAddChild(ctxt->node, lastChild);
   2575 		if (ctxt->node->children != NULL) {
   2576 		    ctxt->nodelen = len;
   2577 		    ctxt->nodemem = len + 1;
   2578 		}
   2579 	    }
   2580 	}
   2581     }
   2582 }
   2583 
   2584 /**
   2585  * xmlSAX2IgnorableWhitespace:
   2586  * @ctx: the user data (XML parser context)
   2587  * @ch:  a xmlChar string
   2588  * @len: the number of xmlChar
   2589  *
   2590  * receiving some ignorable whitespaces from the parser.
   2591  * UNUSED: by default the DOM building will use xmlSAX2Characters
   2592  */
   2593 void
   2594 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
   2595 {
   2596     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
   2597 #ifdef DEBUG_SAX
   2598     xmlGenericError(xmlGenericErrorContext,
   2599 	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
   2600 #endif
   2601 }
   2602 
   2603 /**
   2604  * xmlSAX2ProcessingInstruction:
   2605  * @ctx: the user data (XML parser context)
   2606  * @target:  the target name
   2607  * @data: the PI data's
   2608  *
   2609  * A processing instruction has been parsed.
   2610  */
   2611 void
   2612 xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
   2613                       const xmlChar *data)
   2614 {
   2615     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2616     xmlNodePtr ret;
   2617     xmlNodePtr parent;
   2618 
   2619     if (ctx == NULL) return;
   2620     parent = ctxt->node;
   2621 #ifdef DEBUG_SAX
   2622     xmlGenericError(xmlGenericErrorContext,
   2623 	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
   2624 #endif
   2625 
   2626     ret = xmlNewDocPI(ctxt->myDoc, target, data);
   2627     if (ret == NULL) return;
   2628 
   2629     if (ctxt->linenumbers) {
   2630 	if (ctxt->input != NULL) {
   2631 	    if (ctxt->input->line < 65535)
   2632 		ret->line = (short) ctxt->input->line;
   2633 	    else
   2634 	        ret->line = 65535;
   2635 	}
   2636     }
   2637     if (ctxt->inSubset == 1) {
   2638 	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
   2639 	return;
   2640     } else if (ctxt->inSubset == 2) {
   2641 	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
   2642 	return;
   2643     }
   2644     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2645 #ifdef DEBUG_SAX_TREE
   2646 	    xmlGenericError(xmlGenericErrorContext,
   2647 		    "Setting PI %s as root\n", target);
   2648 #endif
   2649         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2650 	return;
   2651     }
   2652     if (parent->type == XML_ELEMENT_NODE) {
   2653 #ifdef DEBUG_SAX_TREE
   2654 	xmlGenericError(xmlGenericErrorContext,
   2655 		"adding PI %s child to %s\n", target, parent->name);
   2656 #endif
   2657 	xmlAddChild(parent, ret);
   2658     } else {
   2659 #ifdef DEBUG_SAX_TREE
   2660 	xmlGenericError(xmlGenericErrorContext,
   2661 		"adding PI %s sibling to ", target);
   2662 	xmlDebugDumpOneNode(stderr, parent, 0);
   2663 #endif
   2664 	xmlAddSibling(parent, ret);
   2665     }
   2666 }
   2667 
   2668 /**
   2669  * xmlSAX2Comment:
   2670  * @ctx: the user data (XML parser context)
   2671  * @value:  the xmlSAX2Comment content
   2672  *
   2673  * A xmlSAX2Comment has been parsed.
   2674  */
   2675 void
   2676 xmlSAX2Comment(void *ctx, const xmlChar *value)
   2677 {
   2678     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2679     xmlNodePtr ret;
   2680     xmlNodePtr parent;
   2681 
   2682     if (ctx == NULL) return;
   2683     parent = ctxt->node;
   2684 #ifdef DEBUG_SAX
   2685     xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
   2686 #endif
   2687     ret = xmlNewDocComment(ctxt->myDoc, value);
   2688     if (ret == NULL) return;
   2689     if (ctxt->linenumbers) {
   2690 	if (ctxt->input != NULL) {
   2691 	    if (ctxt->input->line < 65535)
   2692 		ret->line = (short) ctxt->input->line;
   2693 	    else
   2694 	        ret->line = 65535;
   2695 	}
   2696     }
   2697 
   2698     if (ctxt->inSubset == 1) {
   2699 	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
   2700 	return;
   2701     } else if (ctxt->inSubset == 2) {
   2702 	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
   2703 	return;
   2704     }
   2705     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
   2706 #ifdef DEBUG_SAX_TREE
   2707 	    xmlGenericError(xmlGenericErrorContext,
   2708 		    "Setting xmlSAX2Comment as root\n");
   2709 #endif
   2710         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
   2711 	return;
   2712     }
   2713     if (parent->type == XML_ELEMENT_NODE) {
   2714 #ifdef DEBUG_SAX_TREE
   2715 	xmlGenericError(xmlGenericErrorContext,
   2716 		"adding xmlSAX2Comment child to %s\n", parent->name);
   2717 #endif
   2718 	xmlAddChild(parent, ret);
   2719     } else {
   2720 #ifdef DEBUG_SAX_TREE
   2721 	xmlGenericError(xmlGenericErrorContext,
   2722 		"adding xmlSAX2Comment sibling to ");
   2723 	xmlDebugDumpOneNode(stderr, parent, 0);
   2724 #endif
   2725 	xmlAddSibling(parent, ret);
   2726     }
   2727 }
   2728 
   2729 /**
   2730  * xmlSAX2CDataBlock:
   2731  * @ctx: the user data (XML parser context)
   2732  * @value:  The pcdata content
   2733  * @len:  the block length
   2734  *
   2735  * called when a pcdata block has been parsed
   2736  */
   2737 void
   2738 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
   2739 {
   2740     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
   2741     xmlNodePtr ret, lastChild;
   2742 
   2743     if (ctx == NULL) return;
   2744 #ifdef DEBUG_SAX
   2745     xmlGenericError(xmlGenericErrorContext,
   2746 	    "SAX.pcdata(%.10s, %d)\n", value, len);
   2747 #endif
   2748     lastChild = xmlGetLastChild(ctxt->node);
   2749 #ifdef DEBUG_SAX_TREE
   2750     xmlGenericError(xmlGenericErrorContext,
   2751 	    "add chars to %s \n", ctxt->node->name);
   2752 #endif
   2753     if ((lastChild != NULL) &&
   2754         (lastChild->type == XML_CDATA_SECTION_NODE)) {
   2755 	xmlTextConcat(lastChild, value, len);
   2756     } else {
   2757 	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
   2758 	xmlAddChild(ctxt->node, ret);
   2759     }
   2760 }
   2761 
   2762 static int xmlSAX2DefaultVersionValue = 2;
   2763 
   2764 #ifdef LIBXML_SAX1_ENABLED
   2765 /**
   2766  * xmlSAXDefaultVersion:
   2767  * @version:  the version, 1 or 2
   2768  *
   2769  * Set the default version of SAX used globally by the library.
   2770  * By default, during initialization the default is set to 2.
   2771  * Note that it is generally a better coding style to use
   2772  * xmlSAXVersion() to set up the version explicitly for a given
   2773  * parsing context.
   2774  *
   2775  * Returns the previous value in case of success and -1 in case of error.
   2776  */
   2777 int
   2778 xmlSAXDefaultVersion(int version)
   2779 {
   2780     int ret = xmlSAX2DefaultVersionValue;
   2781 
   2782     if ((version != 1) && (version != 2))
   2783         return(-1);
   2784     xmlSAX2DefaultVersionValue = version;
   2785     return(ret);
   2786 }
   2787 #endif /* LIBXML_SAX1_ENABLED */
   2788 
   2789 /**
   2790  * xmlSAXVersion:
   2791  * @hdlr:  the SAX handler
   2792  * @version:  the version, 1 or 2
   2793  *
   2794  * Initialize the default XML SAX handler according to the version
   2795  *
   2796  * Returns 0 in case of success and -1 in case of error.
   2797  */
   2798 int
   2799 xmlSAXVersion(xmlSAXHandler *hdlr, int version)
   2800 {
   2801     if (hdlr == NULL) return(-1);
   2802     if (version == 2) {
   2803 	hdlr->startElement = NULL;
   2804 	hdlr->endElement = NULL;
   2805 	hdlr->startElementNs = xmlSAX2StartElementNs;
   2806 	hdlr->endElementNs = xmlSAX2EndElementNs;
   2807 	hdlr->serror = NULL;
   2808 	hdlr->initialized = XML_SAX2_MAGIC;
   2809 #ifdef LIBXML_SAX1_ENABLED
   2810     } else if (version == 1) {
   2811 	hdlr->startElement = xmlSAX2StartElement;
   2812 	hdlr->endElement = xmlSAX2EndElement;
   2813 	hdlr->initialized = 1;
   2814 #endif /* LIBXML_SAX1_ENABLED */
   2815     } else
   2816         return(-1);
   2817     hdlr->internalSubset = xmlSAX2InternalSubset;
   2818     hdlr->externalSubset = xmlSAX2ExternalSubset;
   2819     hdlr->isStandalone = xmlSAX2IsStandalone;
   2820     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
   2821     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
   2822     hdlr->resolveEntity = xmlSAX2ResolveEntity;
   2823     hdlr->getEntity = xmlSAX2GetEntity;
   2824     hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
   2825     hdlr->entityDecl = xmlSAX2EntityDecl;
   2826     hdlr->attributeDecl = xmlSAX2AttributeDecl;
   2827     hdlr->elementDecl = xmlSAX2ElementDecl;
   2828     hdlr->notationDecl = xmlSAX2NotationDecl;
   2829     hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
   2830     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2831     hdlr->startDocument = xmlSAX2StartDocument;
   2832     hdlr->endDocument = xmlSAX2EndDocument;
   2833     hdlr->reference = xmlSAX2Reference;
   2834     hdlr->characters = xmlSAX2Characters;
   2835     hdlr->cdataBlock = xmlSAX2CDataBlock;
   2836     hdlr->ignorableWhitespace = xmlSAX2Characters;
   2837     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
   2838     hdlr->comment = xmlSAX2Comment;
   2839     hdlr->warning = xmlParserWarning;
   2840     hdlr->error = xmlParserError;
   2841     hdlr->fatalError = xmlParserError;
   2842 
   2843     return(0);
   2844 }
   2845 
   2846 /**
   2847  * xmlSAX2InitDefaultSAXHandler:
   2848  * @hdlr:  the SAX handler
   2849  * @warning:  flag if non-zero sets the handler warning procedure
   2850  *
   2851  * Initialize the default XML SAX2 handler
   2852  */
   2853 void
   2854 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
   2855 {
   2856     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2857 	return;
   2858 
   2859     xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
   2860     if (warning == 0)
   2861 	hdlr->warning = NULL;
   2862     else
   2863 	hdlr->warning = xmlParserWarning;
   2864 }
   2865 
   2866 /**
   2867  * xmlDefaultSAXHandlerInit:
   2868  *
   2869  * Initialize the default SAX2 handler
   2870  */
   2871 void
   2872 xmlDefaultSAXHandlerInit(void)
   2873 {
   2874 #ifdef LIBXML_SAX1_ENABLED
   2875     xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
   2876 #endif /* LIBXML_SAX1_ENABLED */
   2877 }
   2878 
   2879 #ifdef LIBXML_HTML_ENABLED
   2880 
   2881 /**
   2882  * xmlSAX2InitHtmlDefaultSAXHandler:
   2883  * @hdlr:  the SAX handler
   2884  *
   2885  * Initialize the default HTML SAX2 handler
   2886  */
   2887 void
   2888 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
   2889 {
   2890     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2891 	return;
   2892 
   2893     hdlr->internalSubset = xmlSAX2InternalSubset;
   2894     hdlr->externalSubset = NULL;
   2895     hdlr->isStandalone = NULL;
   2896     hdlr->hasInternalSubset = NULL;
   2897     hdlr->hasExternalSubset = NULL;
   2898     hdlr->resolveEntity = NULL;
   2899     hdlr->getEntity = xmlSAX2GetEntity;
   2900     hdlr->getParameterEntity = NULL;
   2901     hdlr->entityDecl = NULL;
   2902     hdlr->attributeDecl = NULL;
   2903     hdlr->elementDecl = NULL;
   2904     hdlr->notationDecl = NULL;
   2905     hdlr->unparsedEntityDecl = NULL;
   2906     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2907     hdlr->startDocument = xmlSAX2StartDocument;
   2908     hdlr->endDocument = xmlSAX2EndDocument;
   2909     hdlr->startElement = xmlSAX2StartElement;
   2910     hdlr->endElement = xmlSAX2EndElement;
   2911     hdlr->reference = NULL;
   2912     hdlr->characters = xmlSAX2Characters;
   2913     hdlr->cdataBlock = xmlSAX2CDataBlock;
   2914     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
   2915     hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
   2916     hdlr->comment = xmlSAX2Comment;
   2917     hdlr->warning = xmlParserWarning;
   2918     hdlr->error = xmlParserError;
   2919     hdlr->fatalError = xmlParserError;
   2920 
   2921     hdlr->initialized = 1;
   2922 }
   2923 
   2924 /**
   2925  * htmlDefaultSAXHandlerInit:
   2926  *
   2927  * Initialize the default SAX handler
   2928  */
   2929 void
   2930 htmlDefaultSAXHandlerInit(void)
   2931 {
   2932     xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
   2933 }
   2934 
   2935 #endif /* LIBXML_HTML_ENABLED */
   2936 
   2937 #ifdef LIBXML_DOCB_ENABLED
   2938 
   2939 /**
   2940  * xmlSAX2InitDocbDefaultSAXHandler:
   2941  * @hdlr:  the SAX handler
   2942  *
   2943  * Initialize the default DocBook SAX2 handler
   2944  */
   2945 void
   2946 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
   2947 {
   2948     if ((hdlr == NULL) || (hdlr->initialized != 0))
   2949 	return;
   2950 
   2951     hdlr->internalSubset = xmlSAX2InternalSubset;
   2952     hdlr->externalSubset = NULL;
   2953     hdlr->isStandalone = xmlSAX2IsStandalone;
   2954     hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
   2955     hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
   2956     hdlr->resolveEntity = xmlSAX2ResolveEntity;
   2957     hdlr->getEntity = xmlSAX2GetEntity;
   2958     hdlr->getParameterEntity = NULL;
   2959     hdlr->entityDecl = xmlSAX2EntityDecl;
   2960     hdlr->attributeDecl = NULL;
   2961     hdlr->elementDecl = NULL;
   2962     hdlr->notationDecl = NULL;
   2963     hdlr->unparsedEntityDecl = NULL;
   2964     hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
   2965     hdlr->startDocument = xmlSAX2StartDocument;
   2966     hdlr->endDocument = xmlSAX2EndDocument;
   2967     hdlr->startElement = xmlSAX2StartElement;
   2968     hdlr->endElement = xmlSAX2EndElement;
   2969     hdlr->reference = xmlSAX2Reference;
   2970     hdlr->characters = xmlSAX2Characters;
   2971     hdlr->cdataBlock = NULL;
   2972     hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
   2973     hdlr->processingInstruction = NULL;
   2974     hdlr->comment = xmlSAX2Comment;
   2975     hdlr->warning = xmlParserWarning;
   2976     hdlr->error = xmlParserError;
   2977     hdlr->fatalError = xmlParserError;
   2978 
   2979     hdlr->initialized = 1;
   2980 }
   2981 
   2982 /**
   2983  * docbDefaultSAXHandlerInit:
   2984  *
   2985  * Initialize the default SAX handler
   2986  */
   2987 void
   2988 docbDefaultSAXHandlerInit(void)
   2989 {
   2990     xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
   2991 }
   2992 
   2993 #endif /* LIBXML_DOCB_ENABLED */
   2994 #define bottom_SAX2
   2995 #include "elfgcchack.h"
   2996