SAX.c revision 3473f88a7abdf4e585e267288fb77e898c580d2b
1/* 2 * SAX.c : Default SAX handler to build a tree. 3 * 4 * See Copyright for the status of this software. 5 * 6 * Daniel Veillard <Daniel.Veillard@w3.org> 7 */ 8 9 10#ifdef WIN32 11#include "win32config.h" 12#else 13#include "config.h" 14#endif 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include <libxml/xmlmemory.h> 19#include <libxml/tree.h> 20#include <libxml/parser.h> 21#include <libxml/parserInternals.h> 22#include <libxml/valid.h> 23#include <libxml/entities.h> 24#include <libxml/xmlerror.h> 25#include <libxml/debugXML.h> 26#include <libxml/xmlIO.h> 27#include <libxml/SAX.h> 28#include <libxml/uri.h> 29#include <libxml/HTMLtree.h> 30 31/* #define DEBUG_SAX */ 32/* #define DEBUG_SAX_TREE */ 33 34/** 35 * getPublicId: 36 * @ctx: the user data (XML parser context) 37 * 38 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN" 39 * 40 * Returns a xmlChar * 41 */ 42const xmlChar * 43getPublicId(void *ctx) 44{ 45 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 46 return(NULL); 47} 48 49/** 50 * getSystemId: 51 * @ctx: the user data (XML parser context) 52 * 53 * Return the system ID, basically URL or filename e.g. 54 * http://www.sgmlsource.com/dtds/memo.dtd 55 * 56 * Returns a xmlChar * 57 */ 58const xmlChar * 59getSystemId(void *ctx) 60{ 61 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 62 return(BAD_CAST ctxt->input->filename); 63} 64 65/** 66 * getLineNumber: 67 * @ctx: the user data (XML parser context) 68 * 69 * Return the line number of the current parsing point. 70 * 71 * Returns an int 72 */ 73int 74getLineNumber(void *ctx) 75{ 76 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 77 return(ctxt->input->line); 78} 79 80/** 81 * getColumnNumber: 82 * @ctx: the user data (XML parser context) 83 * 84 * Return the column number of the current parsing point. 85 * 86 * Returns an int 87 */ 88int 89getColumnNumber(void *ctx) 90{ 91 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 92 return(ctxt->input->col); 93} 94 95/* 96 * The default SAX Locator. 97 */ 98 99xmlSAXLocator xmlDefaultSAXLocator = { 100 getPublicId, getSystemId, getLineNumber, getColumnNumber 101}; 102 103/** 104 * isStandalone: 105 * @ctx: the user data (XML parser context) 106 * 107 * Is this document tagged standalone ? 108 * 109 * Returns 1 if true 110 */ 111int 112isStandalone(void *ctx) 113{ 114 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 115 return(ctxt->myDoc->standalone == 1); 116} 117 118/** 119 * hasInternalSubset: 120 * @ctx: the user data (XML parser context) 121 * 122 * Does this document has an internal subset 123 * 124 * Returns 1 if true 125 */ 126int 127hasInternalSubset(void *ctx) 128{ 129 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 130 return(ctxt->myDoc->intSubset != NULL); 131} 132 133/** 134 * hasExternalSubset: 135 * @ctx: the user data (XML parser context) 136 * 137 * Does this document has an external subset 138 * 139 * Returns 1 if true 140 */ 141int 142hasExternalSubset(void *ctx) 143{ 144 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 145 return(ctxt->myDoc->extSubset != NULL); 146} 147 148/** 149 * internalSubset: 150 * @ctx: the user data (XML parser context) 151 * @name: the root element name 152 * @ExternalID: the external ID 153 * @SystemID: the SYSTEM ID (e.g. filename or URL) 154 * 155 * Callback on internal subset declaration. 156 */ 157void 158internalSubset(void *ctx, const xmlChar *name, 159 const xmlChar *ExternalID, const xmlChar *SystemID) 160{ 161 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 162 xmlDtdPtr dtd; 163#ifdef DEBUG_SAX 164 xmlGenericError(xmlGenericErrorContext, 165 "SAX.internalSubset(%s, %s, %s)\n", 166 name, ExternalID, SystemID); 167#endif 168 169 if (ctxt->myDoc == NULL) 170 return; 171 dtd = xmlGetIntSubset(ctxt->myDoc); 172 if (dtd != NULL) { 173 if (ctxt->html) 174 return; 175 xmlUnlinkNode((xmlNodePtr) dtd); 176 xmlFreeDtd(dtd); 177 ctxt->myDoc->intSubset = NULL; 178 } 179 ctxt->myDoc->intSubset = 180 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID); 181} 182 183/** 184 * externalSubset: 185 * @ctx: the user data (XML parser context) 186 * @name: the root element name 187 * @ExternalID: the external ID 188 * @SystemID: the SYSTEM ID (e.g. filename or URL) 189 * 190 * Callback on external subset declaration. 191 */ 192void 193externalSubset(void *ctx, const xmlChar *name, 194 const xmlChar *ExternalID, const xmlChar *SystemID) 195{ 196 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 197#ifdef DEBUG_SAX 198 xmlGenericError(xmlGenericErrorContext, 199 "SAX.externalSubset(%s, %s, %s)\n", 200 name, ExternalID, SystemID); 201#endif 202 if (((ExternalID != NULL) || (SystemID != NULL)) && 203 (((ctxt->validate) || (ctxt->loadsubset)) && 204 (ctxt->wellFormed && ctxt->myDoc))) { 205 /* 206 * Try to fetch and parse the external subset. 207 */ 208 xmlParserInputPtr oldinput; 209 int oldinputNr; 210 int oldinputMax; 211 xmlParserInputPtr *oldinputTab; 212 int oldwellFormed; 213 xmlParserInputPtr input = NULL; 214 xmlCharEncoding enc; 215 int oldcharset; 216 217 /* 218 * Ask the Entity resolver to load the damn thing 219 */ 220 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) 221 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, 222 SystemID); 223 if (input == NULL) { 224 return; 225 } 226 227 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID); 228 229 /* 230 * make sure we won't destroy the main document context 231 */ 232 oldinput = ctxt->input; 233 oldinputNr = ctxt->inputNr; 234 oldinputMax = ctxt->inputMax; 235 oldinputTab = ctxt->inputTab; 236 oldwellFormed = ctxt->wellFormed; 237 oldcharset = ctxt->charset; 238 239 ctxt->inputTab = (xmlParserInputPtr *) 240 xmlMalloc(5 * sizeof(xmlParserInputPtr)); 241 if (ctxt->inputTab == NULL) { 242 ctxt->errNo = XML_ERR_NO_MEMORY; 243 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 244 ctxt->sax->error(ctxt->userData, 245 "externalSubset: out of memory\n"); 246 ctxt->errNo = XML_ERR_NO_MEMORY; 247 ctxt->input = oldinput; 248 ctxt->inputNr = oldinputNr; 249 ctxt->inputMax = oldinputMax; 250 ctxt->inputTab = oldinputTab; 251 ctxt->charset = oldcharset; 252 return; 253 } 254 ctxt->inputNr = 0; 255 ctxt->inputMax = 5; 256 ctxt->input = NULL; 257 xmlPushInput(ctxt, input); 258 259 /* 260 * On the fly encoding conversion if needed 261 */ 262 enc = xmlDetectCharEncoding(ctxt->input->cur, 4); 263 xmlSwitchEncoding(ctxt, enc); 264 265 if (input->filename == NULL) 266 input->filename = (char *) xmlStrdup(SystemID); 267 input->line = 1; 268 input->col = 1; 269 input->base = ctxt->input->cur; 270 input->cur = ctxt->input->cur; 271 input->free = NULL; 272 273 /* 274 * let's parse that entity knowing it's an external subset. 275 */ 276 xmlParseExternalSubset(ctxt, ExternalID, SystemID); 277 278 /* 279 * Free up the external entities 280 */ 281 282 while (ctxt->inputNr > 1) 283 xmlPopInput(ctxt); 284 xmlFreeInputStream(ctxt->input); 285 xmlFree(ctxt->inputTab); 286 287 /* 288 * Restore the parsing context of the main entity 289 */ 290 ctxt->input = oldinput; 291 ctxt->inputNr = oldinputNr; 292 ctxt->inputMax = oldinputMax; 293 ctxt->inputTab = oldinputTab; 294 ctxt->charset = oldcharset; 295 /* ctxt->wellFormed = oldwellFormed; */ 296 } 297} 298 299/** 300 * resolveEntity: 301 * @ctx: the user data (XML parser context) 302 * @publicId: The public ID of the entity 303 * @systemId: The system ID of the entity 304 * 305 * The entity loader, to control the loading of external entities, 306 * the application can either: 307 * - override this resolveEntity() callback in the SAX block 308 * - or better use the xmlSetExternalEntityLoader() function to 309 * set up it's own entity resolution routine 310 * 311 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 312 */ 313xmlParserInputPtr 314resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId) 315{ 316 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 317 xmlParserInputPtr ret; 318 xmlChar *URI; 319 const char *base = NULL; 320 321 if (ctxt->input != NULL) 322 base = ctxt->input->filename; 323 if (base == NULL) 324 base = ctxt->directory; 325 326 URI = xmlBuildURI(systemId, (const xmlChar *) base); 327 328#ifdef DEBUG_SAX 329 xmlGenericError(xmlGenericErrorContext, 330 "SAX.resolveEntity(%s, %s)\n", publicId, systemId); 331#endif 332 333 ret = xmlLoadExternalEntity((const char *) URI, 334 (const char *) publicId, ctxt); 335 if (URI != NULL) 336 xmlFree(URI); 337 return(ret); 338} 339 340/** 341 * getEntity: 342 * @ctx: the user data (XML parser context) 343 * @name: The entity name 344 * 345 * Get an entity by name 346 * 347 * Returns the xmlEntityPtr if found. 348 */ 349xmlEntityPtr 350getEntity(void *ctx, const xmlChar *name) 351{ 352 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 353 xmlEntityPtr ret; 354 355#ifdef DEBUG_SAX 356 xmlGenericError(xmlGenericErrorContext, 357 "SAX.getEntity(%s)\n", name); 358#endif 359 360 ret = xmlGetDocEntity(ctxt->myDoc, name); 361 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) && 362 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { 363 /* 364 * for validation purposes we really need to fetch and 365 * parse the external entity 366 */ 367 int parse; 368 xmlNodePtr children; 369 370 parse = xmlParseCtxtExternalEntity(ctxt, 371 ret->SystemID, ret->ExternalID, &children); 372 xmlAddChildList((xmlNodePtr) ret, children); 373 } 374 return(ret); 375} 376 377/** 378 * getParameterEntity: 379 * @ctx: the user data (XML parser context) 380 * @name: The entity name 381 * 382 * Get a parameter entity by name 383 * 384 * Returns the xmlEntityPtr if found. 385 */ 386xmlEntityPtr 387getParameterEntity(void *ctx, const xmlChar *name) 388{ 389 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 390 xmlEntityPtr ret; 391 392#ifdef DEBUG_SAX 393 xmlGenericError(xmlGenericErrorContext, 394 "SAX.getParameterEntity(%s)\n", name); 395#endif 396 397 ret = xmlGetParameterEntity(ctxt->myDoc, name); 398 return(ret); 399} 400 401 402/** 403 * entityDecl: 404 * @ctx: the user data (XML parser context) 405 * @name: the entity name 406 * @type: the entity type 407 * @publicId: The public ID of the entity 408 * @systemId: The system ID of the entity 409 * @content: the entity value (without processing). 410 * 411 * An entity definition has been parsed 412 */ 413void 414entityDecl(void *ctx, const xmlChar *name, int type, 415 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 416{ 417 xmlEntityPtr ent; 418 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 419 420#ifdef DEBUG_SAX 421 xmlGenericError(xmlGenericErrorContext, 422 "SAX.entityDecl(%s, %d, %s, %s, %s)\n", 423 name, type, publicId, systemId, content); 424#endif 425 if (ctxt->inSubset == 1) { 426 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId, 427 systemId, content); 428 if ((ent == NULL) && (ctxt->pedantic) && 429 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 430 ctxt->sax->warning(ctxt, 431 "Entity(%s) already defined in the internal subset\n", name); 432 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 433 xmlChar *URI; 434 const char *base = NULL; 435 436 if (ctxt->input != NULL) 437 base = ctxt->input->filename; 438 if (base == NULL) 439 base = ctxt->directory; 440 441 URI = xmlBuildURI(systemId, (const xmlChar *) base); 442 ent->URI = URI; 443 } 444 } else if (ctxt->inSubset == 2) { 445 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId, 446 systemId, content); 447 if ((ent == NULL) && (ctxt->pedantic) && 448 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 449 ctxt->sax->warning(ctxt, 450 "Entity(%s) already defined in the external subset\n", name); 451 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { 452 xmlChar *URI; 453 const char *base = NULL; 454 455 if (ctxt->input != NULL) 456 base = ctxt->input->filename; 457 if (base == NULL) 458 base = ctxt->directory; 459 460 URI = xmlBuildURI(systemId, (const xmlChar *) base); 461 ent->URI = URI; 462 } 463 } else { 464 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 465 ctxt->sax->error(ctxt, 466 "SAX.entityDecl(%s) called while not in subset\n", name); 467 } 468} 469 470/** 471 * attributeDecl: 472 * @ctx: the user data (XML parser context) 473 * @elem: the name of the element 474 * @fullname: the attribute name 475 * @type: the attribute type 476 * @def: the type of default value 477 * @defaultValue: the attribute default value 478 * @tree: the tree of enumerated value set 479 * 480 * An attribute definition has been parsed 481 */ 482void 483attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, 484 int type, int def, const xmlChar *defaultValue, 485 xmlEnumerationPtr tree) 486{ 487 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 488 xmlAttributePtr attr; 489 xmlChar *name = NULL, *prefix = NULL; 490 491#ifdef DEBUG_SAX 492 xmlGenericError(xmlGenericErrorContext, 493 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", 494 elem, fullname, type, def, defaultValue); 495#endif 496 name = xmlSplitQName(ctxt, fullname, &prefix); 497 if (ctxt->inSubset == 1) 498 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem, 499 name, prefix, (xmlAttributeType) type, 500 (xmlAttributeDefault) def, defaultValue, tree); 501 else if (ctxt->inSubset == 2) 502 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem, 503 name, prefix, (xmlAttributeType) type, 504 (xmlAttributeDefault) def, defaultValue, tree); 505 else { 506 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 507 ctxt->sax->error(ctxt, 508 "SAX.attributeDecl(%s) called while not in subset\n", name); 509 return; 510 } 511 if (attr == 0) ctxt->valid = 0; 512 if (ctxt->validate && ctxt->wellFormed && 513 ctxt->myDoc && ctxt->myDoc->intSubset) 514 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc, 515 attr); 516 if (prefix != NULL) 517 xmlFree(prefix); 518 if (name != NULL) 519 xmlFree(name); 520} 521 522/** 523 * elementDecl: 524 * @ctx: the user data (XML parser context) 525 * @name: the element name 526 * @type: the element type 527 * @content: the element value tree 528 * 529 * An element definition has been parsed 530 */ 531void 532elementDecl(void *ctx, const xmlChar *name, int type, 533 xmlElementContentPtr content) 534{ 535 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 536 xmlElementPtr elem = NULL; 537 538#ifdef DEBUG_SAX 539 xmlGenericError(xmlGenericErrorContext, 540 "SAX.elementDecl(%s, %d, ...)\n", 541 fullname, type); 542#endif 543 544 if (ctxt->inSubset == 1) 545 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, 546 name, (xmlElementTypeVal) type, content); 547 else if (ctxt->inSubset == 2) 548 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, 549 name, (xmlElementTypeVal) type, content); 550 else { 551 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 552 ctxt->sax->error(ctxt, 553 "SAX.elementDecl(%s) called while not in subset\n", name); 554 return; 555 } 556 if (elem == NULL) ctxt->valid = 0; 557 if (ctxt->validate && ctxt->wellFormed && 558 ctxt->myDoc && ctxt->myDoc->intSubset) 559 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem); 560} 561 562/** 563 * notationDecl: 564 * @ctx: the user data (XML parser context) 565 * @name: The name of the notation 566 * @publicId: The public ID of the entity 567 * @systemId: The system ID of the entity 568 * 569 * What to do when a notation declaration has been parsed. 570 */ 571void 572notationDecl(void *ctx, const xmlChar *name, 573 const xmlChar *publicId, const xmlChar *systemId) 574{ 575 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 576 xmlNotationPtr nota = NULL; 577 578#ifdef DEBUG_SAX 579 xmlGenericError(xmlGenericErrorContext, 580 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId); 581#endif 582 583 if (ctxt->inSubset == 1) 584 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name, 585 publicId, systemId); 586 else if (ctxt->inSubset == 2) 587 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name, 588 publicId, systemId); 589 else { 590 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 591 ctxt->sax->error(ctxt, 592 "SAX.notationDecl(%s) called while not in subset\n", name); 593 return; 594 } 595 if (nota == NULL) ctxt->valid = 0; 596 if (ctxt->validate && ctxt->wellFormed && 597 ctxt->myDoc && ctxt->myDoc->intSubset) 598 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc, 599 nota); 600} 601 602/** 603 * unparsedEntityDecl: 604 * @ctx: the user data (XML parser context) 605 * @name: The name of the entity 606 * @publicId: The public ID of the entity 607 * @systemId: The system ID of the entity 608 * @notationName: the name of the notation 609 * 610 * What to do when an unparsed entity declaration is parsed 611 */ 612void 613unparsedEntityDecl(void *ctx, const xmlChar *name, 614 const xmlChar *publicId, const xmlChar *systemId, 615 const xmlChar *notationName) 616{ 617 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 618#ifdef DEBUG_SAX 619 xmlGenericError(xmlGenericErrorContext, 620 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n", 621 name, publicId, systemId, notationName); 622#endif 623 if (ctxt->validate && ctxt->wellFormed && 624 ctxt->myDoc && ctxt->myDoc->intSubset) 625 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc, 626 notationName); 627 xmlAddDocEntity(ctxt->myDoc, name, 628 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, 629 publicId, systemId, notationName); 630} 631 632/** 633 * setDocumentLocator: 634 * @ctx: the user data (XML parser context) 635 * @loc: A SAX Locator 636 * 637 * Receive the document locator at startup, actually xmlDefaultSAXLocator 638 * Everything is available on the context, so this is useless in our case. 639 */ 640void 641setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc) 642{ 643 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 644#ifdef DEBUG_SAX 645 xmlGenericError(xmlGenericErrorContext, 646 "SAX.setDocumentLocator()\n"); 647#endif 648} 649 650/** 651 * startDocument: 652 * @ctx: the user data (XML parser context) 653 * 654 * called when the document start being processed. 655 */ 656void 657startDocument(void *ctx) 658{ 659 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 660 xmlDocPtr doc; 661 662#ifdef DEBUG_SAX 663 xmlGenericError(xmlGenericErrorContext, 664 "SAX.startDocument()\n"); 665#endif 666 if (ctxt->html) { 667 if (ctxt->myDoc == NULL) 668#ifdef LIBXML_HTML_ENABLED 669 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); 670#else 671 xmlGenericError(xmlGenericErrorContext, 672 "libxml2 built without HTML support\n"); 673#endif 674 } else { 675 doc = ctxt->myDoc = xmlNewDoc(ctxt->version); 676 if (doc != NULL) { 677 if (ctxt->encoding != NULL) 678 doc->encoding = xmlStrdup(ctxt->encoding); 679 else 680 doc->encoding = NULL; 681 doc->standalone = ctxt->standalone; 682 } 683 } 684 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) && 685 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) { 686 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename); 687 } 688} 689 690/** 691 * endDocument: 692 * @ctx: the user data (XML parser context) 693 * 694 * called when the document end has been detected. 695 */ 696void 697endDocument(void *ctx) 698{ 699 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 700#ifdef DEBUG_SAX 701 xmlGenericError(xmlGenericErrorContext, 702 "SAX.endDocument()\n"); 703#endif 704 if (ctxt->validate && ctxt->wellFormed && 705 ctxt->myDoc && ctxt->myDoc->intSubset) 706 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc); 707 708 /* 709 * Grab the encoding if it was added on-the-fly 710 */ 711 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) && 712 (ctxt->myDoc->encoding == NULL)) { 713 ctxt->myDoc->encoding = ctxt->encoding; 714 ctxt->encoding = NULL; 715 } 716 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) && 717 (ctxt->myDoc->encoding == NULL)) { 718 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding); 719 } 720 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) && 721 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) { 722 ctxt->myDoc->charset = ctxt->charset; 723 } 724} 725 726/** 727 * attribute: 728 * @ctx: the user data (XML parser context) 729 * @fullname: The attribute name, including namespace prefix 730 * @value: The attribute value 731 * 732 * Handle an attribute that has been read by the parser. 733 * The default handling is to convert the attribute into an 734 * DOM subtree and past it in a new xmlAttr element added to 735 * the element. 736 */ 737void 738attribute(void *ctx, const xmlChar *fullname, const xmlChar *value) 739{ 740 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 741 xmlAttrPtr ret; 742 xmlChar *name; 743 xmlChar *ns; 744 xmlChar *nval; 745 xmlNsPtr namespace; 746 747/**************** 748#ifdef DEBUG_SAX 749 xmlGenericError(xmlGenericErrorContext, 750 "SAX.attribute(%s, %s)\n", fullname, value); 751#endif 752 ****************/ 753 /* 754 * Split the full name into a namespace prefix and the tag name 755 */ 756 name = xmlSplitQName(ctxt, fullname, &ns); 757 758 /* 759 * Do the last stage of the attribute normalization 760 * Needed for HTML too: 761 * http://www.w3.org/TR/html4/types.html#h-6.2 762 */ 763 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node, 764 fullname, value); 765 if (nval != NULL) 766 value = nval; 767 768 /* 769 * Check whether it's a namespace definition 770 */ 771 if ((!ctxt->html) && (ns == NULL) && 772 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && 773 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) { 774 if (value[0] != 0) { 775 xmlURIPtr uri; 776 777 uri = xmlParseURI((const char *)value); 778 if (uri == NULL) { 779 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 780 ctxt->sax->warning(ctxt->userData, 781 "nmlns: %s not a valid URI\n", value); 782 } else { 783 if (uri->scheme == NULL) { 784 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 785 ctxt->sax->warning(ctxt->userData, 786 "nmlns: URI %s is not absolute\n", value); 787 } 788 xmlFreeURI(uri); 789 } 790 } 791 792 /* a default namespace definition */ 793 xmlNewNs(ctxt->node, value, NULL); 794 if (name != NULL) 795 xmlFree(name); 796 if (nval != NULL) 797 xmlFree(nval); 798 return; 799 } 800 if ((!ctxt->html) && 801 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && 802 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) { 803 /* 804 * Validate also for namespace decls, they are attributes from 805 * an XML-1.0 perspective 806 TODO ... doesn't map well with current API 807 if (ctxt->validate && ctxt->wellFormed && 808 ctxt->myDoc && ctxt->myDoc->intSubset) 809 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, 810 ctxt->node, ret, value); 811 */ 812 /* a standard namespace definition */ 813 xmlNewNs(ctxt->node, value, name); 814 xmlFree(ns); 815 if (name != NULL) 816 xmlFree(name); 817 if (nval != NULL) 818 xmlFree(nval); 819 return; 820 } 821 822 if (ns != NULL) 823 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns); 824 else { 825 namespace = NULL; 826 } 827 828 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */ 829 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL); 830 831 if (ret != NULL) { 832 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { 833 xmlNodePtr tmp; 834 835 ret->children = xmlStringGetNodeList(ctxt->myDoc, value); 836 tmp = ret->children; 837 while (tmp != NULL) { 838 tmp->parent = (xmlNodePtr) ret; 839 if (tmp->next == NULL) 840 ret->last = tmp; 841 tmp = tmp->next; 842 } 843 } else if (value != NULL) { 844 ret->children = xmlNewDocText(ctxt->myDoc, value); 845 ret->last = ret->children; 846 if (ret->children != NULL) 847 ret->children->parent = (xmlNodePtr) ret; 848 } 849 } 850 851 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && 852 ctxt->myDoc && ctxt->myDoc->intSubset) { 853 854 /* 855 * If we don't substitute entities, the validation should be 856 * done on a value with replaced entities anyway. 857 */ 858 if (!ctxt->replaceEntities) { 859 xmlChar *val; 860 861 ctxt->depth++; 862 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, 863 0,0,0); 864 ctxt->depth--; 865 if (val == NULL) 866 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 867 ctxt->myDoc, ctxt->node, ret, value); 868 else { 869 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, 870 ctxt->myDoc, ctxt->node, ret, val); 871 xmlFree(val); 872 } 873 } else { 874 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, 875 ctxt->node, ret, value); 876 } 877 } else { 878 /* 879 * when validating, the ID registration is done at the attribute 880 * validation level. Otherwise we have to do specific handling here. 881 */ 882 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) 883 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); 884 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) 885 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret); 886 } 887 888 if (nval != NULL) 889 xmlFree(nval); 890 if (name != NULL) 891 xmlFree(name); 892 if (ns != NULL) 893 xmlFree(ns); 894} 895 896/** 897 * startElement: 898 * @ctx: the user data (XML parser context) 899 * @fullname: The element name, including namespace prefix 900 * @atts: An array of name/value attributes pairs, NULL terminated 901 * 902 * called when an opening tag has been processed. 903 */ 904void 905startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) 906{ 907 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 908 xmlNodePtr ret; 909 xmlNodePtr parent = ctxt->node; 910 xmlNsPtr ns; 911 xmlChar *name; 912 xmlChar *prefix; 913 const xmlChar *att; 914 const xmlChar *value; 915 int i; 916 917#ifdef DEBUG_SAX 918 xmlGenericError(xmlGenericErrorContext, 919 "SAX.startElement(%s)\n", fullname); 920#endif 921 922 /* 923 * First check on validity: 924 */ 925 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 926 ((ctxt->myDoc->intSubset == NULL) || 927 ((ctxt->myDoc->intSubset->notations == NULL) && 928 (ctxt->myDoc->intSubset->elements == NULL) && 929 (ctxt->myDoc->intSubset->attributes == NULL) && 930 (ctxt->myDoc->intSubset->entities == NULL)))) { 931 if (ctxt->vctxt.error != NULL) { 932 ctxt->vctxt.error(ctxt->vctxt.userData, 933 "Validation failed: no DTD found !\n"); 934 } 935 ctxt->validate = 0; 936 } 937 938 939 /* 940 * Split the full name into a namespace prefix and the tag name 941 */ 942 name = xmlSplitQName(ctxt, fullname, &prefix); 943 944 945 /* 946 * Note : the namespace resolution is deferred until the end of the 947 * attributes parsing, since local namespace can be defined as 948 * an attribute at this level. 949 */ 950 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL); 951 if (ret == NULL) return; 952 if (ctxt->myDoc->children == NULL) { 953#ifdef DEBUG_SAX_TREE 954 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); 955#endif 956 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 957 } else if (parent == NULL) { 958 parent = ctxt->myDoc->children; 959 } 960 ctxt->nodemem = -1; 961 962 /* 963 * We are parsing a new node. 964 */ 965#ifdef DEBUG_SAX_TREE 966 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); 967#endif 968 nodePush(ctxt, ret); 969 970 /* 971 * Link the child element 972 */ 973 if (parent != NULL) { 974 if (parent->type == XML_ELEMENT_NODE) { 975#ifdef DEBUG_SAX_TREE 976 xmlGenericError(xmlGenericErrorContext, 977 "adding child %s to %s\n", name, parent->name); 978#endif 979 xmlAddChild(parent, ret); 980 } else { 981#ifdef DEBUG_SAX_TREE 982 xmlGenericError(xmlGenericErrorContext, 983 "adding sibling %s to ", name); 984 xmlDebugDumpOneNode(stderr, parent, 0); 985#endif 986 xmlAddSibling(parent, ret); 987 } 988 } 989 990 /* 991 * process all the attributes whose name start with "xml" 992 */ 993 if (atts != NULL) { 994 i = 0; 995 att = atts[i++]; 996 value = atts[i++]; 997 if (!ctxt->html) { 998 while ((att != NULL) && (value != NULL)) { 999 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l')) 1000 attribute(ctxt, att, value); 1001 1002 att = atts[i++]; 1003 value = atts[i++]; 1004 } 1005 } 1006 } 1007 1008 /* 1009 * Search the namespace, note that since the attributes have been 1010 * processed, the local namespaces are available. 1011 */ 1012 ns = xmlSearchNs(ctxt->myDoc, ret, prefix); 1013 if ((ns == NULL) && (parent != NULL)) 1014 ns = xmlSearchNs(ctxt->myDoc, parent, prefix); 1015 if ((prefix != NULL) && (ns == NULL)) { 1016 ns = xmlNewNs(ret, NULL, prefix); 1017 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) 1018 ctxt->sax->warning(ctxt->userData, 1019 "Namespace prefix %s is not defined\n", prefix); 1020 } 1021 xmlSetNs(ret, ns); 1022 1023 /* 1024 * process all the other attributes 1025 */ 1026 if (atts != NULL) { 1027 i = 0; 1028 att = atts[i++]; 1029 value = atts[i++]; 1030 if (ctxt->html) { 1031 while (att != NULL) { 1032 attribute(ctxt, att, value); 1033 att = atts[i++]; 1034 value = atts[i++]; 1035 } 1036 } else { 1037 while ((att != NULL) && (value != NULL)) { 1038 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l')) 1039 attribute(ctxt, att, value); 1040 1041 /* 1042 * Next ones 1043 */ 1044 att = atts[i++]; 1045 value = atts[i++]; 1046 } 1047 } 1048 } 1049 1050 /* 1051 * If it's the Document root, finish the Dtd validation and 1052 * check the document root element for validity 1053 */ 1054 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) { 1055 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); 1056 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 1057 ctxt->vctxt.finishDtd = 1; 1058 } 1059 1060 if (prefix != NULL) 1061 xmlFree(prefix); 1062 if (name != NULL) 1063 xmlFree(name); 1064 1065} 1066 1067/** 1068 * endElement: 1069 * @ctx: the user data (XML parser context) 1070 * @name: The element name 1071 * 1072 * called when the end of an element has been detected. 1073 */ 1074void 1075endElement(void *ctx, const xmlChar *name) 1076{ 1077 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1078 xmlParserNodeInfo node_info; 1079 xmlNodePtr cur = ctxt->node; 1080 1081#ifdef DEBUG_SAX 1082 if (name == NULL) 1083 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n"); 1084 else 1085 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name); 1086#endif 1087 1088 /* Capture end position and add node */ 1089 if (cur != NULL && ctxt->record_info) { 1090 node_info.end_pos = ctxt->input->cur - ctxt->input->base; 1091 node_info.end_line = ctxt->input->line; 1092 node_info.node = cur; 1093 xmlParserAddNodeInfo(ctxt, &node_info); 1094 } 1095 ctxt->nodemem = -1; 1096 1097 if (ctxt->validate && ctxt->wellFormed && 1098 ctxt->myDoc && ctxt->myDoc->intSubset) 1099 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, 1100 cur); 1101 1102 1103 /* 1104 * end of parsing of this node. 1105 */ 1106#ifdef DEBUG_SAX_TREE 1107 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); 1108#endif 1109 nodePop(ctxt); 1110} 1111 1112/** 1113 * reference: 1114 * @ctx: the user data (XML parser context) 1115 * @name: The entity name 1116 * 1117 * called when an entity reference is detected. 1118 */ 1119void 1120reference(void *ctx, const xmlChar *name) 1121{ 1122 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1123 xmlNodePtr ret; 1124 1125#ifdef DEBUG_SAX 1126 xmlGenericError(xmlGenericErrorContext, 1127 "SAX.reference(%s)\n", name); 1128#endif 1129 if (name[0] == '#') 1130 ret = xmlNewCharRef(ctxt->myDoc, name); 1131 else 1132 ret = xmlNewReference(ctxt->myDoc, name); 1133#ifdef DEBUG_SAX_TREE 1134 xmlGenericError(xmlGenericErrorContext, 1135 "add reference %s to %s \n", name, ctxt->node->name); 1136#endif 1137 xmlAddChild(ctxt->node, ret); 1138} 1139 1140/** 1141 * characters: 1142 * @ctx: the user data (XML parser context) 1143 * @ch: a xmlChar string 1144 * @len: the number of xmlChar 1145 * 1146 * receiving some chars from the parser. 1147 * Question: how much at a time ??? 1148 */ 1149void 1150characters(void *ctx, const xmlChar *ch, int len) 1151{ 1152 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1153 xmlNodePtr lastChild; 1154 1155#ifdef DEBUG_SAX 1156 xmlGenericError(xmlGenericErrorContext, 1157 "SAX.characters(%.30s, %d)\n", ch, len); 1158#endif 1159 /* 1160 * Handle the data if any. If there is no child 1161 * add it as content, otherwise if the last child is text, 1162 * concatenate it, else create a new node of type text. 1163 */ 1164 1165 if (ctxt->node == NULL) { 1166#ifdef DEBUG_SAX_TREE 1167 xmlGenericError(xmlGenericErrorContext, 1168 "add chars: ctxt->node == NULL !\n"); 1169#endif 1170 return; 1171 } 1172 lastChild = xmlGetLastChild(ctxt->node); 1173#ifdef DEBUG_SAX_TREE 1174 xmlGenericError(xmlGenericErrorContext, 1175 "add chars to %s \n", ctxt->node->name); 1176#endif 1177 1178 /* 1179 * Here we needed an accelerator mechanism in case of very large 1180 * elements. Use an attribute in the structure !!! 1181 */ 1182 if (lastChild == NULL) { 1183 /* first node, first time */ 1184 xmlNodeAddContentLen(ctxt->node, ch, len); 1185#ifndef XML_USE_BUFFER_CONTENT 1186 if (ctxt->node->children != NULL) { 1187 ctxt->nodelen = len; 1188 ctxt->nodemem = len + 1; 1189 } 1190#endif 1191 } else { 1192 if ((xmlNodeIsText(lastChild)) && (ctxt->nodemem != 0)) { 1193#ifndef XML_USE_BUFFER_CONTENT 1194 /* 1195 * The whole point of maintaining nodelen and nodemem, 1196 * xmlTextConcat is too costly, i.e. compute lenght, 1197 * reallocate a new buffer, move data, append ch. Here 1198 * We try to minimaze realloc() uses and avoid copying 1199 * and recomputing lenght over and over. 1200 */ 1201 if (ctxt->nodelen + len >= ctxt->nodemem) { 1202 xmlChar *newbuf; 1203 int size; 1204 1205 size = ctxt->nodemem + len; 1206 size *= 2; 1207 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); 1208 if (newbuf == NULL) { 1209 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 1210 ctxt->sax->error(ctxt->userData, 1211 "SAX.characters(): out of memory\n"); 1212 return; 1213 } 1214 ctxt->nodemem = size; 1215 lastChild->content = newbuf; 1216 } 1217 memcpy(&lastChild->content[ctxt->nodelen], ch, len); 1218 ctxt->nodelen += len; 1219 lastChild->content[ctxt->nodelen] = 0; 1220#else 1221 xmlTextConcat(lastChild, ch, len); 1222#endif 1223 } else { 1224 /* Mixed content, first time */ 1225 lastChild = xmlNewTextLen(ch, len); 1226 xmlAddChild(ctxt->node, lastChild); 1227#ifndef XML_USE_BUFFER_CONTENT 1228 if (ctxt->node->children != NULL) { 1229 ctxt->nodelen = len; 1230 ctxt->nodemem = len + 1; 1231 } 1232#endif 1233 } 1234 } 1235} 1236 1237/** 1238 * ignorableWhitespace: 1239 * @ctx: the user data (XML parser context) 1240 * @ch: a xmlChar string 1241 * @len: the number of xmlChar 1242 * 1243 * receiving some ignorable whitespaces from the parser. 1244 * Question: how much at a time ??? 1245 */ 1246void 1247ignorableWhitespace(void *ctx, const xmlChar *ch, int len) 1248{ 1249 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 1250#ifdef DEBUG_SAX 1251 xmlGenericError(xmlGenericErrorContext, 1252 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len); 1253#endif 1254} 1255 1256/** 1257 * processingInstruction: 1258 * @ctx: the user data (XML parser context) 1259 * @target: the target name 1260 * @data: the PI data's 1261 * 1262 * A processing instruction has been parsed. 1263 */ 1264void 1265processingInstruction(void *ctx, const xmlChar *target, 1266 const xmlChar *data) 1267{ 1268 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1269 xmlNodePtr ret; 1270 xmlNodePtr parent = ctxt->node; 1271 1272#ifdef DEBUG_SAX 1273 xmlGenericError(xmlGenericErrorContext, 1274 "SAX.processingInstruction(%s, %s)\n", target, data); 1275#endif 1276 1277 ret = xmlNewPI(target, data); 1278 if (ret == NULL) return; 1279 parent = ctxt->node; 1280 1281 if (ctxt->inSubset == 1) { 1282 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 1283 return; 1284 } else if (ctxt->inSubset == 2) { 1285 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 1286 return; 1287 } 1288 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 1289#ifdef DEBUG_SAX_TREE 1290 xmlGenericError(xmlGenericErrorContext, 1291 "Setting PI %s as root\n", target); 1292#endif 1293 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 1294 return; 1295 } 1296 if (parent->type == XML_ELEMENT_NODE) { 1297#ifdef DEBUG_SAX_TREE 1298 xmlGenericError(xmlGenericErrorContext, 1299 "adding PI %s child to %s\n", target, parent->name); 1300#endif 1301 xmlAddChild(parent, ret); 1302 } else { 1303#ifdef DEBUG_SAX_TREE 1304 xmlGenericError(xmlGenericErrorContext, 1305 "adding PI %s sibling to ", target); 1306 xmlDebugDumpOneNode(stderr, parent, 0); 1307#endif 1308 xmlAddSibling(parent, ret); 1309 } 1310} 1311 1312/** 1313 * globalNamespace: 1314 * @ctx: the user data (XML parser context) 1315 * @href: the namespace associated URN 1316 * @prefix: the namespace prefix 1317 * 1318 * An old global namespace has been parsed. 1319 */ 1320void 1321globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix) 1322{ 1323 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1324#ifdef DEBUG_SAX 1325 xmlGenericError(xmlGenericErrorContext, 1326 "SAX.globalNamespace(%s, %s)\n", href, prefix); 1327#endif 1328 xmlNewGlobalNs(ctxt->myDoc, href, prefix); 1329} 1330 1331/** 1332 * setNamespace: 1333 * @ctx: the user data (XML parser context) 1334 * @name: the namespace prefix 1335 * 1336 * Set the current element namespace. 1337 */ 1338 1339void 1340setNamespace(void *ctx, const xmlChar *name) 1341{ 1342 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1343 xmlNsPtr ns; 1344 xmlNodePtr parent; 1345 1346#ifdef DEBUG_SAX 1347 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name); 1348#endif 1349 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name); 1350 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */ 1351 if (ctxt->nodeNr >= 2) { 1352 parent = ctxt->nodeTab[ctxt->nodeNr - 2]; 1353 if (parent != NULL) 1354 ns = xmlSearchNs(ctxt->myDoc, parent, name); 1355 } 1356 } 1357 xmlSetNs(ctxt->node, ns); 1358} 1359 1360/** 1361 * getNamespace: 1362 * @ctx: the user data (XML parser context) 1363 * 1364 * Get the current element namespace. 1365 * 1366 * Returns the xmlNsPtr or NULL if none 1367 */ 1368 1369xmlNsPtr 1370getNamespace(void *ctx) 1371{ 1372 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1373 xmlNsPtr ret; 1374 1375#ifdef DEBUG_SAX 1376 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n"); 1377#endif 1378 ret = ctxt->node->ns; 1379 return(ret); 1380} 1381 1382/** 1383 * checkNamespace: 1384 * @ctx: the user data (XML parser context) 1385 * @namespace: the namespace to check against 1386 * 1387 * Check that the current element namespace is the same as the 1388 * one read upon parsing. 1389 * 1390 * Returns 1 if true 0 otherwise 1391 */ 1392 1393int 1394checkNamespace(void *ctx, xmlChar *namespace) 1395{ 1396 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1397 xmlNodePtr cur = ctxt->node; 1398 1399#ifdef DEBUG_SAX 1400 xmlGenericError(xmlGenericErrorContext, 1401 "SAX.checkNamespace(%s)\n", namespace); 1402#endif 1403 1404 /* 1405 * Check that the Name in the ETag is the same as in the STag. 1406 */ 1407 if (namespace == NULL) { 1408 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { 1409 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 1410 ctxt->sax->error(ctxt, 1411 "End tags for %s don't hold the namespace %s\n", 1412 cur->name, cur->ns->prefix); 1413 ctxt->wellFormed = 0; 1414 } 1415 } else { 1416 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) { 1417 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 1418 ctxt->sax->error(ctxt, 1419 "End tags %s holds a prefix %s not used by the open tag\n", 1420 cur->name, namespace); 1421 ctxt->wellFormed = 0; 1422 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) { 1423 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) 1424 ctxt->sax->error(ctxt, 1425 "Start and End tags for %s don't use the same namespaces: %s and %s\n", 1426 cur->name, cur->ns->prefix, namespace); 1427 ctxt->wellFormed = 0; 1428 } else 1429 return(1); 1430 } 1431 return(0); 1432} 1433 1434/** 1435 * namespaceDecl: 1436 * @ctx: the user data (XML parser context) 1437 * @href: the namespace associated URN 1438 * @prefix: the namespace prefix 1439 * 1440 * A namespace has been parsed. 1441 */ 1442void 1443namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix) 1444{ 1445 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1446#ifdef DEBUG_SAX 1447 if (prefix == NULL) 1448 xmlGenericError(xmlGenericErrorContext, 1449 "SAX.namespaceDecl(%s, NULL)\n", href); 1450 else 1451 xmlGenericError(xmlGenericErrorContext, 1452 "SAX.namespaceDecl(%s, %s)\n", href, prefix); 1453#endif 1454 xmlNewNs(ctxt->node, href, prefix); 1455} 1456 1457/** 1458 * comment: 1459 * @ctx: the user data (XML parser context) 1460 * @value: the comment content 1461 * 1462 * A comment has been parsed. 1463 */ 1464void 1465comment(void *ctx, const xmlChar *value) 1466{ 1467 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1468 xmlNodePtr ret; 1469 xmlNodePtr parent = ctxt->node; 1470 1471#ifdef DEBUG_SAX 1472 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value); 1473#endif 1474 ret = xmlNewDocComment(ctxt->myDoc, value); 1475 if (ret == NULL) return; 1476 1477 if (ctxt->inSubset == 1) { 1478 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); 1479 return; 1480 } else if (ctxt->inSubset == 2) { 1481 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); 1482 return; 1483 } 1484 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { 1485#ifdef DEBUG_SAX_TREE 1486 xmlGenericError(xmlGenericErrorContext, 1487 "Setting comment as root\n"); 1488#endif 1489 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); 1490 return; 1491 } 1492 if (parent->type == XML_ELEMENT_NODE) { 1493#ifdef DEBUG_SAX_TREE 1494 xmlGenericError(xmlGenericErrorContext, 1495 "adding comment child to %s\n", parent->name); 1496#endif 1497 xmlAddChild(parent, ret); 1498 } else { 1499#ifdef DEBUG_SAX_TREE 1500 xmlGenericError(xmlGenericErrorContext, 1501 "adding comment sibling to "); 1502 xmlDebugDumpOneNode(stderr, parent, 0); 1503#endif 1504 xmlAddSibling(parent, ret); 1505 } 1506} 1507 1508/** 1509 * cdataBlock: 1510 * @ctx: the user data (XML parser context) 1511 * @value: The pcdata content 1512 * @len: the block length 1513 * 1514 * called when a pcdata block has been parsed 1515 */ 1516void 1517cdataBlock(void *ctx, const xmlChar *value, int len) 1518{ 1519 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 1520 xmlNodePtr ret, lastChild; 1521 1522#ifdef DEBUG_SAX 1523 xmlGenericError(xmlGenericErrorContext, 1524 "SAX.pcdata(%.10s, %d)\n", value, len); 1525#endif 1526 lastChild = xmlGetLastChild(ctxt->node); 1527#ifdef DEBUG_SAX_TREE 1528 xmlGenericError(xmlGenericErrorContext, 1529 "add chars to %s \n", ctxt->node->name); 1530#endif 1531 if ((lastChild != NULL) && 1532 (lastChild->type == XML_CDATA_SECTION_NODE)) { 1533 xmlTextConcat(lastChild, value, len); 1534 } else { 1535 ret = xmlNewCDataBlock(ctxt->myDoc, value, len); 1536 xmlAddChild(ctxt->node, ret); 1537 } 1538} 1539 1540/* 1541 * Default handler for XML, builds the DOM tree 1542 */ 1543xmlSAXHandler xmlDefaultSAXHandler = { 1544 internalSubset, 1545 isStandalone, 1546 hasInternalSubset, 1547 hasExternalSubset, 1548 resolveEntity, 1549 getEntity, 1550 entityDecl, 1551 notationDecl, 1552 attributeDecl, 1553 elementDecl, 1554 unparsedEntityDecl, 1555 setDocumentLocator, 1556 startDocument, 1557 endDocument, 1558 startElement, 1559 endElement, 1560 reference, 1561 characters, 1562 ignorableWhitespace, 1563 processingInstruction, 1564 comment, 1565 xmlParserWarning, 1566 xmlParserError, 1567 xmlParserError, 1568 getParameterEntity, 1569 cdataBlock, 1570 externalSubset, 1571}; 1572 1573/** 1574 * xmlDefaultSAXHandlerInit: 1575 * 1576 * Initialize the default SAX handler 1577 */ 1578void 1579xmlDefaultSAXHandlerInit(void) 1580{ 1581 xmlDefaultSAXHandler.internalSubset = internalSubset; 1582 xmlDefaultSAXHandler.externalSubset = externalSubset; 1583 xmlDefaultSAXHandler.isStandalone = isStandalone; 1584 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset; 1585 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset; 1586 xmlDefaultSAXHandler.resolveEntity = resolveEntity; 1587 xmlDefaultSAXHandler.getEntity = getEntity; 1588 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity; 1589 xmlDefaultSAXHandler.entityDecl = entityDecl; 1590 xmlDefaultSAXHandler.attributeDecl = attributeDecl; 1591 xmlDefaultSAXHandler.elementDecl = elementDecl; 1592 xmlDefaultSAXHandler.notationDecl = notationDecl; 1593 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl; 1594 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator; 1595 xmlDefaultSAXHandler.startDocument = startDocument; 1596 xmlDefaultSAXHandler.endDocument = endDocument; 1597 xmlDefaultSAXHandler.startElement = startElement; 1598 xmlDefaultSAXHandler.endElement = endElement; 1599 xmlDefaultSAXHandler.reference = reference; 1600 xmlDefaultSAXHandler.characters = characters; 1601 xmlDefaultSAXHandler.cdataBlock = cdataBlock; 1602 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace; 1603 xmlDefaultSAXHandler.processingInstruction = processingInstruction; 1604 xmlDefaultSAXHandler.comment = comment; 1605 if (xmlGetWarningsDefaultValue == 0) 1606 xmlDefaultSAXHandler.warning = NULL; 1607 else 1608 xmlDefaultSAXHandler.warning = xmlParserWarning; 1609 xmlDefaultSAXHandler.error = xmlParserError; 1610 xmlDefaultSAXHandler.fatalError = xmlParserError; 1611} 1612 1613/* 1614 * Default handler for HTML, builds the DOM tree 1615 */ 1616xmlSAXHandler htmlDefaultSAXHandler = { 1617 internalSubset, 1618 NULL, 1619 NULL, 1620 NULL, 1621 NULL, 1622 getEntity, 1623 NULL, 1624 NULL, 1625 NULL, 1626 NULL, 1627 NULL, 1628 setDocumentLocator, 1629 startDocument, 1630 endDocument, 1631 startElement, 1632 endElement, 1633 NULL, 1634 characters, 1635 ignorableWhitespace, 1636 NULL, 1637 comment, 1638 xmlParserWarning, 1639 xmlParserError, 1640 xmlParserError, 1641 getParameterEntity, 1642 cdataBlock, 1643 NULL, 1644}; 1645 1646/** 1647 * htmlDefaultSAXHandlerInit: 1648 * 1649 * Initialize the default SAX handler 1650 */ 1651void 1652htmlDefaultSAXHandlerInit(void) 1653{ 1654 htmlDefaultSAXHandler.internalSubset = internalSubset; 1655 htmlDefaultSAXHandler.externalSubset = NULL; 1656 htmlDefaultSAXHandler.isStandalone = NULL; 1657 htmlDefaultSAXHandler.hasInternalSubset = NULL; 1658 htmlDefaultSAXHandler.hasExternalSubset = NULL; 1659 htmlDefaultSAXHandler.resolveEntity = NULL; 1660 htmlDefaultSAXHandler.getEntity = getEntity; 1661 htmlDefaultSAXHandler.getParameterEntity = NULL; 1662 htmlDefaultSAXHandler.entityDecl = NULL; 1663 htmlDefaultSAXHandler.attributeDecl = NULL; 1664 htmlDefaultSAXHandler.elementDecl = NULL; 1665 htmlDefaultSAXHandler.notationDecl = NULL; 1666 htmlDefaultSAXHandler.unparsedEntityDecl = NULL; 1667 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator; 1668 htmlDefaultSAXHandler.startDocument = startDocument; 1669 htmlDefaultSAXHandler.endDocument = endDocument; 1670 htmlDefaultSAXHandler.startElement = startElement; 1671 htmlDefaultSAXHandler.endElement = endElement; 1672 htmlDefaultSAXHandler.reference = NULL; 1673 htmlDefaultSAXHandler.characters = characters; 1674 htmlDefaultSAXHandler.cdataBlock = cdataBlock; 1675 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace; 1676 htmlDefaultSAXHandler.processingInstruction = NULL; 1677 htmlDefaultSAXHandler.comment = comment; 1678 htmlDefaultSAXHandler.warning = xmlParserWarning; 1679 htmlDefaultSAXHandler.error = xmlParserError; 1680 htmlDefaultSAXHandler.fatalError = xmlParserError; 1681} 1682 1683/* 1684 * Default handler for HTML, builds the DOM tree 1685 */ 1686xmlSAXHandler sgmlDefaultSAXHandler = { 1687 internalSubset, 1688 NULL, 1689 NULL, 1690 NULL, 1691 NULL, 1692 getEntity, 1693 NULL, 1694 NULL, 1695 NULL, 1696 NULL, 1697 NULL, 1698 setDocumentLocator, 1699 startDocument, 1700 endDocument, 1701 startElement, 1702 endElement, 1703 NULL, 1704 characters, 1705 ignorableWhitespace, 1706 NULL, 1707 comment, 1708 xmlParserWarning, 1709 xmlParserError, 1710 xmlParserError, 1711 getParameterEntity, 1712 NULL, 1713 NULL, 1714}; 1715 1716/** 1717 * sgmlDefaultSAXHandlerInit: 1718 * 1719 * Initialize the default SAX handler 1720 */ 1721void 1722sgmlDefaultSAXHandlerInit(void) 1723{ 1724 sgmlDefaultSAXHandler.internalSubset = internalSubset; 1725 sgmlDefaultSAXHandler.externalSubset = NULL; 1726 sgmlDefaultSAXHandler.isStandalone = NULL; 1727 sgmlDefaultSAXHandler.hasInternalSubset = NULL; 1728 sgmlDefaultSAXHandler.hasExternalSubset = NULL; 1729 sgmlDefaultSAXHandler.resolveEntity = NULL; 1730 sgmlDefaultSAXHandler.getEntity = getEntity; 1731 sgmlDefaultSAXHandler.getParameterEntity = NULL; 1732 sgmlDefaultSAXHandler.entityDecl = NULL; 1733 sgmlDefaultSAXHandler.attributeDecl = NULL; 1734 sgmlDefaultSAXHandler.elementDecl = NULL; 1735 sgmlDefaultSAXHandler.notationDecl = NULL; 1736 sgmlDefaultSAXHandler.unparsedEntityDecl = NULL; 1737 sgmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator; 1738 sgmlDefaultSAXHandler.startDocument = startDocument; 1739 sgmlDefaultSAXHandler.endDocument = endDocument; 1740 sgmlDefaultSAXHandler.startElement = startElement; 1741 sgmlDefaultSAXHandler.endElement = endElement; 1742 sgmlDefaultSAXHandler.reference = NULL; 1743 sgmlDefaultSAXHandler.characters = characters; 1744 sgmlDefaultSAXHandler.cdataBlock = NULL; 1745 sgmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace; 1746 sgmlDefaultSAXHandler.processingInstruction = NULL; 1747 sgmlDefaultSAXHandler.comment = comment; 1748 sgmlDefaultSAXHandler.warning = xmlParserWarning; 1749 sgmlDefaultSAXHandler.error = xmlParserError; 1750 sgmlDefaultSAXHandler.fatalError = xmlParserError; 1751} 1752