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