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