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