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