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