1 /* 2 * xmlreader.c: implements the xmlTextReader streaming node API 3 * 4 * NOTE: 5 * XmlTextReader.Normalization Property won't be supported, since 6 * it makes the parser non compliant to the XML recommendation 7 * 8 * See Copyright for the status of this software. 9 * 10 * daniel@veillard.com 11 */ 12 13 /* 14 * TODOs: 15 * - XML Schemas validation 16 */ 17 #define IN_LIBXML 18 #include "libxml.h" 19 20 #ifdef LIBXML_READER_ENABLED 21 #include <string.h> /* for memset() only ! */ 22 #include <stdarg.h> 23 24 #ifdef HAVE_CTYPE_H 25 #include <ctype.h> 26 #endif 27 #ifdef HAVE_STDLIB_H 28 #include <stdlib.h> 29 #endif 30 31 #include <libxml/xmlmemory.h> 32 #include <libxml/xmlIO.h> 33 #include <libxml/xmlreader.h> 34 #include <libxml/parserInternals.h> 35 #ifdef LIBXML_SCHEMAS_ENABLED 36 #include <libxml/relaxng.h> 37 #include <libxml/xmlschemas.h> 38 #endif 39 #include <libxml/uri.h> 40 #ifdef LIBXML_XINCLUDE_ENABLED 41 #include <libxml/xinclude.h> 42 #endif 43 #ifdef LIBXML_PATTERN_ENABLED 44 #include <libxml/pattern.h> 45 #endif 46 47 #include "buf.h" 48 49 #define MAX_ERR_MSG_SIZE 64000 50 51 /* 52 * The following VA_COPY was coded following an example in 53 * the Samba project. It may not be sufficient for some 54 * esoteric implementations of va_list but (hopefully) will 55 * be sufficient for libxml2. 56 */ 57 #ifndef VA_COPY 58 #ifdef HAVE_VA_COPY 59 #define VA_COPY(dest, src) va_copy(dest, src) 60 #else 61 #ifdef HAVE___VA_COPY 62 #define VA_COPY(dest,src) __va_copy(dest, src) 63 #else 64 #ifndef VA_LIST_IS_ARRAY 65 #define VA_COPY(dest,src) (dest) = (src) 66 #else 67 #include <string.h> 68 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list)) 69 #endif 70 #endif 71 #endif 72 #endif 73 74 /* #define DEBUG_CALLBACKS */ 75 /* #define DEBUG_READER */ 76 77 /** 78 * TODO: 79 * 80 * macro to flag unimplemented blocks 81 */ 82 #define TODO \ 83 xmlGenericError(xmlGenericErrorContext, \ 84 "Unimplemented block at %s:%d\n", \ 85 __FILE__, __LINE__); 86 87 #ifdef DEBUG_READER 88 #define DUMP_READER xmlTextReaderDebug(reader); 89 #else 90 #define DUMP_READER 91 #endif 92 93 #define CHUNK_SIZE 512 94 /************************************************************************ 95 * * 96 * The parser: maps the Text Reader API on top of the existing * 97 * parsing routines building a tree * 98 * * 99 ************************************************************************/ 100 101 #define XML_TEXTREADER_INPUT 1 102 #define XML_TEXTREADER_CTXT 2 103 104 typedef enum { 105 XML_TEXTREADER_NONE = -1, 106 XML_TEXTREADER_START= 0, 107 XML_TEXTREADER_ELEMENT= 1, 108 XML_TEXTREADER_END= 2, 109 XML_TEXTREADER_EMPTY= 3, 110 XML_TEXTREADER_BACKTRACK= 4, 111 XML_TEXTREADER_DONE= 5, 112 XML_TEXTREADER_ERROR= 6 113 } xmlTextReaderState; 114 115 typedef enum { 116 XML_TEXTREADER_NOT_VALIDATE = 0, 117 XML_TEXTREADER_VALIDATE_DTD = 1, 118 XML_TEXTREADER_VALIDATE_RNG = 2, 119 XML_TEXTREADER_VALIDATE_XSD = 4 120 } xmlTextReaderValidate; 121 122 struct _xmlTextReader { 123 int mode; /* the parsing mode */ 124 xmlDocPtr doc; /* when walking an existing doc */ 125 xmlTextReaderValidate validate;/* is there any validation */ 126 int allocs; /* what structure were deallocated */ 127 xmlTextReaderState state; 128 xmlParserCtxtPtr ctxt; /* the parser context */ 129 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */ 130 xmlParserInputBufferPtr input; /* the input */ 131 startElementSAXFunc startElement;/* initial SAX callbacks */ 132 endElementSAXFunc endElement; /* idem */ 133 startElementNsSAX2Func startElementNs;/* idem */ 134 endElementNsSAX2Func endElementNs; /* idem */ 135 charactersSAXFunc characters; 136 cdataBlockSAXFunc cdataBlock; 137 unsigned int base; /* base of the segment in the input */ 138 unsigned int cur; /* current position in the input */ 139 xmlNodePtr node; /* current node */ 140 xmlNodePtr curnode;/* current attribute node */ 141 int depth; /* depth of the current node */ 142 xmlNodePtr faketext;/* fake xmlNs chld */ 143 int preserve;/* preserve the resulting document */ 144 xmlBufPtr buffer; /* used to return const xmlChar * */ 145 xmlDictPtr dict; /* the context dictionary */ 146 147 /* entity stack when traversing entities content */ 148 xmlNodePtr ent; /* Current Entity Ref Node */ 149 int entNr; /* Depth of the entities stack */ 150 int entMax; /* Max depth of the entities stack */ 151 xmlNodePtr *entTab; /* array of entities */ 152 153 /* error handling */ 154 xmlTextReaderErrorFunc errorFunc; /* callback function */ 155 void *errorFuncArg; /* callback function user argument */ 156 157 #ifdef LIBXML_SCHEMAS_ENABLED 158 /* Handling of RelaxNG validation */ 159 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */ 160 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */ 161 int rngPreserveCtxt; /* 1 if the context was provided by the user */ 162 int rngValidErrors;/* The number of errors detected */ 163 xmlNodePtr rngFullNode; /* the node if RNG not progressive */ 164 /* Handling of Schemas validation */ 165 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */ 166 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */ 167 int xsdPreserveCtxt; /* 1 if the context was provided by the user */ 168 int xsdValidErrors;/* The number of errors detected */ 169 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */ 170 #endif 171 #ifdef LIBXML_XINCLUDE_ENABLED 172 /* Handling of XInclude processing */ 173 int xinclude; /* is xinclude asked for */ 174 const xmlChar * xinclude_name; /* the xinclude name from dict */ 175 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */ 176 int in_xinclude; /* counts for xinclude */ 177 #endif 178 #ifdef LIBXML_PATTERN_ENABLED 179 int patternNr; /* number of preserve patterns */ 180 int patternMax; /* max preserve patterns */ 181 xmlPatternPtr *patternTab; /* array of preserve patterns */ 182 #endif 183 int preserves; /* level of preserves */ 184 int parserFlags; /* the set of options set */ 185 /* Structured error handling */ 186 xmlStructuredErrorFunc sErrorFunc; /* callback function */ 187 }; 188 189 #define NODE_IS_EMPTY 0x1 190 #define NODE_IS_PRESERVED 0x2 191 #define NODE_IS_SPRESERVED 0x4 192 193 /** 194 * CONSTSTR: 195 * 196 * Macro used to return an interned string 197 */ 198 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1) 199 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str)) 200 201 static int xmlTextReaderReadTree(xmlTextReaderPtr reader); 202 static int xmlTextReaderNextTree(xmlTextReaderPtr reader); 203 204 /************************************************************************ 205 * * 206 * Our own version of the freeing routines as we recycle nodes * 207 * * 208 ************************************************************************/ 209 /** 210 * DICT_FREE: 211 * @str: a string 212 * 213 * Free a string if it is not owned by the "dict" dictionary in the 214 * current scope 215 */ 216 #define DICT_FREE(str) \ 217 if ((str) && ((!dict) || \ 218 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ 219 xmlFree((char *)(str)); 220 221 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur); 222 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur); 223 224 /** 225 * xmlFreeID: 226 * @not: A id 227 * 228 * Deallocate the memory used by an id definition 229 */ 230 static void 231 xmlFreeID(xmlIDPtr id) { 232 xmlDictPtr dict = NULL; 233 234 if (id == NULL) return; 235 236 if (id->doc != NULL) 237 dict = id->doc->dict; 238 239 if (id->value != NULL) 240 DICT_FREE(id->value) 241 xmlFree(id); 242 } 243 244 /** 245 * xmlTextReaderRemoveID: 246 * @doc: the document 247 * @attr: the attribute 248 * 249 * Remove the given attribute from the ID table maintained internally. 250 * 251 * Returns -1 if the lookup failed and 0 otherwise 252 */ 253 static int 254 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { 255 xmlIDTablePtr table; 256 xmlIDPtr id; 257 xmlChar *ID; 258 259 if (doc == NULL) return(-1); 260 if (attr == NULL) return(-1); 261 table = (xmlIDTablePtr) doc->ids; 262 if (table == NULL) 263 return(-1); 264 265 ID = xmlNodeListGetString(doc, attr->children, 1); 266 if (ID == NULL) 267 return(-1); 268 id = xmlHashLookup(table, ID); 269 xmlFree(ID); 270 if (id == NULL || id->attr != attr) { 271 return(-1); 272 } 273 id->name = attr->name; 274 id->attr = NULL; 275 return(0); 276 } 277 278 /** 279 * xmlTextReaderFreeProp: 280 * @reader: the xmlTextReaderPtr used 281 * @cur: the node 282 * 283 * Free a node. 284 */ 285 static void 286 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { 287 xmlDictPtr dict; 288 289 if ((reader != NULL) && (reader->ctxt != NULL)) 290 dict = reader->ctxt->dict; 291 else 292 dict = NULL; 293 if (cur == NULL) return; 294 295 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) 296 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur); 297 298 /* Check for ID removal -> leading to invalid references ! */ 299 if ((cur->parent != NULL) && (cur->parent->doc != NULL) && 300 ((cur->parent->doc->intSubset != NULL) || 301 (cur->parent->doc->extSubset != NULL))) { 302 if (xmlIsID(cur->parent->doc, cur->parent, cur)) 303 xmlTextReaderRemoveID(cur->parent->doc, cur); 304 } 305 if (cur->children != NULL) 306 xmlTextReaderFreeNodeList(reader, cur->children); 307 308 DICT_FREE(cur->name); 309 if ((reader != NULL) && (reader->ctxt != NULL) && 310 (reader->ctxt->freeAttrsNr < 100)) { 311 cur->next = reader->ctxt->freeAttrs; 312 reader->ctxt->freeAttrs = cur; 313 reader->ctxt->freeAttrsNr++; 314 } else { 315 xmlFree(cur); 316 } 317 } 318 319 /** 320 * xmlTextReaderFreePropList: 321 * @reader: the xmlTextReaderPtr used 322 * @cur: the first property in the list 323 * 324 * Free a property and all its siblings, all the children are freed too. 325 */ 326 static void 327 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) { 328 xmlAttrPtr next; 329 330 while (cur != NULL) { 331 next = cur->next; 332 xmlTextReaderFreeProp(reader, cur); 333 cur = next; 334 } 335 } 336 337 /** 338 * xmlTextReaderFreeNodeList: 339 * @reader: the xmlTextReaderPtr used 340 * @cur: the first node in the list 341 * 342 * Free a node and all its siblings, this is a recursive behaviour, all 343 * the children are freed too. 344 */ 345 static void 346 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) { 347 xmlNodePtr next; 348 xmlDictPtr dict; 349 350 if ((reader != NULL) && (reader->ctxt != NULL)) 351 dict = reader->ctxt->dict; 352 else 353 dict = NULL; 354 if (cur == NULL) return; 355 if (cur->type == XML_NAMESPACE_DECL) { 356 xmlFreeNsList((xmlNsPtr) cur); 357 return; 358 } 359 if ((cur->type == XML_DOCUMENT_NODE) || 360 (cur->type == XML_HTML_DOCUMENT_NODE)) { 361 xmlFreeDoc((xmlDocPtr) cur); 362 return; 363 } 364 while (cur != NULL) { 365 next = cur->next; 366 /* unroll to speed up freeing the document */ 367 if (cur->type != XML_DTD_NODE) { 368 369 if ((cur->children != NULL) && 370 (cur->type != XML_ENTITY_REF_NODE)) { 371 if (cur->children->parent == cur) 372 xmlTextReaderFreeNodeList(reader, cur->children); 373 cur->children = NULL; 374 } 375 376 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) 377 xmlDeregisterNodeDefaultValue(cur); 378 379 if (((cur->type == XML_ELEMENT_NODE) || 380 (cur->type == XML_XINCLUDE_START) || 381 (cur->type == XML_XINCLUDE_END)) && 382 (cur->properties != NULL)) 383 xmlTextReaderFreePropList(reader, cur->properties); 384 if ((cur->content != (xmlChar *) &(cur->properties)) && 385 (cur->type != XML_ELEMENT_NODE) && 386 (cur->type != XML_XINCLUDE_START) && 387 (cur->type != XML_XINCLUDE_END) && 388 (cur->type != XML_ENTITY_REF_NODE)) { 389 DICT_FREE(cur->content); 390 } 391 if (((cur->type == XML_ELEMENT_NODE) || 392 (cur->type == XML_XINCLUDE_START) || 393 (cur->type == XML_XINCLUDE_END)) && 394 (cur->nsDef != NULL)) 395 xmlFreeNsList(cur->nsDef); 396 397 /* 398 * we don't free element names here they are interned now 399 */ 400 if ((cur->type != XML_TEXT_NODE) && 401 (cur->type != XML_COMMENT_NODE)) 402 DICT_FREE(cur->name); 403 if (((cur->type == XML_ELEMENT_NODE) || 404 (cur->type == XML_TEXT_NODE)) && 405 (reader != NULL) && (reader->ctxt != NULL) && 406 (reader->ctxt->freeElemsNr < 100)) { 407 cur->next = reader->ctxt->freeElems; 408 reader->ctxt->freeElems = cur; 409 reader->ctxt->freeElemsNr++; 410 } else { 411 xmlFree(cur); 412 } 413 } 414 cur = next; 415 } 416 } 417 418 /** 419 * xmlTextReaderFreeNode: 420 * @reader: the xmlTextReaderPtr used 421 * @cur: the node 422 * 423 * Free a node, this is a recursive behaviour, all the children are freed too. 424 * This doesn't unlink the child from the list, use xmlUnlinkNode() first. 425 */ 426 static void 427 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) { 428 xmlDictPtr dict; 429 430 if ((reader != NULL) && (reader->ctxt != NULL)) 431 dict = reader->ctxt->dict; 432 else 433 dict = NULL; 434 if (cur->type == XML_DTD_NODE) { 435 xmlFreeDtd((xmlDtdPtr) cur); 436 return; 437 } 438 if (cur->type == XML_NAMESPACE_DECL) { 439 xmlFreeNs((xmlNsPtr) cur); 440 return; 441 } 442 if (cur->type == XML_ATTRIBUTE_NODE) { 443 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur); 444 return; 445 } 446 447 if ((cur->children != NULL) && 448 (cur->type != XML_ENTITY_REF_NODE)) { 449 if (cur->children->parent == cur) 450 xmlTextReaderFreeNodeList(reader, cur->children); 451 cur->children = NULL; 452 } 453 454 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) 455 xmlDeregisterNodeDefaultValue(cur); 456 457 if (((cur->type == XML_ELEMENT_NODE) || 458 (cur->type == XML_XINCLUDE_START) || 459 (cur->type == XML_XINCLUDE_END)) && 460 (cur->properties != NULL)) 461 xmlTextReaderFreePropList(reader, cur->properties); 462 if ((cur->content != (xmlChar *) &(cur->properties)) && 463 (cur->type != XML_ELEMENT_NODE) && 464 (cur->type != XML_XINCLUDE_START) && 465 (cur->type != XML_XINCLUDE_END) && 466 (cur->type != XML_ENTITY_REF_NODE)) { 467 DICT_FREE(cur->content); 468 } 469 if (((cur->type == XML_ELEMENT_NODE) || 470 (cur->type == XML_XINCLUDE_START) || 471 (cur->type == XML_XINCLUDE_END)) && 472 (cur->nsDef != NULL)) 473 xmlFreeNsList(cur->nsDef); 474 475 /* 476 * we don't free names here they are interned now 477 */ 478 if ((cur->type != XML_TEXT_NODE) && 479 (cur->type != XML_COMMENT_NODE)) 480 DICT_FREE(cur->name); 481 482 if (((cur->type == XML_ELEMENT_NODE) || 483 (cur->type == XML_TEXT_NODE)) && 484 (reader != NULL) && (reader->ctxt != NULL) && 485 (reader->ctxt->freeElemsNr < 100)) { 486 cur->next = reader->ctxt->freeElems; 487 reader->ctxt->freeElems = cur; 488 reader->ctxt->freeElemsNr++; 489 } else { 490 xmlFree(cur); 491 } 492 } 493 494 /** 495 * xmlTextReaderFreeIDTable: 496 * @table: An id table 497 * 498 * Deallocate the memory used by an ID hash table. 499 */ 500 static void 501 xmlTextReaderFreeIDTable(xmlIDTablePtr table) { 502 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID); 503 } 504 505 /** 506 * xmlTextReaderFreeDoc: 507 * @reader: the xmlTextReaderPtr used 508 * @cur: pointer to the document 509 * 510 * Free up all the structures used by a document, tree included. 511 */ 512 static void 513 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) { 514 xmlDtdPtr extSubset, intSubset; 515 516 if (cur == NULL) return; 517 518 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) 519 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur); 520 521 /* 522 * Do this before freeing the children list to avoid ID lookups 523 */ 524 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids); 525 cur->ids = NULL; 526 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs); 527 cur->refs = NULL; 528 extSubset = cur->extSubset; 529 intSubset = cur->intSubset; 530 if (intSubset == extSubset) 531 extSubset = NULL; 532 if (extSubset != NULL) { 533 xmlUnlinkNode((xmlNodePtr) cur->extSubset); 534 cur->extSubset = NULL; 535 xmlFreeDtd(extSubset); 536 } 537 if (intSubset != NULL) { 538 xmlUnlinkNode((xmlNodePtr) cur->intSubset); 539 cur->intSubset = NULL; 540 xmlFreeDtd(intSubset); 541 } 542 543 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children); 544 545 if (cur->version != NULL) xmlFree((char *) cur->version); 546 if (cur->name != NULL) xmlFree((char *) cur->name); 547 if (cur->encoding != NULL) xmlFree((char *) cur->encoding); 548 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); 549 if (cur->URL != NULL) xmlFree((char *) cur->URL); 550 if (cur->dict != NULL) xmlDictFree(cur->dict); 551 552 xmlFree(cur); 553 } 554 555 /************************************************************************ 556 * * 557 * The reader core parser * 558 * * 559 ************************************************************************/ 560 #ifdef DEBUG_READER 561 static void 562 xmlTextReaderDebug(xmlTextReaderPtr reader) { 563 if ((reader == NULL) || (reader->ctxt == NULL)) { 564 fprintf(stderr, "xmlTextReader NULL\n"); 565 return; 566 } 567 fprintf(stderr, "xmlTextReader: state %d depth %d ", 568 reader->state, reader->depth); 569 if (reader->node == NULL) { 570 fprintf(stderr, "node = NULL\n"); 571 } else { 572 fprintf(stderr, "node %s\n", reader->node->name); 573 } 574 fprintf(stderr, " input: base %d, cur %d, depth %d: ", 575 reader->base, reader->cur, reader->ctxt->nodeNr); 576 if (reader->input->buffer == NULL) { 577 fprintf(stderr, "buffer is NULL\n"); 578 } else { 579 #ifdef LIBXML_DEBUG_ENABLED 580 xmlDebugDumpString(stderr, 581 &reader->input->buffer->content[reader->cur]); 582 #endif 583 fprintf(stderr, "\n"); 584 } 585 } 586 #endif 587 588 /** 589 * xmlTextReaderEntPush: 590 * @reader: the xmlTextReaderPtr used 591 * @value: the entity reference node 592 * 593 * Pushes a new entity reference node on top of the entities stack 594 * 595 * Returns 0 in case of error, the index in the stack otherwise 596 */ 597 static int 598 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value) 599 { 600 if (reader->entMax <= 0) { 601 reader->entMax = 10; 602 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax * 603 sizeof(reader->entTab[0])); 604 if (reader->entTab == NULL) { 605 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 606 return (0); 607 } 608 } 609 if (reader->entNr >= reader->entMax) { 610 reader->entMax *= 2; 611 reader->entTab = 612 (xmlNodePtr *) xmlRealloc(reader->entTab, 613 reader->entMax * 614 sizeof(reader->entTab[0])); 615 if (reader->entTab == NULL) { 616 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 617 return (0); 618 } 619 } 620 reader->entTab[reader->entNr] = value; 621 reader->ent = value; 622 return (reader->entNr++); 623 } 624 625 /** 626 * xmlTextReaderEntPop: 627 * @reader: the xmlTextReaderPtr used 628 * 629 * Pops the top element entity from the entities stack 630 * 631 * Returns the entity just removed 632 */ 633 static xmlNodePtr 634 xmlTextReaderEntPop(xmlTextReaderPtr reader) 635 { 636 xmlNodePtr ret; 637 638 if (reader->entNr <= 0) 639 return (NULL); 640 reader->entNr--; 641 if (reader->entNr > 0) 642 reader->ent = reader->entTab[reader->entNr - 1]; 643 else 644 reader->ent = NULL; 645 ret = reader->entTab[reader->entNr]; 646 reader->entTab[reader->entNr] = NULL; 647 return (ret); 648 } 649 650 /** 651 * xmlTextReaderStartElement: 652 * @ctx: the user data (XML parser context) 653 * @fullname: The element name, including namespace prefix 654 * @atts: An array of name/value attributes pairs, NULL terminated 655 * 656 * called when an opening tag has been processed. 657 */ 658 static void 659 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname, 660 const xmlChar **atts) { 661 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 662 xmlTextReaderPtr reader = ctxt->_private; 663 664 #ifdef DEBUG_CALLBACKS 665 printf("xmlTextReaderStartElement(%s)\n", fullname); 666 #endif 667 if ((reader != NULL) && (reader->startElement != NULL)) { 668 reader->startElement(ctx, fullname, atts); 669 if ((ctxt->node != NULL) && (ctxt->input != NULL) && 670 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && 671 (ctxt->input->cur[1] == '>')) 672 ctxt->node->extra = NODE_IS_EMPTY; 673 } 674 if (reader != NULL) 675 reader->state = XML_TEXTREADER_ELEMENT; 676 } 677 678 /** 679 * xmlTextReaderEndElement: 680 * @ctx: the user data (XML parser context) 681 * @fullname: The element name, including namespace prefix 682 * 683 * called when an ending tag has been processed. 684 */ 685 static void 686 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { 687 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 688 xmlTextReaderPtr reader = ctxt->_private; 689 690 #ifdef DEBUG_CALLBACKS 691 printf("xmlTextReaderEndElement(%s)\n", fullname); 692 #endif 693 if ((reader != NULL) && (reader->endElement != NULL)) { 694 reader->endElement(ctx, fullname); 695 } 696 } 697 698 /** 699 * xmlTextReaderStartElementNs: 700 * @ctx: the user data (XML parser context) 701 * @localname: the local name of the element 702 * @prefix: the element namespace prefix if available 703 * @URI: the element namespace name if available 704 * @nb_namespaces: number of namespace definitions on that node 705 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions 706 * @nb_attributes: the number of attributes on that node 707 * nb_defaulted: the number of defaulted attributes. 708 * @attributes: pointer to the array of (localname/prefix/URI/value/end) 709 * attribute values. 710 * 711 * called when an opening tag has been processed. 712 */ 713 static void 714 xmlTextReaderStartElementNs(void *ctx, 715 const xmlChar *localname, 716 const xmlChar *prefix, 717 const xmlChar *URI, 718 int nb_namespaces, 719 const xmlChar **namespaces, 720 int nb_attributes, 721 int nb_defaulted, 722 const xmlChar **attributes) 723 { 724 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 725 xmlTextReaderPtr reader = ctxt->_private; 726 727 #ifdef DEBUG_CALLBACKS 728 printf("xmlTextReaderStartElementNs(%s)\n", localname); 729 #endif 730 if ((reader != NULL) && (reader->startElementNs != NULL)) { 731 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces, 732 namespaces, nb_attributes, nb_defaulted, 733 attributes); 734 if ((ctxt->node != NULL) && (ctxt->input != NULL) && 735 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && 736 (ctxt->input->cur[1] == '>')) 737 ctxt->node->extra = NODE_IS_EMPTY; 738 } 739 if (reader != NULL) 740 reader->state = XML_TEXTREADER_ELEMENT; 741 } 742 743 /** 744 * xmlTextReaderEndElementNs: 745 * @ctx: the user data (XML parser context) 746 * @localname: the local name of the element 747 * @prefix: the element namespace prefix if available 748 * @URI: the element namespace name if available 749 * 750 * called when an ending tag has been processed. 751 */ 752 static void 753 xmlTextReaderEndElementNs(void *ctx, 754 const xmlChar * localname, 755 const xmlChar * prefix, 756 const xmlChar * URI) 757 { 758 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 759 xmlTextReaderPtr reader = ctxt->_private; 760 761 #ifdef DEBUG_CALLBACKS 762 printf("xmlTextReaderEndElementNs(%s)\n", localname); 763 #endif 764 if ((reader != NULL) && (reader->endElementNs != NULL)) { 765 reader->endElementNs(ctx, localname, prefix, URI); 766 } 767 } 768 769 770 /** 771 * xmlTextReaderCharacters: 772 * @ctx: the user data (XML parser context) 773 * @ch: a xmlChar string 774 * @len: the number of xmlChar 775 * 776 * receiving some chars from the parser. 777 */ 778 static void 779 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len) 780 { 781 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 782 xmlTextReaderPtr reader = ctxt->_private; 783 784 #ifdef DEBUG_CALLBACKS 785 printf("xmlTextReaderCharacters()\n"); 786 #endif 787 if ((reader != NULL) && (reader->characters != NULL)) { 788 reader->characters(ctx, ch, len); 789 } 790 } 791 792 /** 793 * xmlTextReaderCDataBlock: 794 * @ctx: the user data (XML parser context) 795 * @value: The pcdata content 796 * @len: the block length 797 * 798 * called when a pcdata block has been parsed 799 */ 800 static void 801 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len) 802 { 803 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 804 xmlTextReaderPtr reader = ctxt->_private; 805 806 #ifdef DEBUG_CALLBACKS 807 printf("xmlTextReaderCDataBlock()\n"); 808 #endif 809 if ((reader != NULL) && (reader->cdataBlock != NULL)) { 810 reader->cdataBlock(ctx, ch, len); 811 } 812 } 813 814 /** 815 * xmlTextReaderPushData: 816 * @reader: the xmlTextReaderPtr used 817 * 818 * Push data down the progressive parser until a significant callback 819 * got raised. 820 * 821 * Returns -1 in case of failure, 0 otherwise 822 */ 823 static int 824 xmlTextReaderPushData(xmlTextReaderPtr reader) { 825 xmlBufPtr inbuf; 826 int val, s; 827 xmlTextReaderState oldstate; 828 int alloc; 829 830 if ((reader->input == NULL) || (reader->input->buffer == NULL)) 831 return(-1); 832 833 oldstate = reader->state; 834 reader->state = XML_TEXTREADER_NONE; 835 inbuf = reader->input->buffer; 836 alloc = xmlBufGetAllocationScheme(inbuf); 837 838 while (reader->state == XML_TEXTREADER_NONE) { 839 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) { 840 /* 841 * Refill the buffer unless we are at the end of the stream 842 */ 843 if (reader->mode != XML_TEXTREADER_MODE_EOF) { 844 val = xmlParserInputBufferRead(reader->input, 4096); 845 if ((val == 0) && 846 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) { 847 if (xmlBufUse(inbuf) == reader->cur) { 848 reader->mode = XML_TEXTREADER_MODE_EOF; 849 reader->state = oldstate; 850 } 851 } else if (val < 0) { 852 reader->mode = XML_TEXTREADER_MODE_EOF; 853 reader->state = oldstate; 854 if ((oldstate != XML_TEXTREADER_START) || 855 (reader->ctxt->myDoc != NULL)) 856 return(val); 857 } else if (val == 0) { 858 /* mark the end of the stream and process the remains */ 859 reader->mode = XML_TEXTREADER_MODE_EOF; 860 break; 861 } 862 863 } else 864 break; 865 } 866 /* 867 * parse by block of CHUNK_SIZE bytes, various tests show that 868 * it's the best tradeoff at least on a 1.2GH Duron 869 */ 870 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) { 871 val = xmlParseChunk(reader->ctxt, 872 (const char *) xmlBufContent(inbuf) + reader->cur, 873 CHUNK_SIZE, 0); 874 reader->cur += CHUNK_SIZE; 875 if (val != 0) 876 reader->ctxt->wellFormed = 0; 877 if (reader->ctxt->wellFormed == 0) 878 break; 879 } else { 880 s = xmlBufUse(inbuf) - reader->cur; 881 val = xmlParseChunk(reader->ctxt, 882 (const char *) xmlBufContent(inbuf) + reader->cur, 883 s, 0); 884 reader->cur += s; 885 if (val != 0) 886 reader->ctxt->wellFormed = 0; 887 break; 888 } 889 } 890 891 /* 892 * Discard the consumed input when needed and possible 893 */ 894 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) { 895 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) { 896 if ((reader->cur >= 4096) && 897 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) { 898 val = xmlBufShrink(inbuf, reader->cur); 899 if (val >= 0) { 900 reader->cur -= val; 901 } 902 } 903 } 904 } 905 906 /* 907 * At the end of the stream signal that the work is done to the Push 908 * parser. 909 */ 910 else if (reader->mode == XML_TEXTREADER_MODE_EOF) { 911 if (reader->state != XML_TEXTREADER_DONE) { 912 s = xmlBufUse(inbuf) - reader->cur; 913 val = xmlParseChunk(reader->ctxt, 914 (const char *) xmlBufContent(inbuf) + reader->cur, 915 s, 1); 916 reader->cur = xmlBufUse(inbuf); 917 reader->state = XML_TEXTREADER_DONE; 918 if (val != 0) { 919 if (reader->ctxt->wellFormed) 920 reader->ctxt->wellFormed = 0; 921 else 922 return(-1); 923 } 924 } 925 } 926 reader->state = oldstate; 927 if (reader->ctxt->wellFormed == 0) { 928 reader->mode = XML_TEXTREADER_MODE_EOF; 929 return(-1); 930 } 931 932 return(0); 933 } 934 935 #ifdef LIBXML_REGEXP_ENABLED 936 /** 937 * xmlTextReaderValidatePush: 938 * @reader: the xmlTextReaderPtr used 939 * 940 * Push the current node for validation 941 */ 942 static void 943 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { 944 xmlNodePtr node = reader->node; 945 946 #ifdef LIBXML_VALID_ENABLED 947 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && 948 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { 949 if ((node->ns == NULL) || (node->ns->prefix == NULL)) { 950 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, 951 reader->ctxt->myDoc, node, node->name); 952 } else { 953 /* TODO use the BuildQName interface */ 954 xmlChar *qname; 955 956 qname = xmlStrdup(node->ns->prefix); 957 qname = xmlStrcat(qname, BAD_CAST ":"); 958 qname = xmlStrcat(qname, node->name); 959 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, 960 reader->ctxt->myDoc, node, qname); 961 if (qname != NULL) 962 xmlFree(qname); 963 } 964 } 965 #endif /* LIBXML_VALID_ENABLED */ 966 #ifdef LIBXML_SCHEMAS_ENABLED 967 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && 968 (reader->rngValidCtxt != NULL)) { 969 int ret; 970 971 if (reader->rngFullNode != NULL) return; 972 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt, 973 reader->ctxt->myDoc, 974 node); 975 if (ret == 0) { 976 /* 977 * this element requires a full tree 978 */ 979 node = xmlTextReaderExpand(reader); 980 if (node == NULL) { 981 printf("Expand failed !\n"); 982 ret = -1; 983 } else { 984 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt, 985 reader->ctxt->myDoc, 986 node); 987 reader->rngFullNode = node; 988 } 989 } 990 if (ret != 1) 991 reader->rngValidErrors++; 992 } 993 #endif 994 } 995 996 /** 997 * xmlTextReaderValidateCData: 998 * @reader: the xmlTextReaderPtr used 999 * @data: pointer to the CData 1000 * @len: length of the CData block in bytes. 1001 * 1002 * Push some CData for validation 1003 */ 1004 static void 1005 xmlTextReaderValidateCData(xmlTextReaderPtr reader, 1006 const xmlChar *data, int len) { 1007 #ifdef LIBXML_VALID_ENABLED 1008 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && 1009 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { 1010 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt, 1011 data, len); 1012 } 1013 #endif /* LIBXML_VALID_ENABLED */ 1014 #ifdef LIBXML_SCHEMAS_ENABLED 1015 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && 1016 (reader->rngValidCtxt != NULL)) { 1017 int ret; 1018 1019 if (reader->rngFullNode != NULL) return; 1020 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len); 1021 if (ret != 1) 1022 reader->rngValidErrors++; 1023 } 1024 #endif 1025 } 1026 1027 /** 1028 * xmlTextReaderValidatePop: 1029 * @reader: the xmlTextReaderPtr used 1030 * 1031 * Pop the current node from validation 1032 */ 1033 static void 1034 xmlTextReaderValidatePop(xmlTextReaderPtr reader) { 1035 xmlNodePtr node = reader->node; 1036 1037 #ifdef LIBXML_VALID_ENABLED 1038 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && 1039 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { 1040 if ((node->ns == NULL) || (node->ns->prefix == NULL)) { 1041 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, 1042 reader->ctxt->myDoc, node, node->name); 1043 } else { 1044 /* TODO use the BuildQName interface */ 1045 xmlChar *qname; 1046 1047 qname = xmlStrdup(node->ns->prefix); 1048 qname = xmlStrcat(qname, BAD_CAST ":"); 1049 qname = xmlStrcat(qname, node->name); 1050 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, 1051 reader->ctxt->myDoc, node, qname); 1052 if (qname != NULL) 1053 xmlFree(qname); 1054 } 1055 } 1056 #endif /* LIBXML_VALID_ENABLED */ 1057 #ifdef LIBXML_SCHEMAS_ENABLED 1058 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && 1059 (reader->rngValidCtxt != NULL)) { 1060 int ret; 1061 1062 if (reader->rngFullNode != NULL) { 1063 if (node == reader->rngFullNode) 1064 reader->rngFullNode = NULL; 1065 return; 1066 } 1067 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt, 1068 reader->ctxt->myDoc, 1069 node); 1070 if (ret != 1) 1071 reader->rngValidErrors++; 1072 } 1073 #endif 1074 } 1075 1076 /** 1077 * xmlTextReaderValidateEntity: 1078 * @reader: the xmlTextReaderPtr used 1079 * 1080 * Handle the validation when an entity reference is encountered and 1081 * entity substitution is not activated. As a result the parser interface 1082 * must walk through the entity and do the validation calls 1083 */ 1084 static void 1085 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { 1086 xmlNodePtr oldnode = reader->node; 1087 xmlNodePtr node = reader->node; 1088 xmlParserCtxtPtr ctxt = reader->ctxt; 1089 1090 do { 1091 if (node->type == XML_ENTITY_REF_NODE) { 1092 /* 1093 * Case where the underlying tree is not availble, lookup the entity 1094 * and walk it. 1095 */ 1096 if ((node->children == NULL) && (ctxt->sax != NULL) && 1097 (ctxt->sax->getEntity != NULL)) { 1098 node->children = (xmlNodePtr) 1099 ctxt->sax->getEntity(ctxt, node->name); 1100 } 1101 1102 if ((node->children != NULL) && 1103 (node->children->type == XML_ENTITY_DECL) && 1104 (node->children->children != NULL)) { 1105 xmlTextReaderEntPush(reader, node); 1106 node = node->children->children; 1107 continue; 1108 } else { 1109 /* 1110 * The error has probably be raised already. 1111 */ 1112 if (node == oldnode) 1113 break; 1114 node = node->next; 1115 } 1116 #ifdef LIBXML_REGEXP_ENABLED 1117 } else if (node->type == XML_ELEMENT_NODE) { 1118 reader->node = node; 1119 xmlTextReaderValidatePush(reader); 1120 } else if ((node->type == XML_TEXT_NODE) || 1121 (node->type == XML_CDATA_SECTION_NODE)) { 1122 xmlTextReaderValidateCData(reader, node->content, 1123 xmlStrlen(node->content)); 1124 #endif 1125 } 1126 1127 /* 1128 * go to next node 1129 */ 1130 if (node->children != NULL) { 1131 node = node->children; 1132 continue; 1133 } else if (node->type == XML_ELEMENT_NODE) { 1134 xmlTextReaderValidatePop(reader); 1135 } 1136 if (node->next != NULL) { 1137 node = node->next; 1138 continue; 1139 } 1140 do { 1141 node = node->parent; 1142 if (node->type == XML_ELEMENT_NODE) { 1143 xmlNodePtr tmp; 1144 if (reader->entNr == 0) { 1145 while ((tmp = node->last) != NULL) { 1146 if ((tmp->extra & NODE_IS_PRESERVED) == 0) { 1147 xmlUnlinkNode(tmp); 1148 xmlTextReaderFreeNode(reader, tmp); 1149 } else 1150 break; 1151 } 1152 } 1153 reader->node = node; 1154 xmlTextReaderValidatePop(reader); 1155 } 1156 if ((node->type == XML_ENTITY_DECL) && 1157 (reader->ent != NULL) && (reader->ent->children == node)) { 1158 node = xmlTextReaderEntPop(reader); 1159 } 1160 if (node == oldnode) 1161 break; 1162 if (node->next != NULL) { 1163 node = node->next; 1164 break; 1165 } 1166 } while ((node != NULL) && (node != oldnode)); 1167 } while ((node != NULL) && (node != oldnode)); 1168 reader->node = oldnode; 1169 } 1170 #endif /* LIBXML_REGEXP_ENABLED */ 1171 1172 1173 /** 1174 * xmlTextReaderGetSuccessor: 1175 * @cur: the current node 1176 * 1177 * Get the successor of a node if available. 1178 * 1179 * Returns the successor node or NULL 1180 */ 1181 static xmlNodePtr 1182 xmlTextReaderGetSuccessor(xmlNodePtr cur) { 1183 if (cur == NULL) return(NULL) ; /* ERROR */ 1184 if (cur->next != NULL) return(cur->next) ; 1185 do { 1186 cur = cur->parent; 1187 if (cur == NULL) break; 1188 if (cur->next != NULL) return(cur->next); 1189 } while (cur != NULL); 1190 return(cur); 1191 } 1192 1193 /** 1194 * xmlTextReaderDoExpand: 1195 * @reader: the xmlTextReaderPtr used 1196 * 1197 * Makes sure that the current node is fully read as well as all its 1198 * descendant. It means the full DOM subtree must be available at the 1199 * end of the call. 1200 * 1201 * Returns 1 if the node was expanded successfully, 0 if there is no more 1202 * nodes to read, or -1 in case of error 1203 */ 1204 static int 1205 xmlTextReaderDoExpand(xmlTextReaderPtr reader) { 1206 int val; 1207 1208 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL)) 1209 return(-1); 1210 do { 1211 if (reader->ctxt->instate == XML_PARSER_EOF) return(1); 1212 1213 if (xmlTextReaderGetSuccessor(reader->node) != NULL) 1214 return(1); 1215 if (reader->ctxt->nodeNr < reader->depth) 1216 return(1); 1217 if (reader->mode == XML_TEXTREADER_MODE_EOF) 1218 return(1); 1219 val = xmlTextReaderPushData(reader); 1220 if (val < 0){ 1221 reader->mode = XML_TEXTREADER_MODE_ERROR; 1222 return(-1); 1223 } 1224 } while(reader->mode != XML_TEXTREADER_MODE_EOF); 1225 return(1); 1226 } 1227 1228 /** 1229 * xmlTextReaderCollectSiblings: 1230 * @node: the first child 1231 * 1232 * Traverse depth-first through all sibling nodes and their children 1233 * nodes and concatenate their content. This is an auxiliary function 1234 * to xmlTextReaderReadString. 1235 * 1236 * Returns a string containing the content, or NULL in case of error. 1237 */ 1238 static xmlChar * 1239 xmlTextReaderCollectSiblings(xmlNodePtr node) 1240 { 1241 xmlBufferPtr buffer; 1242 xmlChar *ret; 1243 1244 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) 1245 return(NULL); 1246 1247 buffer = xmlBufferCreate(); 1248 if (buffer == NULL) 1249 return NULL; 1250 1251 for ( ; node != NULL; node = node->next) { 1252 switch (node->type) { 1253 case XML_TEXT_NODE: 1254 case XML_CDATA_SECTION_NODE: 1255 xmlBufferCat(buffer, node->content); 1256 break; 1257 case XML_ELEMENT_NODE: { 1258 xmlChar *tmp; 1259 1260 tmp = xmlTextReaderCollectSiblings(node->children); 1261 xmlBufferCat(buffer, tmp); 1262 xmlFree(tmp); 1263 break; 1264 } 1265 default: 1266 break; 1267 } 1268 } 1269 ret = buffer->content; 1270 buffer->content = NULL; 1271 xmlBufferFree(buffer); 1272 return(ret); 1273 } 1274 1275 /** 1276 * xmlTextReaderRead: 1277 * @reader: the xmlTextReaderPtr used 1278 * 1279 * Moves the position of the current instance to the next node in 1280 * the stream, exposing its properties. 1281 * 1282 * Returns 1 if the node was read successfully, 0 if there is no more 1283 * nodes to read, or -1 in case of error 1284 */ 1285 int 1286 xmlTextReaderRead(xmlTextReaderPtr reader) { 1287 int val, olddepth = 0; 1288 xmlTextReaderState oldstate = XML_TEXTREADER_START; 1289 xmlNodePtr oldnode = NULL; 1290 1291 1292 if (reader == NULL) 1293 return(-1); 1294 reader->curnode = NULL; 1295 if (reader->doc != NULL) 1296 return(xmlTextReaderReadTree(reader)); 1297 if (reader->ctxt == NULL) 1298 return(-1); 1299 1300 #ifdef DEBUG_READER 1301 fprintf(stderr, "\nREAD "); 1302 DUMP_READER 1303 #endif 1304 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) { 1305 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE; 1306 /* 1307 * Initial state 1308 */ 1309 do { 1310 val = xmlTextReaderPushData(reader); 1311 if (val < 0){ 1312 reader->mode = XML_TEXTREADER_MODE_ERROR; 1313 reader->state = XML_TEXTREADER_ERROR; 1314 return(-1); 1315 } 1316 } while ((reader->ctxt->node == NULL) && 1317 ((reader->mode != XML_TEXTREADER_MODE_EOF) && 1318 (reader->state != XML_TEXTREADER_DONE))); 1319 if (reader->ctxt->node == NULL) { 1320 if (reader->ctxt->myDoc != NULL) { 1321 reader->node = reader->ctxt->myDoc->children; 1322 } 1323 if (reader->node == NULL){ 1324 reader->mode = XML_TEXTREADER_MODE_ERROR; 1325 reader->state = XML_TEXTREADER_ERROR; 1326 return(-1); 1327 } 1328 reader->state = XML_TEXTREADER_ELEMENT; 1329 } else { 1330 if (reader->ctxt->myDoc != NULL) { 1331 reader->node = reader->ctxt->myDoc->children; 1332 } 1333 if (reader->node == NULL) 1334 reader->node = reader->ctxt->nodeTab[0]; 1335 reader->state = XML_TEXTREADER_ELEMENT; 1336 } 1337 reader->depth = 0; 1338 reader->ctxt->parseMode = XML_PARSE_READER; 1339 goto node_found; 1340 } 1341 oldstate = reader->state; 1342 olddepth = reader->ctxt->nodeNr; 1343 oldnode = reader->node; 1344 1345 get_next_node: 1346 if (reader->node == NULL) { 1347 if (reader->mode == XML_TEXTREADER_MODE_EOF) 1348 return(0); 1349 else 1350 return(-1); 1351 } 1352 1353 /* 1354 * If we are not backtracking on ancestors or examined nodes, 1355 * that the parser didn't finished or that we arent at the end 1356 * of stream, continue processing. 1357 */ 1358 while ((reader->node != NULL) && (reader->node->next == NULL) && 1359 (reader->ctxt->nodeNr == olddepth) && 1360 ((oldstate == XML_TEXTREADER_BACKTRACK) || 1361 (reader->node->children == NULL) || 1362 (reader->node->type == XML_ENTITY_REF_NODE) || 1363 ((reader->node->children != NULL) && 1364 (reader->node->children->type == XML_TEXT_NODE) && 1365 (reader->node->children->next == NULL)) || 1366 (reader->node->type == XML_DTD_NODE) || 1367 (reader->node->type == XML_DOCUMENT_NODE) || 1368 (reader->node->type == XML_HTML_DOCUMENT_NODE)) && 1369 ((reader->ctxt->node == NULL) || 1370 (reader->ctxt->node == reader->node) || 1371 (reader->ctxt->node == reader->node->parent)) && 1372 (reader->ctxt->instate != XML_PARSER_EOF)) { 1373 val = xmlTextReaderPushData(reader); 1374 if (val < 0){ 1375 reader->mode = XML_TEXTREADER_MODE_ERROR; 1376 reader->state = XML_TEXTREADER_ERROR; 1377 return(-1); 1378 } 1379 if (reader->node == NULL) 1380 goto node_end; 1381 } 1382 if (oldstate != XML_TEXTREADER_BACKTRACK) { 1383 if ((reader->node->children != NULL) && 1384 (reader->node->type != XML_ENTITY_REF_NODE) && 1385 (reader->node->type != XML_XINCLUDE_START) && 1386 (reader->node->type != XML_DTD_NODE)) { 1387 reader->node = reader->node->children; 1388 reader->depth++; 1389 reader->state = XML_TEXTREADER_ELEMENT; 1390 goto node_found; 1391 } 1392 } 1393 if (reader->node->next != NULL) { 1394 if ((oldstate == XML_TEXTREADER_ELEMENT) && 1395 (reader->node->type == XML_ELEMENT_NODE) && 1396 (reader->node->children == NULL) && 1397 ((reader->node->extra & NODE_IS_EMPTY) == 0) 1398 #ifdef LIBXML_XINCLUDE_ENABLED 1399 && (reader->in_xinclude <= 0) 1400 #endif 1401 ) { 1402 reader->state = XML_TEXTREADER_END; 1403 goto node_found; 1404 } 1405 #ifdef LIBXML_REGEXP_ENABLED 1406 if ((reader->validate) && 1407 (reader->node->type == XML_ELEMENT_NODE)) 1408 xmlTextReaderValidatePop(reader); 1409 #endif /* LIBXML_REGEXP_ENABLED */ 1410 if ((reader->preserves > 0) && 1411 (reader->node->extra & NODE_IS_SPRESERVED)) 1412 reader->preserves--; 1413 reader->node = reader->node->next; 1414 reader->state = XML_TEXTREADER_ELEMENT; 1415 1416 /* 1417 * Cleanup of the old node 1418 */ 1419 if ((reader->preserves == 0) && 1420 #ifdef LIBXML_XINCLUDE_ENABLED 1421 (reader->in_xinclude == 0) && 1422 #endif 1423 (reader->entNr == 0) && 1424 (reader->node->prev != NULL) && 1425 (reader->node->prev->type != XML_DTD_NODE)) { 1426 xmlNodePtr tmp = reader->node->prev; 1427 if ((tmp->extra & NODE_IS_PRESERVED) == 0) { 1428 xmlUnlinkNode(tmp); 1429 xmlTextReaderFreeNode(reader, tmp); 1430 } 1431 } 1432 1433 goto node_found; 1434 } 1435 if ((oldstate == XML_TEXTREADER_ELEMENT) && 1436 (reader->node->type == XML_ELEMENT_NODE) && 1437 (reader->node->children == NULL) && 1438 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {; 1439 reader->state = XML_TEXTREADER_END; 1440 goto node_found; 1441 } 1442 #ifdef LIBXML_REGEXP_ENABLED 1443 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE)) 1444 xmlTextReaderValidatePop(reader); 1445 #endif /* LIBXML_REGEXP_ENABLED */ 1446 if ((reader->preserves > 0) && 1447 (reader->node->extra & NODE_IS_SPRESERVED)) 1448 reader->preserves--; 1449 reader->node = reader->node->parent; 1450 if ((reader->node == NULL) || 1451 (reader->node->type == XML_DOCUMENT_NODE) || 1452 #ifdef LIBXML_DOCB_ENABLED 1453 (reader->node->type == XML_DOCB_DOCUMENT_NODE) || 1454 #endif 1455 (reader->node->type == XML_HTML_DOCUMENT_NODE)) { 1456 if (reader->mode != XML_TEXTREADER_MODE_EOF) { 1457 val = xmlParseChunk(reader->ctxt, "", 0, 1); 1458 reader->state = XML_TEXTREADER_DONE; 1459 if (val != 0) 1460 return(-1); 1461 } 1462 reader->node = NULL; 1463 reader->depth = -1; 1464 1465 /* 1466 * Cleanup of the old node 1467 */ 1468 if ((oldnode != NULL) && (reader->preserves == 0) && 1469 #ifdef LIBXML_XINCLUDE_ENABLED 1470 (reader->in_xinclude == 0) && 1471 #endif 1472 (reader->entNr == 0) && 1473 (oldnode->type != XML_DTD_NODE) && 1474 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) { 1475 xmlUnlinkNode(oldnode); 1476 xmlTextReaderFreeNode(reader, oldnode); 1477 } 1478 1479 goto node_end; 1480 } 1481 if ((reader->preserves == 0) && 1482 #ifdef LIBXML_XINCLUDE_ENABLED 1483 (reader->in_xinclude == 0) && 1484 #endif 1485 (reader->entNr == 0) && 1486 (reader->node->last != NULL) && 1487 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) { 1488 xmlNodePtr tmp = reader->node->last; 1489 xmlUnlinkNode(tmp); 1490 xmlTextReaderFreeNode(reader, tmp); 1491 } 1492 reader->depth--; 1493 reader->state = XML_TEXTREADER_BACKTRACK; 1494 1495 node_found: 1496 DUMP_READER 1497 1498 /* 1499 * If we are in the middle of a piece of CDATA make sure it's finished 1500 */ 1501 if ((reader->node != NULL) && 1502 (reader->node->next == NULL) && 1503 ((reader->node->type == XML_TEXT_NODE) || 1504 (reader->node->type == XML_CDATA_SECTION_NODE))) { 1505 if (xmlTextReaderExpand(reader) == NULL) 1506 return -1; 1507 } 1508 1509 #ifdef LIBXML_XINCLUDE_ENABLED 1510 /* 1511 * Handle XInclude if asked for 1512 */ 1513 if ((reader->xinclude) && (reader->node != NULL) && 1514 (reader->node->type == XML_ELEMENT_NODE) && 1515 (reader->node->ns != NULL) && 1516 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) || 1517 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) { 1518 if (reader->xincctxt == NULL) { 1519 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc); 1520 xmlXIncludeSetFlags(reader->xincctxt, 1521 reader->parserFlags & (~XML_PARSE_NOXINCNODE)); 1522 } 1523 /* 1524 * expand that node and process it 1525 */ 1526 if (xmlTextReaderExpand(reader) == NULL) 1527 return -1; 1528 xmlXIncludeProcessNode(reader->xincctxt, reader->node); 1529 } 1530 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) { 1531 reader->in_xinclude++; 1532 goto get_next_node; 1533 } 1534 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) { 1535 reader->in_xinclude--; 1536 goto get_next_node; 1537 } 1538 #endif 1539 /* 1540 * Handle entities enter and exit when in entity replacement mode 1541 */ 1542 if ((reader->node != NULL) && 1543 (reader->node->type == XML_ENTITY_REF_NODE) && 1544 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) { 1545 /* 1546 * Case where the underlying tree is not availble, lookup the entity 1547 * and walk it. 1548 */ 1549 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) && 1550 (reader->ctxt->sax->getEntity != NULL)) { 1551 reader->node->children = (xmlNodePtr) 1552 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name); 1553 } 1554 1555 if ((reader->node->children != NULL) && 1556 (reader->node->children->type == XML_ENTITY_DECL) && 1557 (reader->node->children->children != NULL)) { 1558 xmlTextReaderEntPush(reader, reader->node); 1559 reader->node = reader->node->children->children; 1560 } 1561 #ifdef LIBXML_REGEXP_ENABLED 1562 } else if ((reader->node != NULL) && 1563 (reader->node->type == XML_ENTITY_REF_NODE) && 1564 (reader->ctxt != NULL) && (reader->validate)) { 1565 xmlTextReaderValidateEntity(reader); 1566 #endif /* LIBXML_REGEXP_ENABLED */ 1567 } 1568 if ((reader->node != NULL) && 1569 (reader->node->type == XML_ENTITY_DECL) && 1570 (reader->ent != NULL) && (reader->ent->children == reader->node)) { 1571 reader->node = xmlTextReaderEntPop(reader); 1572 reader->depth++; 1573 goto get_next_node; 1574 } 1575 #ifdef LIBXML_REGEXP_ENABLED 1576 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) { 1577 xmlNodePtr node = reader->node; 1578 1579 if ((node->type == XML_ELEMENT_NODE) && 1580 ((reader->state != XML_TEXTREADER_END) && 1581 (reader->state != XML_TEXTREADER_BACKTRACK))) { 1582 xmlTextReaderValidatePush(reader); 1583 } else if ((node->type == XML_TEXT_NODE) || 1584 (node->type == XML_CDATA_SECTION_NODE)) { 1585 xmlTextReaderValidateCData(reader, node->content, 1586 xmlStrlen(node->content)); 1587 } 1588 } 1589 #endif /* LIBXML_REGEXP_ENABLED */ 1590 #ifdef LIBXML_PATTERN_ENABLED 1591 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) && 1592 (reader->state != XML_TEXTREADER_BACKTRACK)) { 1593 int i; 1594 for (i = 0;i < reader->patternNr;i++) { 1595 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) { 1596 xmlTextReaderPreserve(reader); 1597 break; 1598 } 1599 } 1600 } 1601 #endif /* LIBXML_PATTERN_ENABLED */ 1602 #ifdef LIBXML_SCHEMAS_ENABLED 1603 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) && 1604 (reader->xsdValidErrors == 0) && 1605 (reader->xsdValidCtxt != NULL)) { 1606 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt); 1607 } 1608 #endif /* LIBXML_PATTERN_ENABLED */ 1609 return(1); 1610 node_end: 1611 reader->state = XML_TEXTREADER_DONE; 1612 return(0); 1613 } 1614 1615 /** 1616 * xmlTextReaderReadState: 1617 * @reader: the xmlTextReaderPtr used 1618 * 1619 * Gets the read state of the reader. 1620 * 1621 * Returns the state value, or -1 in case of error 1622 */ 1623 int 1624 xmlTextReaderReadState(xmlTextReaderPtr reader) { 1625 if (reader == NULL) 1626 return(-1); 1627 return(reader->mode); 1628 } 1629 1630 /** 1631 * xmlTextReaderExpand: 1632 * @reader: the xmlTextReaderPtr used 1633 * 1634 * Reads the contents of the current node and the full subtree. It then makes 1635 * the subtree available until the next xmlTextReaderRead() call 1636 * 1637 * Returns a node pointer valid until the next xmlTextReaderRead() call 1638 * or NULL in case of error. 1639 */ 1640 xmlNodePtr 1641 xmlTextReaderExpand(xmlTextReaderPtr reader) { 1642 if ((reader == NULL) || (reader->node == NULL)) 1643 return(NULL); 1644 if (reader->doc != NULL) 1645 return(reader->node); 1646 if (reader->ctxt == NULL) 1647 return(NULL); 1648 if (xmlTextReaderDoExpand(reader) < 0) 1649 return(NULL); 1650 return(reader->node); 1651 } 1652 1653 /** 1654 * xmlTextReaderNext: 1655 * @reader: the xmlTextReaderPtr used 1656 * 1657 * Skip to the node following the current one in document order while 1658 * avoiding the subtree if any. 1659 * 1660 * Returns 1 if the node was read successfully, 0 if there is no more 1661 * nodes to read, or -1 in case of error 1662 */ 1663 int 1664 xmlTextReaderNext(xmlTextReaderPtr reader) { 1665 int ret; 1666 xmlNodePtr cur; 1667 1668 if (reader == NULL) 1669 return(-1); 1670 if (reader->doc != NULL) 1671 return(xmlTextReaderNextTree(reader)); 1672 cur = reader->node; 1673 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) 1674 return(xmlTextReaderRead(reader)); 1675 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK) 1676 return(xmlTextReaderRead(reader)); 1677 if (cur->extra & NODE_IS_EMPTY) 1678 return(xmlTextReaderRead(reader)); 1679 do { 1680 ret = xmlTextReaderRead(reader); 1681 if (ret != 1) 1682 return(ret); 1683 } while (reader->node != cur); 1684 return(xmlTextReaderRead(reader)); 1685 } 1686 1687 #ifdef LIBXML_WRITER_ENABLED 1688 /** 1689 * xmlTextReaderReadInnerXml: 1690 * @reader: the xmlTextReaderPtr used 1691 * 1692 * Reads the contents of the current node, including child nodes and markup. 1693 * 1694 * Returns a string containing the XML content, or NULL if the current node 1695 * is neither an element nor attribute, or has no child nodes. The 1696 * string must be deallocated by the caller. 1697 */ 1698 xmlChar * 1699 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) 1700 { 1701 xmlChar *resbuf; 1702 xmlNodePtr node, cur_node; 1703 xmlBufferPtr buff, buff2; 1704 xmlDocPtr doc; 1705 1706 if (xmlTextReaderExpand(reader) == NULL) { 1707 return NULL; 1708 } 1709 doc = reader->doc; 1710 buff = xmlBufferCreate(); 1711 for (cur_node = reader->node->children; cur_node != NULL; 1712 cur_node = cur_node->next) { 1713 node = xmlDocCopyNode(cur_node, doc, 1); 1714 buff2 = xmlBufferCreate(); 1715 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { 1716 xmlFreeNode(node); 1717 xmlBufferFree(buff2); 1718 xmlBufferFree(buff); 1719 return NULL; 1720 } 1721 xmlBufferCat(buff, buff2->content); 1722 xmlFreeNode(node); 1723 xmlBufferFree(buff2); 1724 } 1725 resbuf = buff->content; 1726 buff->content = NULL; 1727 1728 xmlBufferFree(buff); 1729 return resbuf; 1730 } 1731 #endif 1732 1733 #ifdef LIBXML_WRITER_ENABLED 1734 /** 1735 * xmlTextReaderReadOuterXml: 1736 * @reader: the xmlTextReaderPtr used 1737 * 1738 * Reads the contents of the current node, including child nodes and markup. 1739 * 1740 * Returns a string containing the node and any XML content, or NULL if the 1741 * current node cannot be serialized. The string must be deallocated 1742 * by the caller. 1743 */ 1744 xmlChar * 1745 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) 1746 { 1747 xmlChar *resbuf; 1748 xmlNodePtr node; 1749 xmlBufferPtr buff; 1750 xmlDocPtr doc; 1751 1752 node = reader->node; 1753 doc = reader->doc; 1754 if (xmlTextReaderExpand(reader) == NULL) { 1755 return NULL; 1756 } 1757 if (node->type == XML_DTD_NODE) { 1758 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node); 1759 } else { 1760 node = xmlDocCopyNode(node, doc, 1); 1761 } 1762 buff = xmlBufferCreate(); 1763 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { 1764 xmlFreeNode(node); 1765 xmlBufferFree(buff); 1766 return NULL; 1767 } 1768 1769 resbuf = buff->content; 1770 buff->content = NULL; 1771 1772 xmlFreeNode(node); 1773 xmlBufferFree(buff); 1774 return resbuf; 1775 } 1776 #endif 1777 1778 /** 1779 * xmlTextReaderReadString: 1780 * @reader: the xmlTextReaderPtr used 1781 * 1782 * Reads the contents of an element or a text node as a string. 1783 * 1784 * Returns a string containing the contents of the Element or Text node, 1785 * or NULL if the reader is positioned on any other type of node. 1786 * The string must be deallocated by the caller. 1787 */ 1788 xmlChar * 1789 xmlTextReaderReadString(xmlTextReaderPtr reader) 1790 { 1791 xmlNodePtr node; 1792 1793 if ((reader == NULL) || (reader->node == NULL)) 1794 return(NULL); 1795 1796 node = (reader->curnode != NULL) ? reader->curnode : reader->node; 1797 switch (node->type) { 1798 case XML_TEXT_NODE: 1799 if (node->content != NULL) 1800 return(xmlStrdup(node->content)); 1801 break; 1802 case XML_ELEMENT_NODE: 1803 if (xmlTextReaderDoExpand(reader) != -1) { 1804 return xmlTextReaderCollectSiblings(node->children); 1805 } 1806 break; 1807 case XML_ATTRIBUTE_NODE: 1808 TODO 1809 break; 1810 default: 1811 break; 1812 } 1813 return(NULL); 1814 } 1815 1816 #if 0 1817 /** 1818 * xmlTextReaderReadBase64: 1819 * @reader: the xmlTextReaderPtr used 1820 * @array: a byte array to store the content. 1821 * @offset: the zero-based index into array where the method should 1822 * begin to write. 1823 * @len: the number of bytes to write. 1824 * 1825 * Reads and decodes the Base64 encoded contents of an element and 1826 * stores the result in a byte buffer. 1827 * 1828 * Returns the number of bytes written to array, or zero if the current 1829 * instance is not positioned on an element or -1 in case of error. 1830 */ 1831 int 1832 xmlTextReaderReadBase64(xmlTextReaderPtr reader, 1833 unsigned char *array ATTRIBUTE_UNUSED, 1834 int offset ATTRIBUTE_UNUSED, 1835 int len ATTRIBUTE_UNUSED) { 1836 if ((reader == NULL) || (reader->ctxt == NULL)) 1837 return(-1); 1838 if (reader->ctxt->wellFormed != 1) 1839 return(-1); 1840 1841 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1842 return(0); 1843 TODO 1844 return(0); 1845 } 1846 1847 /** 1848 * xmlTextReaderReadBinHex: 1849 * @reader: the xmlTextReaderPtr used 1850 * @array: a byte array to store the content. 1851 * @offset: the zero-based index into array where the method should 1852 * begin to write. 1853 * @len: the number of bytes to write. 1854 * 1855 * Reads and decodes the BinHex encoded contents of an element and 1856 * stores the result in a byte buffer. 1857 * 1858 * Returns the number of bytes written to array, or zero if the current 1859 * instance is not positioned on an element or -1 in case of error. 1860 */ 1861 int 1862 xmlTextReaderReadBinHex(xmlTextReaderPtr reader, 1863 unsigned char *array ATTRIBUTE_UNUSED, 1864 int offset ATTRIBUTE_UNUSED, 1865 int len ATTRIBUTE_UNUSED) { 1866 if ((reader == NULL) || (reader->ctxt == NULL)) 1867 return(-1); 1868 if (reader->ctxt->wellFormed != 1) 1869 return(-1); 1870 1871 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1872 return(0); 1873 TODO 1874 return(0); 1875 } 1876 #endif 1877 1878 /************************************************************************ 1879 * * 1880 * Operating on a preparsed tree * 1881 * * 1882 ************************************************************************/ 1883 static int 1884 xmlTextReaderNextTree(xmlTextReaderPtr reader) 1885 { 1886 if (reader == NULL) 1887 return(-1); 1888 1889 if (reader->state == XML_TEXTREADER_END) 1890 return(0); 1891 1892 if (reader->node == NULL) { 1893 if (reader->doc->children == NULL) { 1894 reader->state = XML_TEXTREADER_END; 1895 return(0); 1896 } 1897 1898 reader->node = reader->doc->children; 1899 reader->state = XML_TEXTREADER_START; 1900 return(1); 1901 } 1902 1903 if (reader->state != XML_TEXTREADER_BACKTRACK) { 1904 /* Here removed traversal to child, because we want to skip the subtree, 1905 replace with traversal to sibling to skip subtree */ 1906 if (reader->node->next != 0) { 1907 /* Move to sibling if present,skipping sub-tree */ 1908 reader->node = reader->node->next; 1909 reader->state = XML_TEXTREADER_START; 1910 return(1); 1911 } 1912 1913 /* if reader->node->next is NULL mean no subtree for current node, 1914 so need to move to sibling of parent node if present */ 1915 if ((reader->node->type == XML_ELEMENT_NODE) || 1916 (reader->node->type == XML_ATTRIBUTE_NODE)) { 1917 reader->state = XML_TEXTREADER_BACKTRACK; 1918 /* This will move to parent if present */ 1919 xmlTextReaderRead(reader); 1920 } 1921 } 1922 1923 if (reader->node->next != 0) { 1924 reader->node = reader->node->next; 1925 reader->state = XML_TEXTREADER_START; 1926 return(1); 1927 } 1928 1929 if (reader->node->parent != 0) { 1930 if (reader->node->parent->type == XML_DOCUMENT_NODE) { 1931 reader->state = XML_TEXTREADER_END; 1932 return(0); 1933 } 1934 1935 reader->node = reader->node->parent; 1936 reader->depth--; 1937 reader->state = XML_TEXTREADER_BACKTRACK; 1938 /* Repeat process to move to sibling of parent node if present */ 1939 xmlTextReaderNextTree(reader); 1940 } 1941 1942 reader->state = XML_TEXTREADER_END; 1943 1944 return(1); 1945 } 1946 1947 /** 1948 * xmlTextReaderReadTree: 1949 * @reader: the xmlTextReaderPtr used 1950 * 1951 * Moves the position of the current instance to the next node in 1952 * the stream, exposing its properties. 1953 * 1954 * Returns 1 if the node was read successfully, 0 if there is no more 1955 * nodes to read, or -1 in case of error 1956 */ 1957 static int 1958 xmlTextReaderReadTree(xmlTextReaderPtr reader) { 1959 if (reader->state == XML_TEXTREADER_END) 1960 return(0); 1961 1962 next_node: 1963 if (reader->node == NULL) { 1964 if (reader->doc->children == NULL) { 1965 reader->state = XML_TEXTREADER_END; 1966 return(0); 1967 } 1968 1969 reader->node = reader->doc->children; 1970 reader->state = XML_TEXTREADER_START; 1971 goto found_node; 1972 } 1973 1974 if ((reader->state != XML_TEXTREADER_BACKTRACK) && 1975 (reader->node->type != XML_DTD_NODE) && 1976 (reader->node->type != XML_XINCLUDE_START) && 1977 (reader->node->type != XML_ENTITY_REF_NODE)) { 1978 if (reader->node->children != NULL) { 1979 reader->node = reader->node->children; 1980 reader->depth++; 1981 reader->state = XML_TEXTREADER_START; 1982 goto found_node; 1983 } 1984 1985 if (reader->node->type == XML_ATTRIBUTE_NODE) { 1986 reader->state = XML_TEXTREADER_BACKTRACK; 1987 goto found_node; 1988 } 1989 } 1990 1991 if (reader->node->next != NULL) { 1992 reader->node = reader->node->next; 1993 reader->state = XML_TEXTREADER_START; 1994 goto found_node; 1995 } 1996 1997 if (reader->node->parent != NULL) { 1998 if ((reader->node->parent->type == XML_DOCUMENT_NODE) || 1999 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { 2000 reader->state = XML_TEXTREADER_END; 2001 return(0); 2002 } 2003 2004 reader->node = reader->node->parent; 2005 reader->depth--; 2006 reader->state = XML_TEXTREADER_BACKTRACK; 2007 goto found_node; 2008 } 2009 2010 reader->state = XML_TEXTREADER_END; 2011 2012 found_node: 2013 if ((reader->node->type == XML_XINCLUDE_START) || 2014 (reader->node->type == XML_XINCLUDE_END)) 2015 goto next_node; 2016 2017 return(1); 2018 } 2019 2020 /** 2021 * xmlTextReaderNextSibling: 2022 * @reader: the xmlTextReaderPtr used 2023 * 2024 * Skip to the node following the current one in document order while 2025 * avoiding the subtree if any. 2026 * Currently implemented only for Readers built on a document 2027 * 2028 * Returns 1 if the node was read successfully, 0 if there is no more 2029 * nodes to read, or -1 in case of error 2030 */ 2031 int 2032 xmlTextReaderNextSibling(xmlTextReaderPtr reader) { 2033 if (reader == NULL) 2034 return(-1); 2035 if (reader->doc == NULL) { 2036 /* TODO */ 2037 return(-1); 2038 } 2039 2040 if (reader->state == XML_TEXTREADER_END) 2041 return(0); 2042 2043 if (reader->node == NULL) 2044 return(xmlTextReaderNextTree(reader)); 2045 2046 if (reader->node->next != NULL) { 2047 reader->node = reader->node->next; 2048 reader->state = XML_TEXTREADER_START; 2049 return(1); 2050 } 2051 2052 return(0); 2053 } 2054 2055 /************************************************************************ 2056 * * 2057 * Constructor and destructors * 2058 * * 2059 ************************************************************************/ 2060 /** 2061 * xmlNewTextReader: 2062 * @input: the xmlParserInputBufferPtr used to read data 2063 * @URI: the URI information for the source if available 2064 * 2065 * Create an xmlTextReader structure fed with @input 2066 * 2067 * Returns the new xmlTextReaderPtr or NULL in case of error 2068 */ 2069 xmlTextReaderPtr 2070 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { 2071 xmlTextReaderPtr ret; 2072 2073 if (input == NULL) 2074 return(NULL); 2075 ret = xmlMalloc(sizeof(xmlTextReader)); 2076 if (ret == NULL) { 2077 xmlGenericError(xmlGenericErrorContext, 2078 "xmlNewTextReader : malloc failed\n"); 2079 return(NULL); 2080 } 2081 memset(ret, 0, sizeof(xmlTextReader)); 2082 ret->doc = NULL; 2083 ret->entTab = NULL; 2084 ret->entMax = 0; 2085 ret->entNr = 0; 2086 ret->input = input; 2087 ret->buffer = xmlBufCreateSize(100); 2088 if (ret->buffer == NULL) { 2089 xmlFree(ret); 2090 xmlGenericError(xmlGenericErrorContext, 2091 "xmlNewTextReader : malloc failed\n"); 2092 return(NULL); 2093 } 2094 /* no operation on a reader should require a huge buffer */ 2095 xmlBufSetAllocationScheme(ret->buffer, 2096 XML_BUFFER_ALLOC_BOUNDED); 2097 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 2098 if (ret->sax == NULL) { 2099 xmlBufFree(ret->buffer); 2100 xmlFree(ret); 2101 xmlGenericError(xmlGenericErrorContext, 2102 "xmlNewTextReader : malloc failed\n"); 2103 return(NULL); 2104 } 2105 xmlSAXVersion(ret->sax, 2); 2106 ret->startElement = ret->sax->startElement; 2107 ret->sax->startElement = xmlTextReaderStartElement; 2108 ret->endElement = ret->sax->endElement; 2109 ret->sax->endElement = xmlTextReaderEndElement; 2110 #ifdef LIBXML_SAX1_ENABLED 2111 if (ret->sax->initialized == XML_SAX2_MAGIC) { 2112 #endif /* LIBXML_SAX1_ENABLED */ 2113 ret->startElementNs = ret->sax->startElementNs; 2114 ret->sax->startElementNs = xmlTextReaderStartElementNs; 2115 ret->endElementNs = ret->sax->endElementNs; 2116 ret->sax->endElementNs = xmlTextReaderEndElementNs; 2117 #ifdef LIBXML_SAX1_ENABLED 2118 } else { 2119 ret->startElementNs = NULL; 2120 ret->endElementNs = NULL; 2121 } 2122 #endif /* LIBXML_SAX1_ENABLED */ 2123 ret->characters = ret->sax->characters; 2124 ret->sax->characters = xmlTextReaderCharacters; 2125 ret->sax->ignorableWhitespace = xmlTextReaderCharacters; 2126 ret->cdataBlock = ret->sax->cdataBlock; 2127 ret->sax->cdataBlock = xmlTextReaderCDataBlock; 2128 2129 ret->mode = XML_TEXTREADER_MODE_INITIAL; 2130 ret->node = NULL; 2131 ret->curnode = NULL; 2132 if (xmlBufUse(ret->input->buffer) < 4) { 2133 xmlParserInputBufferRead(input, 4); 2134 } 2135 if (xmlBufUse(ret->input->buffer) >= 4) { 2136 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, 2137 (const char *) xmlBufContent(ret->input->buffer), 2138 4, URI); 2139 ret->base = 0; 2140 ret->cur = 4; 2141 } else { 2142 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); 2143 ret->base = 0; 2144 ret->cur = 0; 2145 } 2146 2147 if (ret->ctxt == NULL) { 2148 xmlGenericError(xmlGenericErrorContext, 2149 "xmlNewTextReader : malloc failed\n"); 2150 xmlBufFree(ret->buffer); 2151 xmlFree(ret->sax); 2152 xmlFree(ret); 2153 return(NULL); 2154 } 2155 ret->ctxt->parseMode = XML_PARSE_READER; 2156 ret->ctxt->_private = ret; 2157 ret->ctxt->linenumbers = 1; 2158 ret->ctxt->dictNames = 1; 2159 ret->allocs = XML_TEXTREADER_CTXT; 2160 /* 2161 * use the parser dictionary to allocate all elements and attributes names 2162 */ 2163 ret->ctxt->docdict = 1; 2164 ret->dict = ret->ctxt->dict; 2165 #ifdef LIBXML_XINCLUDE_ENABLED 2166 ret->xinclude = 0; 2167 #endif 2168 #ifdef LIBXML_PATTERN_ENABLED 2169 ret->patternMax = 0; 2170 ret->patternTab = NULL; 2171 #endif 2172 return(ret); 2173 } 2174 2175 /** 2176 * xmlNewTextReaderFilename: 2177 * @URI: the URI of the resource to process 2178 * 2179 * Create an xmlTextReader structure fed with the resource at @URI 2180 * 2181 * Returns the new xmlTextReaderPtr or NULL in case of error 2182 */ 2183 xmlTextReaderPtr 2184 xmlNewTextReaderFilename(const char *URI) { 2185 xmlParserInputBufferPtr input; 2186 xmlTextReaderPtr ret; 2187 char *directory = NULL; 2188 2189 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); 2190 if (input == NULL) 2191 return(NULL); 2192 ret = xmlNewTextReader(input, URI); 2193 if (ret == NULL) { 2194 xmlFreeParserInputBuffer(input); 2195 return(NULL); 2196 } 2197 ret->allocs |= XML_TEXTREADER_INPUT; 2198 if (ret->ctxt->directory == NULL) 2199 directory = xmlParserGetDirectory(URI); 2200 if ((ret->ctxt->directory == NULL) && (directory != NULL)) 2201 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); 2202 if (directory != NULL) 2203 xmlFree(directory); 2204 return(ret); 2205 } 2206 2207 /** 2208 * xmlFreeTextReader: 2209 * @reader: the xmlTextReaderPtr 2210 * 2211 * Deallocate all the resources associated to the reader 2212 */ 2213 void 2214 xmlFreeTextReader(xmlTextReaderPtr reader) { 2215 if (reader == NULL) 2216 return; 2217 #ifdef LIBXML_SCHEMAS_ENABLED 2218 if (reader->rngSchemas != NULL) { 2219 xmlRelaxNGFree(reader->rngSchemas); 2220 reader->rngSchemas = NULL; 2221 } 2222 if (reader->rngValidCtxt != NULL) { 2223 if (! reader->rngPreserveCtxt) 2224 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 2225 reader->rngValidCtxt = NULL; 2226 } 2227 if (reader->xsdPlug != NULL) { 2228 xmlSchemaSAXUnplug(reader->xsdPlug); 2229 reader->xsdPlug = NULL; 2230 } 2231 if (reader->xsdValidCtxt != NULL) { 2232 if (! reader->xsdPreserveCtxt) 2233 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 2234 reader->xsdValidCtxt = NULL; 2235 } 2236 if (reader->xsdSchemas != NULL) { 2237 xmlSchemaFree(reader->xsdSchemas); 2238 reader->xsdSchemas = NULL; 2239 } 2240 #endif 2241 #ifdef LIBXML_XINCLUDE_ENABLED 2242 if (reader->xincctxt != NULL) 2243 xmlXIncludeFreeContext(reader->xincctxt); 2244 #endif 2245 #ifdef LIBXML_PATTERN_ENABLED 2246 if (reader->patternTab != NULL) { 2247 int i; 2248 for (i = 0;i < reader->patternNr;i++) { 2249 if (reader->patternTab[i] != NULL) 2250 xmlFreePattern(reader->patternTab[i]); 2251 } 2252 xmlFree(reader->patternTab); 2253 } 2254 #endif 2255 if (reader->faketext != NULL) { 2256 xmlFreeNode(reader->faketext); 2257 } 2258 if (reader->ctxt != NULL) { 2259 if (reader->dict == reader->ctxt->dict) 2260 reader->dict = NULL; 2261 if (reader->ctxt->myDoc != NULL) { 2262 if (reader->preserve == 0) 2263 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2264 reader->ctxt->myDoc = NULL; 2265 } 2266 if ((reader->ctxt->vctxt.vstateTab != NULL) && 2267 (reader->ctxt->vctxt.vstateMax > 0)){ 2268 xmlFree(reader->ctxt->vctxt.vstateTab); 2269 reader->ctxt->vctxt.vstateTab = NULL; 2270 reader->ctxt->vctxt.vstateMax = 0; 2271 } 2272 if (reader->allocs & XML_TEXTREADER_CTXT) 2273 xmlFreeParserCtxt(reader->ctxt); 2274 } 2275 if (reader->sax != NULL) 2276 xmlFree(reader->sax); 2277 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) 2278 xmlFreeParserInputBuffer(reader->input); 2279 if (reader->buffer != NULL) 2280 xmlBufFree(reader->buffer); 2281 if (reader->entTab != NULL) 2282 xmlFree(reader->entTab); 2283 if (reader->dict != NULL) 2284 xmlDictFree(reader->dict); 2285 xmlFree(reader); 2286 } 2287 2288 /************************************************************************ 2289 * * 2290 * Methods for XmlTextReader * 2291 * * 2292 ************************************************************************/ 2293 /** 2294 * xmlTextReaderClose: 2295 * @reader: the xmlTextReaderPtr used 2296 * 2297 * This method releases any resources allocated by the current instance 2298 * changes the state to Closed and close any underlying input. 2299 * 2300 * Returns 0 or -1 in case of error 2301 */ 2302 int 2303 xmlTextReaderClose(xmlTextReaderPtr reader) { 2304 if (reader == NULL) 2305 return(-1); 2306 reader->node = NULL; 2307 reader->curnode = NULL; 2308 reader->mode = XML_TEXTREADER_MODE_CLOSED; 2309 if (reader->ctxt != NULL) { 2310 xmlStopParser(reader->ctxt); 2311 if (reader->ctxt->myDoc != NULL) { 2312 if (reader->preserve == 0) 2313 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2314 reader->ctxt->myDoc = NULL; 2315 } 2316 } 2317 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { 2318 xmlFreeParserInputBuffer(reader->input); 2319 reader->allocs -= XML_TEXTREADER_INPUT; 2320 } 2321 return(0); 2322 } 2323 2324 /** 2325 * xmlTextReaderGetAttributeNo: 2326 * @reader: the xmlTextReaderPtr used 2327 * @no: the zero-based index of the attribute relative to the containing element 2328 * 2329 * Provides the value of the attribute with the specified index relative 2330 * to the containing element. 2331 * 2332 * Returns a string containing the value of the specified attribute, or NULL 2333 * in case of error. The string must be deallocated by the caller. 2334 */ 2335 xmlChar * 2336 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { 2337 xmlChar *ret; 2338 int i; 2339 xmlAttrPtr cur; 2340 xmlNsPtr ns; 2341 2342 if (reader == NULL) 2343 return(NULL); 2344 if (reader->node == NULL) 2345 return(NULL); 2346 if (reader->curnode != NULL) 2347 return(NULL); 2348 /* TODO: handle the xmlDecl */ 2349 if (reader->node->type != XML_ELEMENT_NODE) 2350 return(NULL); 2351 2352 ns = reader->node->nsDef; 2353 for (i = 0;(i < no) && (ns != NULL);i++) { 2354 ns = ns->next; 2355 } 2356 if (ns != NULL) 2357 return(xmlStrdup(ns->href)); 2358 2359 cur = reader->node->properties; 2360 if (cur == NULL) 2361 return(NULL); 2362 for (;i < no;i++) { 2363 cur = cur->next; 2364 if (cur == NULL) 2365 return(NULL); 2366 } 2367 /* TODO walk the DTD if present */ 2368 2369 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); 2370 if (ret == NULL) return(xmlStrdup((xmlChar *)"")); 2371 return(ret); 2372 } 2373 2374 /** 2375 * xmlTextReaderGetAttribute: 2376 * @reader: the xmlTextReaderPtr used 2377 * @name: the qualified name of the attribute. 2378 * 2379 * Provides the value of the attribute with the specified qualified name. 2380 * 2381 * Returns a string containing the value of the specified attribute, or NULL 2382 * in case of error. The string must be deallocated by the caller. 2383 */ 2384 xmlChar * 2385 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2386 xmlChar *prefix = NULL; 2387 xmlChar *localname; 2388 xmlNsPtr ns; 2389 xmlChar *ret = NULL; 2390 2391 if ((reader == NULL) || (name == NULL)) 2392 return(NULL); 2393 if (reader->node == NULL) 2394 return(NULL); 2395 if (reader->curnode != NULL) 2396 return(NULL); 2397 2398 /* TODO: handle the xmlDecl */ 2399 if (reader->node->type != XML_ELEMENT_NODE) 2400 return(NULL); 2401 2402 localname = xmlSplitQName2(name, &prefix); 2403 if (localname == NULL) { 2404 /* 2405 * Namespace default decl 2406 */ 2407 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 2408 ns = reader->node->nsDef; 2409 while (ns != NULL) { 2410 if (ns->prefix == NULL) { 2411 return(xmlStrdup(ns->href)); 2412 } 2413 ns = ns->next; 2414 } 2415 return NULL; 2416 } 2417 return(xmlGetNoNsProp(reader->node, name)); 2418 } 2419 2420 /* 2421 * Namespace default decl 2422 */ 2423 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { 2424 ns = reader->node->nsDef; 2425 while (ns != NULL) { 2426 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { 2427 ret = xmlStrdup(ns->href); 2428 break; 2429 } 2430 ns = ns->next; 2431 } 2432 } else { 2433 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2434 if (ns != NULL) 2435 ret = xmlGetNsProp(reader->node, localname, ns->href); 2436 } 2437 2438 xmlFree(localname); 2439 if (prefix != NULL) 2440 xmlFree(prefix); 2441 return(ret); 2442 } 2443 2444 2445 /** 2446 * xmlTextReaderGetAttributeNs: 2447 * @reader: the xmlTextReaderPtr used 2448 * @localName: the local name of the attribute. 2449 * @namespaceURI: the namespace URI of the attribute. 2450 * 2451 * Provides the value of the specified attribute 2452 * 2453 * Returns a string containing the value of the specified attribute, or NULL 2454 * in case of error. The string must be deallocated by the caller. 2455 */ 2456 xmlChar * 2457 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, 2458 const xmlChar *namespaceURI) { 2459 xmlChar *prefix = NULL; 2460 xmlNsPtr ns; 2461 2462 if ((reader == NULL) || (localName == NULL)) 2463 return(NULL); 2464 if (reader->node == NULL) 2465 return(NULL); 2466 if (reader->curnode != NULL) 2467 return(NULL); 2468 2469 /* TODO: handle the xmlDecl */ 2470 if (reader->node->type != XML_ELEMENT_NODE) 2471 return(NULL); 2472 2473 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { 2474 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { 2475 prefix = BAD_CAST localName; 2476 } 2477 ns = reader->node->nsDef; 2478 while (ns != NULL) { 2479 if ((prefix == NULL && ns->prefix == NULL) || 2480 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { 2481 return xmlStrdup(ns->href); 2482 } 2483 ns = ns->next; 2484 } 2485 return NULL; 2486 } 2487 2488 return(xmlGetNsProp(reader->node, localName, namespaceURI)); 2489 } 2490 2491 /** 2492 * xmlTextReaderGetRemainder: 2493 * @reader: the xmlTextReaderPtr used 2494 * 2495 * Method to get the remainder of the buffered XML. this method stops the 2496 * parser, set its state to End Of File and return the input stream with 2497 * what is left that the parser did not use. 2498 * 2499 * The implementation is not good, the parser certainly procgressed past 2500 * what's left in reader->input, and there is an allocation problem. Best 2501 * would be to rewrite it differently. 2502 * 2503 * Returns the xmlParserInputBufferPtr attached to the XML or NULL 2504 * in case of error. 2505 */ 2506 xmlParserInputBufferPtr 2507 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { 2508 xmlParserInputBufferPtr ret = NULL; 2509 2510 if (reader == NULL) 2511 return(NULL); 2512 if (reader->node == NULL) 2513 return(NULL); 2514 2515 reader->node = NULL; 2516 reader->curnode = NULL; 2517 reader->mode = XML_TEXTREADER_MODE_EOF; 2518 if (reader->ctxt != NULL) { 2519 xmlStopParser(reader->ctxt); 2520 if (reader->ctxt->myDoc != NULL) { 2521 if (reader->preserve == 0) 2522 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2523 reader->ctxt->myDoc = NULL; 2524 } 2525 } 2526 if (reader->allocs & XML_TEXTREADER_INPUT) { 2527 ret = reader->input; 2528 reader->input = NULL; 2529 reader->allocs -= XML_TEXTREADER_INPUT; 2530 } else { 2531 /* 2532 * Hum, one may need to duplicate the data structure because 2533 * without reference counting the input may be freed twice: 2534 * - by the layer which allocated it. 2535 * - by the layer to which would have been returned to. 2536 */ 2537 TODO 2538 return(NULL); 2539 } 2540 return(ret); 2541 } 2542 2543 /** 2544 * xmlTextReaderLookupNamespace: 2545 * @reader: the xmlTextReaderPtr used 2546 * @prefix: the prefix whose namespace URI is to be resolved. To return 2547 * the default namespace, specify NULL 2548 * 2549 * Resolves a namespace prefix in the scope of the current element. 2550 * 2551 * Returns a string containing the namespace URI to which the prefix maps 2552 * or NULL in case of error. The string must be deallocated by the caller. 2553 */ 2554 xmlChar * 2555 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { 2556 xmlNsPtr ns; 2557 2558 if (reader == NULL) 2559 return(NULL); 2560 if (reader->node == NULL) 2561 return(NULL); 2562 2563 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2564 if (ns == NULL) 2565 return(NULL); 2566 return(xmlStrdup(ns->href)); 2567 } 2568 2569 /** 2570 * xmlTextReaderMoveToAttributeNo: 2571 * @reader: the xmlTextReaderPtr used 2572 * @no: the zero-based index of the attribute relative to the containing 2573 * element. 2574 * 2575 * Moves the position of the current instance to the attribute with 2576 * the specified index relative to the containing element. 2577 * 2578 * Returns 1 in case of success, -1 in case of error, 0 if not found 2579 */ 2580 int 2581 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { 2582 int i; 2583 xmlAttrPtr cur; 2584 xmlNsPtr ns; 2585 2586 if (reader == NULL) 2587 return(-1); 2588 if (reader->node == NULL) 2589 return(-1); 2590 /* TODO: handle the xmlDecl */ 2591 if (reader->node->type != XML_ELEMENT_NODE) 2592 return(-1); 2593 2594 reader->curnode = NULL; 2595 2596 ns = reader->node->nsDef; 2597 for (i = 0;(i < no) && (ns != NULL);i++) { 2598 ns = ns->next; 2599 } 2600 if (ns != NULL) { 2601 reader->curnode = (xmlNodePtr) ns; 2602 return(1); 2603 } 2604 2605 cur = reader->node->properties; 2606 if (cur == NULL) 2607 return(0); 2608 for (;i < no;i++) { 2609 cur = cur->next; 2610 if (cur == NULL) 2611 return(0); 2612 } 2613 /* TODO walk the DTD if present */ 2614 2615 reader->curnode = (xmlNodePtr) cur; 2616 return(1); 2617 } 2618 2619 /** 2620 * xmlTextReaderMoveToAttribute: 2621 * @reader: the xmlTextReaderPtr used 2622 * @name: the qualified name of the attribute. 2623 * 2624 * Moves the position of the current instance to the attribute with 2625 * the specified qualified name. 2626 * 2627 * Returns 1 in case of success, -1 in case of error, 0 if not found 2628 */ 2629 int 2630 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2631 xmlChar *prefix = NULL; 2632 xmlChar *localname; 2633 xmlNsPtr ns; 2634 xmlAttrPtr prop; 2635 2636 if ((reader == NULL) || (name == NULL)) 2637 return(-1); 2638 if (reader->node == NULL) 2639 return(-1); 2640 2641 /* TODO: handle the xmlDecl */ 2642 if (reader->node->type != XML_ELEMENT_NODE) 2643 return(0); 2644 2645 localname = xmlSplitQName2(name, &prefix); 2646 if (localname == NULL) { 2647 /* 2648 * Namespace default decl 2649 */ 2650 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 2651 ns = reader->node->nsDef; 2652 while (ns != NULL) { 2653 if (ns->prefix == NULL) { 2654 reader->curnode = (xmlNodePtr) ns; 2655 return(1); 2656 } 2657 ns = ns->next; 2658 } 2659 return(0); 2660 } 2661 2662 prop = reader->node->properties; 2663 while (prop != NULL) { 2664 /* 2665 * One need to have 2666 * - same attribute names 2667 * - and the attribute carrying that namespace 2668 */ 2669 if ((xmlStrEqual(prop->name, name)) && 2670 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { 2671 reader->curnode = (xmlNodePtr) prop; 2672 return(1); 2673 } 2674 prop = prop->next; 2675 } 2676 return(0); 2677 } 2678 2679 /* 2680 * Namespace default decl 2681 */ 2682 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { 2683 ns = reader->node->nsDef; 2684 while (ns != NULL) { 2685 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { 2686 reader->curnode = (xmlNodePtr) ns; 2687 goto found; 2688 } 2689 ns = ns->next; 2690 } 2691 goto not_found; 2692 } 2693 prop = reader->node->properties; 2694 while (prop != NULL) { 2695 /* 2696 * One need to have 2697 * - same attribute names 2698 * - and the attribute carrying that namespace 2699 */ 2700 if ((xmlStrEqual(prop->name, localname)) && 2701 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) { 2702 reader->curnode = (xmlNodePtr) prop; 2703 goto found; 2704 } 2705 prop = prop->next; 2706 } 2707 not_found: 2708 if (localname != NULL) 2709 xmlFree(localname); 2710 if (prefix != NULL) 2711 xmlFree(prefix); 2712 return(0); 2713 2714 found: 2715 if (localname != NULL) 2716 xmlFree(localname); 2717 if (prefix != NULL) 2718 xmlFree(prefix); 2719 return(1); 2720 } 2721 2722 /** 2723 * xmlTextReaderMoveToAttributeNs: 2724 * @reader: the xmlTextReaderPtr used 2725 * @localName: the local name of the attribute. 2726 * @namespaceURI: the namespace URI of the attribute. 2727 * 2728 * Moves the position of the current instance to the attribute with the 2729 * specified local name and namespace URI. 2730 * 2731 * Returns 1 in case of success, -1 in case of error, 0 if not found 2732 */ 2733 int 2734 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, 2735 const xmlChar *localName, const xmlChar *namespaceURI) { 2736 xmlAttrPtr prop; 2737 xmlNodePtr node; 2738 xmlNsPtr ns; 2739 xmlChar *prefix = NULL; 2740 2741 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL)) 2742 return(-1); 2743 if (reader->node == NULL) 2744 return(-1); 2745 if (reader->node->type != XML_ELEMENT_NODE) 2746 return(0); 2747 node = reader->node; 2748 2749 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { 2750 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { 2751 prefix = BAD_CAST localName; 2752 } 2753 ns = reader->node->nsDef; 2754 while (ns != NULL) { 2755 if ((prefix == NULL && ns->prefix == NULL) || 2756 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { 2757 reader->curnode = (xmlNodePtr) ns; 2758 return(1); 2759 } 2760 ns = ns->next; 2761 } 2762 return(0); 2763 } 2764 2765 prop = node->properties; 2766 while (prop != NULL) { 2767 /* 2768 * One need to have 2769 * - same attribute names 2770 * - and the attribute carrying that namespace 2771 */ 2772 if (xmlStrEqual(prop->name, localName) && 2773 ((prop->ns != NULL) && 2774 (xmlStrEqual(prop->ns->href, namespaceURI)))) { 2775 reader->curnode = (xmlNodePtr) prop; 2776 return(1); 2777 } 2778 prop = prop->next; 2779 } 2780 return(0); 2781 } 2782 2783 /** 2784 * xmlTextReaderMoveToFirstAttribute: 2785 * @reader: the xmlTextReaderPtr used 2786 * 2787 * Moves the position of the current instance to the first attribute 2788 * associated with the current node. 2789 * 2790 * Returns 1 in case of success, -1 in case of error, 0 if not found 2791 */ 2792 int 2793 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) { 2794 if (reader == NULL) 2795 return(-1); 2796 if (reader->node == NULL) 2797 return(-1); 2798 if (reader->node->type != XML_ELEMENT_NODE) 2799 return(0); 2800 2801 if (reader->node->nsDef != NULL) { 2802 reader->curnode = (xmlNodePtr) reader->node->nsDef; 2803 return(1); 2804 } 2805 if (reader->node->properties != NULL) { 2806 reader->curnode = (xmlNodePtr) reader->node->properties; 2807 return(1); 2808 } 2809 return(0); 2810 } 2811 2812 /** 2813 * xmlTextReaderMoveToNextAttribute: 2814 * @reader: the xmlTextReaderPtr used 2815 * 2816 * Moves the position of the current instance to the next attribute 2817 * associated with the current node. 2818 * 2819 * Returns 1 in case of success, -1 in case of error, 0 if not found 2820 */ 2821 int 2822 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) { 2823 if (reader == NULL) 2824 return(-1); 2825 if (reader->node == NULL) 2826 return(-1); 2827 if (reader->node->type != XML_ELEMENT_NODE) 2828 return(0); 2829 if (reader->curnode == NULL) 2830 return(xmlTextReaderMoveToFirstAttribute(reader)); 2831 2832 if (reader->curnode->type == XML_NAMESPACE_DECL) { 2833 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2834 if (ns->next != NULL) { 2835 reader->curnode = (xmlNodePtr) ns->next; 2836 return(1); 2837 } 2838 if (reader->node->properties != NULL) { 2839 reader->curnode = (xmlNodePtr) reader->node->properties; 2840 return(1); 2841 } 2842 return(0); 2843 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) && 2844 (reader->curnode->next != NULL)) { 2845 reader->curnode = reader->curnode->next; 2846 return(1); 2847 } 2848 return(0); 2849 } 2850 2851 /** 2852 * xmlTextReaderMoveToElement: 2853 * @reader: the xmlTextReaderPtr used 2854 * 2855 * Moves the position of the current instance to the node that 2856 * contains the current Attribute node. 2857 * 2858 * Returns 1 in case of success, -1 in case of error, 0 if not moved 2859 */ 2860 int 2861 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) { 2862 if (reader == NULL) 2863 return(-1); 2864 if (reader->node == NULL) 2865 return(-1); 2866 if (reader->node->type != XML_ELEMENT_NODE) 2867 return(0); 2868 if (reader->curnode != NULL) { 2869 reader->curnode = NULL; 2870 return(1); 2871 } 2872 return(0); 2873 } 2874 2875 /** 2876 * xmlTextReaderReadAttributeValue: 2877 * @reader: the xmlTextReaderPtr used 2878 * 2879 * Parses an attribute value into one or more Text and EntityReference nodes. 2880 * 2881 * Returns 1 in case of success, 0 if the reader was not positionned on an 2882 * ttribute node or all the attribute values have been read, or -1 2883 * in case of error. 2884 */ 2885 int 2886 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { 2887 if (reader == NULL) 2888 return(-1); 2889 if (reader->node == NULL) 2890 return(-1); 2891 if (reader->curnode == NULL) 2892 return(0); 2893 if (reader->curnode->type == XML_ATTRIBUTE_NODE) { 2894 if (reader->curnode->children == NULL) 2895 return(0); 2896 reader->curnode = reader->curnode->children; 2897 } else if (reader->curnode->type == XML_NAMESPACE_DECL) { 2898 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2899 2900 if (reader->faketext == NULL) { 2901 reader->faketext = xmlNewDocText(reader->node->doc, 2902 ns->href); 2903 } else { 2904 if ((reader->faketext->content != NULL) && 2905 (reader->faketext->content != 2906 (xmlChar *) &(reader->faketext->properties))) 2907 xmlFree(reader->faketext->content); 2908 reader->faketext->content = xmlStrdup(ns->href); 2909 } 2910 reader->curnode = reader->faketext; 2911 } else { 2912 if (reader->curnode->next == NULL) 2913 return(0); 2914 reader->curnode = reader->curnode->next; 2915 } 2916 return(1); 2917 } 2918 2919 /** 2920 * xmlTextReaderConstEncoding: 2921 * @reader: the xmlTextReaderPtr used 2922 * 2923 * Determine the encoding of the document being read. 2924 * 2925 * Returns a string containing the encoding of the document or NULL in 2926 * case of error. The string is deallocated with the reader. 2927 */ 2928 const xmlChar * 2929 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { 2930 xmlDocPtr doc = NULL; 2931 if (reader == NULL) 2932 return(NULL); 2933 if (reader->doc != NULL) 2934 doc = reader->doc; 2935 else if (reader->ctxt != NULL) 2936 doc = reader->ctxt->myDoc; 2937 if (doc == NULL) 2938 return(NULL); 2939 2940 if (doc->encoding == NULL) 2941 return(NULL); 2942 else 2943 return(CONSTSTR(doc->encoding)); 2944 } 2945 2946 2947 /************************************************************************ 2948 * * 2949 * Acces API to the current node * 2950 * * 2951 ************************************************************************/ 2952 /** 2953 * xmlTextReaderAttributeCount: 2954 * @reader: the xmlTextReaderPtr used 2955 * 2956 * Provides the number of attributes of the current node 2957 * 2958 * Returns 0 i no attributes, -1 in case of error or the attribute count 2959 */ 2960 int 2961 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) { 2962 int ret; 2963 xmlAttrPtr attr; 2964 xmlNsPtr ns; 2965 xmlNodePtr node; 2966 2967 if (reader == NULL) 2968 return(-1); 2969 if (reader->node == NULL) 2970 return(0); 2971 2972 if (reader->curnode != NULL) 2973 node = reader->curnode; 2974 else 2975 node = reader->node; 2976 2977 if (node->type != XML_ELEMENT_NODE) 2978 return(0); 2979 if ((reader->state == XML_TEXTREADER_END) || 2980 (reader->state == XML_TEXTREADER_BACKTRACK)) 2981 return(0); 2982 ret = 0; 2983 attr = node->properties; 2984 while (attr != NULL) { 2985 ret++; 2986 attr = attr->next; 2987 } 2988 ns = node->nsDef; 2989 while (ns != NULL) { 2990 ret++; 2991 ns = ns->next; 2992 } 2993 return(ret); 2994 } 2995 2996 /** 2997 * xmlTextReaderNodeType: 2998 * @reader: the xmlTextReaderPtr used 2999 * 3000 * Get the node type of the current node 3001 * Reference: 3002 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html 3003 * 3004 * Returns the xmlNodeType of the current node or -1 in case of error 3005 */ 3006 int 3007 xmlTextReaderNodeType(xmlTextReaderPtr reader) { 3008 xmlNodePtr node; 3009 3010 if (reader == NULL) 3011 return(-1); 3012 if (reader->node == NULL) 3013 return(XML_READER_TYPE_NONE); 3014 if (reader->curnode != NULL) 3015 node = reader->curnode; 3016 else 3017 node = reader->node; 3018 switch (node->type) { 3019 case XML_ELEMENT_NODE: 3020 if ((reader->state == XML_TEXTREADER_END) || 3021 (reader->state == XML_TEXTREADER_BACKTRACK)) 3022 return(XML_READER_TYPE_END_ELEMENT); 3023 return(XML_READER_TYPE_ELEMENT); 3024 case XML_NAMESPACE_DECL: 3025 case XML_ATTRIBUTE_NODE: 3026 return(XML_READER_TYPE_ATTRIBUTE); 3027 case XML_TEXT_NODE: 3028 if (xmlIsBlankNode(reader->node)) { 3029 if (xmlNodeGetSpacePreserve(reader->node)) 3030 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE); 3031 else 3032 return(XML_READER_TYPE_WHITESPACE); 3033 } else { 3034 return(XML_READER_TYPE_TEXT); 3035 } 3036 case XML_CDATA_SECTION_NODE: 3037 return(XML_READER_TYPE_CDATA); 3038 case XML_ENTITY_REF_NODE: 3039 return(XML_READER_TYPE_ENTITY_REFERENCE); 3040 case XML_ENTITY_NODE: 3041 return(XML_READER_TYPE_ENTITY); 3042 case XML_PI_NODE: 3043 return(XML_READER_TYPE_PROCESSING_INSTRUCTION); 3044 case XML_COMMENT_NODE: 3045 return(XML_READER_TYPE_COMMENT); 3046 case XML_DOCUMENT_NODE: 3047 case XML_HTML_DOCUMENT_NODE: 3048 #ifdef LIBXML_DOCB_ENABLED 3049 case XML_DOCB_DOCUMENT_NODE: 3050 #endif 3051 return(XML_READER_TYPE_DOCUMENT); 3052 case XML_DOCUMENT_FRAG_NODE: 3053 return(XML_READER_TYPE_DOCUMENT_FRAGMENT); 3054 case XML_NOTATION_NODE: 3055 return(XML_READER_TYPE_NOTATION); 3056 case XML_DOCUMENT_TYPE_NODE: 3057 case XML_DTD_NODE: 3058 return(XML_READER_TYPE_DOCUMENT_TYPE); 3059 3060 case XML_ELEMENT_DECL: 3061 case XML_ATTRIBUTE_DECL: 3062 case XML_ENTITY_DECL: 3063 case XML_XINCLUDE_START: 3064 case XML_XINCLUDE_END: 3065 return(XML_READER_TYPE_NONE); 3066 } 3067 return(-1); 3068 } 3069 3070 /** 3071 * xmlTextReaderIsEmptyElement: 3072 * @reader: the xmlTextReaderPtr used 3073 * 3074 * Check if the current node is empty 3075 * 3076 * Returns 1 if empty, 0 if not and -1 in case of error 3077 */ 3078 int 3079 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) { 3080 if ((reader == NULL) || (reader->node == NULL)) 3081 return(-1); 3082 if (reader->node->type != XML_ELEMENT_NODE) 3083 return(0); 3084 if (reader->curnode != NULL) 3085 return(0); 3086 if (reader->node->children != NULL) 3087 return(0); 3088 if (reader->state == XML_TEXTREADER_END) 3089 return(0); 3090 if (reader->doc != NULL) 3091 return(1); 3092 #ifdef LIBXML_XINCLUDE_ENABLED 3093 if (reader->in_xinclude > 0) 3094 return(1); 3095 #endif 3096 return((reader->node->extra & NODE_IS_EMPTY) != 0); 3097 } 3098 3099 /** 3100 * xmlTextReaderLocalName: 3101 * @reader: the xmlTextReaderPtr used 3102 * 3103 * The local name of the node. 3104 * 3105 * Returns the local name or NULL if not available, 3106 * if non NULL it need to be freed by the caller. 3107 */ 3108 xmlChar * 3109 xmlTextReaderLocalName(xmlTextReaderPtr reader) { 3110 xmlNodePtr node; 3111 if ((reader == NULL) || (reader->node == NULL)) 3112 return(NULL); 3113 if (reader->curnode != NULL) 3114 node = reader->curnode; 3115 else 3116 node = reader->node; 3117 if (node->type == XML_NAMESPACE_DECL) { 3118 xmlNsPtr ns = (xmlNsPtr) node; 3119 if (ns->prefix == NULL) 3120 return(xmlStrdup(BAD_CAST "xmlns")); 3121 else 3122 return(xmlStrdup(ns->prefix)); 3123 } 3124 if ((node->type != XML_ELEMENT_NODE) && 3125 (node->type != XML_ATTRIBUTE_NODE)) 3126 return(xmlTextReaderName(reader)); 3127 return(xmlStrdup(node->name)); 3128 } 3129 3130 /** 3131 * xmlTextReaderConstLocalName: 3132 * @reader: the xmlTextReaderPtr used 3133 * 3134 * The local name of the node. 3135 * 3136 * Returns the local name or NULL if not available, the 3137 * string will be deallocated with the reader. 3138 */ 3139 const xmlChar * 3140 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { 3141 xmlNodePtr node; 3142 if ((reader == NULL) || (reader->node == NULL)) 3143 return(NULL); 3144 if (reader->curnode != NULL) 3145 node = reader->curnode; 3146 else 3147 node = reader->node; 3148 if (node->type == XML_NAMESPACE_DECL) { 3149 xmlNsPtr ns = (xmlNsPtr) node; 3150 if (ns->prefix == NULL) 3151 return(CONSTSTR(BAD_CAST "xmlns")); 3152 else 3153 return(ns->prefix); 3154 } 3155 if ((node->type != XML_ELEMENT_NODE) && 3156 (node->type != XML_ATTRIBUTE_NODE)) 3157 return(xmlTextReaderConstName(reader)); 3158 return(node->name); 3159 } 3160 3161 /** 3162 * xmlTextReaderName: 3163 * @reader: the xmlTextReaderPtr used 3164 * 3165 * The qualified name of the node, equal to Prefix :LocalName. 3166 * 3167 * Returns the local name or NULL if not available, 3168 * if non NULL it need to be freed by the caller. 3169 */ 3170 xmlChar * 3171 xmlTextReaderName(xmlTextReaderPtr reader) { 3172 xmlNodePtr node; 3173 xmlChar *ret; 3174 3175 if ((reader == NULL) || (reader->node == NULL)) 3176 return(NULL); 3177 if (reader->curnode != NULL) 3178 node = reader->curnode; 3179 else 3180 node = reader->node; 3181 switch (node->type) { 3182 case XML_ELEMENT_NODE: 3183 case XML_ATTRIBUTE_NODE: 3184 if ((node->ns == NULL) || 3185 (node->ns->prefix == NULL)) 3186 return(xmlStrdup(node->name)); 3187 3188 ret = xmlStrdup(node->ns->prefix); 3189 ret = xmlStrcat(ret, BAD_CAST ":"); 3190 ret = xmlStrcat(ret, node->name); 3191 return(ret); 3192 case XML_TEXT_NODE: 3193 return(xmlStrdup(BAD_CAST "#text")); 3194 case XML_CDATA_SECTION_NODE: 3195 return(xmlStrdup(BAD_CAST "#cdata-section")); 3196 case XML_ENTITY_NODE: 3197 case XML_ENTITY_REF_NODE: 3198 return(xmlStrdup(node->name)); 3199 case XML_PI_NODE: 3200 return(xmlStrdup(node->name)); 3201 case XML_COMMENT_NODE: 3202 return(xmlStrdup(BAD_CAST "#comment")); 3203 case XML_DOCUMENT_NODE: 3204 case XML_HTML_DOCUMENT_NODE: 3205 #ifdef LIBXML_DOCB_ENABLED 3206 case XML_DOCB_DOCUMENT_NODE: 3207 #endif 3208 return(xmlStrdup(BAD_CAST "#document")); 3209 case XML_DOCUMENT_FRAG_NODE: 3210 return(xmlStrdup(BAD_CAST "#document-fragment")); 3211 case XML_NOTATION_NODE: 3212 return(xmlStrdup(node->name)); 3213 case XML_DOCUMENT_TYPE_NODE: 3214 case XML_DTD_NODE: 3215 return(xmlStrdup(node->name)); 3216 case XML_NAMESPACE_DECL: { 3217 xmlNsPtr ns = (xmlNsPtr) node; 3218 3219 ret = xmlStrdup(BAD_CAST "xmlns"); 3220 if (ns->prefix == NULL) 3221 return(ret); 3222 ret = xmlStrcat(ret, BAD_CAST ":"); 3223 ret = xmlStrcat(ret, ns->prefix); 3224 return(ret); 3225 } 3226 3227 case XML_ELEMENT_DECL: 3228 case XML_ATTRIBUTE_DECL: 3229 case XML_ENTITY_DECL: 3230 case XML_XINCLUDE_START: 3231 case XML_XINCLUDE_END: 3232 return(NULL); 3233 } 3234 return(NULL); 3235 } 3236 3237 /** 3238 * xmlTextReaderConstName: 3239 * @reader: the xmlTextReaderPtr used 3240 * 3241 * The qualified name of the node, equal to Prefix :LocalName. 3242 * 3243 * Returns the local name or NULL if not available, the string is 3244 * deallocated with the reader. 3245 */ 3246 const xmlChar * 3247 xmlTextReaderConstName(xmlTextReaderPtr reader) { 3248 xmlNodePtr node; 3249 3250 if ((reader == NULL) || (reader->node == NULL)) 3251 return(NULL); 3252 if (reader->curnode != NULL) 3253 node = reader->curnode; 3254 else 3255 node = reader->node; 3256 switch (node->type) { 3257 case XML_ELEMENT_NODE: 3258 case XML_ATTRIBUTE_NODE: 3259 if ((node->ns == NULL) || 3260 (node->ns->prefix == NULL)) 3261 return(node->name); 3262 return(CONSTQSTR(node->ns->prefix, node->name)); 3263 case XML_TEXT_NODE: 3264 return(CONSTSTR(BAD_CAST "#text")); 3265 case XML_CDATA_SECTION_NODE: 3266 return(CONSTSTR(BAD_CAST "#cdata-section")); 3267 case XML_ENTITY_NODE: 3268 case XML_ENTITY_REF_NODE: 3269 return(CONSTSTR(node->name)); 3270 case XML_PI_NODE: 3271 return(CONSTSTR(node->name)); 3272 case XML_COMMENT_NODE: 3273 return(CONSTSTR(BAD_CAST "#comment")); 3274 case XML_DOCUMENT_NODE: 3275 case XML_HTML_DOCUMENT_NODE: 3276 #ifdef LIBXML_DOCB_ENABLED 3277 case XML_DOCB_DOCUMENT_NODE: 3278 #endif 3279 return(CONSTSTR(BAD_CAST "#document")); 3280 case XML_DOCUMENT_FRAG_NODE: 3281 return(CONSTSTR(BAD_CAST "#document-fragment")); 3282 case XML_NOTATION_NODE: 3283 return(CONSTSTR(node->name)); 3284 case XML_DOCUMENT_TYPE_NODE: 3285 case XML_DTD_NODE: 3286 return(CONSTSTR(node->name)); 3287 case XML_NAMESPACE_DECL: { 3288 xmlNsPtr ns = (xmlNsPtr) node; 3289 3290 if (ns->prefix == NULL) 3291 return(CONSTSTR(BAD_CAST "xmlns")); 3292 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); 3293 } 3294 3295 case XML_ELEMENT_DECL: 3296 case XML_ATTRIBUTE_DECL: 3297 case XML_ENTITY_DECL: 3298 case XML_XINCLUDE_START: 3299 case XML_XINCLUDE_END: 3300 return(NULL); 3301 } 3302 return(NULL); 3303 } 3304 3305 /** 3306 * xmlTextReaderPrefix: 3307 * @reader: the xmlTextReaderPtr used 3308 * 3309 * A shorthand reference to the namespace associated with the node. 3310 * 3311 * Returns the prefix or NULL if not available, 3312 * if non NULL it need to be freed by the caller. 3313 */ 3314 xmlChar * 3315 xmlTextReaderPrefix(xmlTextReaderPtr reader) { 3316 xmlNodePtr node; 3317 if ((reader == NULL) || (reader->node == NULL)) 3318 return(NULL); 3319 if (reader->curnode != NULL) 3320 node = reader->curnode; 3321 else 3322 node = reader->node; 3323 if (node->type == XML_NAMESPACE_DECL) { 3324 xmlNsPtr ns = (xmlNsPtr) node; 3325 if (ns->prefix == NULL) 3326 return(NULL); 3327 return(xmlStrdup(BAD_CAST "xmlns")); 3328 } 3329 if ((node->type != XML_ELEMENT_NODE) && 3330 (node->type != XML_ATTRIBUTE_NODE)) 3331 return(NULL); 3332 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 3333 return(xmlStrdup(node->ns->prefix)); 3334 return(NULL); 3335 } 3336 3337 /** 3338 * xmlTextReaderConstPrefix: 3339 * @reader: the xmlTextReaderPtr used 3340 * 3341 * A shorthand reference to the namespace associated with the node. 3342 * 3343 * Returns the prefix or NULL if not available, the string is deallocated 3344 * with the reader. 3345 */ 3346 const xmlChar * 3347 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { 3348 xmlNodePtr node; 3349 if ((reader == NULL) || (reader->node == NULL)) 3350 return(NULL); 3351 if (reader->curnode != NULL) 3352 node = reader->curnode; 3353 else 3354 node = reader->node; 3355 if (node->type == XML_NAMESPACE_DECL) { 3356 xmlNsPtr ns = (xmlNsPtr) node; 3357 if (ns->prefix == NULL) 3358 return(NULL); 3359 return(CONSTSTR(BAD_CAST "xmlns")); 3360 } 3361 if ((node->type != XML_ELEMENT_NODE) && 3362 (node->type != XML_ATTRIBUTE_NODE)) 3363 return(NULL); 3364 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 3365 return(CONSTSTR(node->ns->prefix)); 3366 return(NULL); 3367 } 3368 3369 /** 3370 * xmlTextReaderNamespaceUri: 3371 * @reader: the xmlTextReaderPtr used 3372 * 3373 * The URI defining the namespace associated with the node. 3374 * 3375 * Returns the namespace URI or NULL if not available, 3376 * if non NULL it need to be freed by the caller. 3377 */ 3378 xmlChar * 3379 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { 3380 xmlNodePtr node; 3381 if ((reader == NULL) || (reader->node == NULL)) 3382 return(NULL); 3383 if (reader->curnode != NULL) 3384 node = reader->curnode; 3385 else 3386 node = reader->node; 3387 if (node->type == XML_NAMESPACE_DECL) 3388 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3389 if ((node->type != XML_ELEMENT_NODE) && 3390 (node->type != XML_ATTRIBUTE_NODE)) 3391 return(NULL); 3392 if (node->ns != NULL) 3393 return(xmlStrdup(node->ns->href)); 3394 return(NULL); 3395 } 3396 3397 /** 3398 * xmlTextReaderConstNamespaceUri: 3399 * @reader: the xmlTextReaderPtr used 3400 * 3401 * The URI defining the namespace associated with the node. 3402 * 3403 * Returns the namespace URI or NULL if not available, the string 3404 * will be deallocated with the reader 3405 */ 3406 const xmlChar * 3407 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { 3408 xmlNodePtr node; 3409 if ((reader == NULL) || (reader->node == NULL)) 3410 return(NULL); 3411 if (reader->curnode != NULL) 3412 node = reader->curnode; 3413 else 3414 node = reader->node; 3415 if (node->type == XML_NAMESPACE_DECL) 3416 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3417 if ((node->type != XML_ELEMENT_NODE) && 3418 (node->type != XML_ATTRIBUTE_NODE)) 3419 return(NULL); 3420 if (node->ns != NULL) 3421 return(CONSTSTR(node->ns->href)); 3422 return(NULL); 3423 } 3424 3425 /** 3426 * xmlTextReaderBaseUri: 3427 * @reader: the xmlTextReaderPtr used 3428 * 3429 * The base URI of the node. 3430 * 3431 * Returns the base URI or NULL if not available, 3432 * if non NULL it need to be freed by the caller. 3433 */ 3434 xmlChar * 3435 xmlTextReaderBaseUri(xmlTextReaderPtr reader) { 3436 if ((reader == NULL) || (reader->node == NULL)) 3437 return(NULL); 3438 return(xmlNodeGetBase(NULL, reader->node)); 3439 } 3440 3441 /** 3442 * xmlTextReaderConstBaseUri: 3443 * @reader: the xmlTextReaderPtr used 3444 * 3445 * The base URI of the node. 3446 * 3447 * Returns the base URI or NULL if not available, the string 3448 * will be deallocated with the reader 3449 */ 3450 const xmlChar * 3451 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { 3452 xmlChar *tmp; 3453 const xmlChar *ret; 3454 3455 if ((reader == NULL) || (reader->node == NULL)) 3456 return(NULL); 3457 tmp = xmlNodeGetBase(NULL, reader->node); 3458 if (tmp == NULL) 3459 return(NULL); 3460 ret = CONSTSTR(tmp); 3461 xmlFree(tmp); 3462 return(ret); 3463 } 3464 3465 /** 3466 * xmlTextReaderDepth: 3467 * @reader: the xmlTextReaderPtr used 3468 * 3469 * The depth of the node in the tree. 3470 * 3471 * Returns the depth or -1 in case of error 3472 */ 3473 int 3474 xmlTextReaderDepth(xmlTextReaderPtr reader) { 3475 if (reader == NULL) 3476 return(-1); 3477 if (reader->node == NULL) 3478 return(0); 3479 3480 if (reader->curnode != NULL) { 3481 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) || 3482 (reader->curnode->type == XML_NAMESPACE_DECL)) 3483 return(reader->depth + 1); 3484 return(reader->depth + 2); 3485 } 3486 return(reader->depth); 3487 } 3488 3489 /** 3490 * xmlTextReaderHasAttributes: 3491 * @reader: the xmlTextReaderPtr used 3492 * 3493 * Whether the node has attributes. 3494 * 3495 * Returns 1 if true, 0 if false, and -1 in case or error 3496 */ 3497 int 3498 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) { 3499 xmlNodePtr node; 3500 if (reader == NULL) 3501 return(-1); 3502 if (reader->node == NULL) 3503 return(0); 3504 if (reader->curnode != NULL) 3505 node = reader->curnode; 3506 else 3507 node = reader->node; 3508 3509 if ((node->type == XML_ELEMENT_NODE) && 3510 ((node->properties != NULL) || (node->nsDef != NULL))) 3511 return(1); 3512 /* TODO: handle the xmlDecl */ 3513 return(0); 3514 } 3515 3516 /** 3517 * xmlTextReaderHasValue: 3518 * @reader: the xmlTextReaderPtr used 3519 * 3520 * Whether the node can have a text value. 3521 * 3522 * Returns 1 if true, 0 if false, and -1 in case or error 3523 */ 3524 int 3525 xmlTextReaderHasValue(xmlTextReaderPtr reader) { 3526 xmlNodePtr node; 3527 if (reader == NULL) 3528 return(-1); 3529 if (reader->node == NULL) 3530 return(0); 3531 if (reader->curnode != NULL) 3532 node = reader->curnode; 3533 else 3534 node = reader->node; 3535 3536 switch (node->type) { 3537 case XML_ATTRIBUTE_NODE: 3538 case XML_TEXT_NODE: 3539 case XML_CDATA_SECTION_NODE: 3540 case XML_PI_NODE: 3541 case XML_COMMENT_NODE: 3542 case XML_NAMESPACE_DECL: 3543 return(1); 3544 default: 3545 break; 3546 } 3547 return(0); 3548 } 3549 3550 /** 3551 * xmlTextReaderValue: 3552 * @reader: the xmlTextReaderPtr used 3553 * 3554 * Provides the text value of the node if present 3555 * 3556 * Returns the string or NULL if not available. The result must be deallocated 3557 * with xmlFree() 3558 */ 3559 xmlChar * 3560 xmlTextReaderValue(xmlTextReaderPtr reader) { 3561 xmlNodePtr node; 3562 if (reader == NULL) 3563 return(NULL); 3564 if (reader->node == NULL) 3565 return(NULL); 3566 if (reader->curnode != NULL) 3567 node = reader->curnode; 3568 else 3569 node = reader->node; 3570 3571 switch (node->type) { 3572 case XML_NAMESPACE_DECL: 3573 return(xmlStrdup(((xmlNsPtr) node)->href)); 3574 case XML_ATTRIBUTE_NODE:{ 3575 xmlAttrPtr attr = (xmlAttrPtr) node; 3576 3577 if (attr->parent != NULL) 3578 return (xmlNodeListGetString 3579 (attr->parent->doc, attr->children, 1)); 3580 else 3581 return (xmlNodeListGetString(NULL, attr->children, 1)); 3582 break; 3583 } 3584 case XML_TEXT_NODE: 3585 case XML_CDATA_SECTION_NODE: 3586 case XML_PI_NODE: 3587 case XML_COMMENT_NODE: 3588 if (node->content != NULL) 3589 return (xmlStrdup(node->content)); 3590 default: 3591 break; 3592 } 3593 return(NULL); 3594 } 3595 3596 /** 3597 * xmlTextReaderConstValue: 3598 * @reader: the xmlTextReaderPtr used 3599 * 3600 * Provides the text value of the node if present 3601 * 3602 * Returns the string or NULL if not available. The result will be 3603 * deallocated on the next Read() operation. 3604 */ 3605 const xmlChar * 3606 xmlTextReaderConstValue(xmlTextReaderPtr reader) { 3607 xmlNodePtr node; 3608 if (reader == NULL) 3609 return(NULL); 3610 if (reader->node == NULL) 3611 return(NULL); 3612 if (reader->curnode != NULL) 3613 node = reader->curnode; 3614 else 3615 node = reader->node; 3616 3617 switch (node->type) { 3618 case XML_NAMESPACE_DECL: 3619 return(((xmlNsPtr) node)->href); 3620 case XML_ATTRIBUTE_NODE:{ 3621 xmlAttrPtr attr = (xmlAttrPtr) node; 3622 const xmlChar *ret; 3623 3624 if ((attr->children != NULL) && 3625 (attr->children->type == XML_TEXT_NODE) && 3626 (attr->children->next == NULL)) 3627 return(attr->children->content); 3628 else { 3629 if (reader->buffer == NULL) { 3630 reader->buffer = xmlBufCreateSize(100); 3631 if (reader->buffer == NULL) { 3632 xmlGenericError(xmlGenericErrorContext, 3633 "xmlTextReaderSetup : malloc failed\n"); 3634 return (NULL); 3635 } 3636 xmlBufSetAllocationScheme(reader->buffer, 3637 XML_BUFFER_ALLOC_BOUNDED); 3638 } else 3639 xmlBufEmpty(reader->buffer); 3640 xmlBufGetNodeContent(reader->buffer, node); 3641 ret = xmlBufContent(reader->buffer); 3642 if (ret == NULL) { 3643 /* error on the buffer best to reallocate */ 3644 xmlBufFree(reader->buffer); 3645 reader->buffer = xmlBufCreateSize(100); 3646 xmlBufSetAllocationScheme(reader->buffer, 3647 XML_BUFFER_ALLOC_BOUNDED); 3648 ret = BAD_CAST ""; 3649 } 3650 return(ret); 3651 } 3652 break; 3653 } 3654 case XML_TEXT_NODE: 3655 case XML_CDATA_SECTION_NODE: 3656 case XML_PI_NODE: 3657 case XML_COMMENT_NODE: 3658 return(node->content); 3659 default: 3660 break; 3661 } 3662 return(NULL); 3663 } 3664 3665 /** 3666 * xmlTextReaderIsDefault: 3667 * @reader: the xmlTextReaderPtr used 3668 * 3669 * Whether an Attribute node was generated from the default value 3670 * defined in the DTD or schema. 3671 * 3672 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error 3673 */ 3674 int 3675 xmlTextReaderIsDefault(xmlTextReaderPtr reader) { 3676 if (reader == NULL) 3677 return(-1); 3678 return(0); 3679 } 3680 3681 /** 3682 * xmlTextReaderQuoteChar: 3683 * @reader: the xmlTextReaderPtr used 3684 * 3685 * The quotation mark character used to enclose the value of an attribute. 3686 * 3687 * Returns " or ' and -1 in case of error 3688 */ 3689 int 3690 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) { 3691 if (reader == NULL) 3692 return(-1); 3693 /* TODO maybe lookup the attribute value for " first */ 3694 return((int) '"'); 3695 } 3696 3697 /** 3698 * xmlTextReaderXmlLang: 3699 * @reader: the xmlTextReaderPtr used 3700 * 3701 * The xml:lang scope within which the node resides. 3702 * 3703 * Returns the xml:lang value or NULL if none exists., 3704 * if non NULL it need to be freed by the caller. 3705 */ 3706 xmlChar * 3707 xmlTextReaderXmlLang(xmlTextReaderPtr reader) { 3708 if (reader == NULL) 3709 return(NULL); 3710 if (reader->node == NULL) 3711 return(NULL); 3712 return(xmlNodeGetLang(reader->node)); 3713 } 3714 3715 /** 3716 * xmlTextReaderConstXmlLang: 3717 * @reader: the xmlTextReaderPtr used 3718 * 3719 * The xml:lang scope within which the node resides. 3720 * 3721 * Returns the xml:lang value or NULL if none exists. 3722 */ 3723 const xmlChar * 3724 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { 3725 xmlChar *tmp; 3726 const xmlChar *ret; 3727 3728 if (reader == NULL) 3729 return(NULL); 3730 if (reader->node == NULL) 3731 return(NULL); 3732 tmp = xmlNodeGetLang(reader->node); 3733 if (tmp == NULL) 3734 return(NULL); 3735 ret = CONSTSTR(tmp); 3736 xmlFree(tmp); 3737 return(ret); 3738 } 3739 3740 /** 3741 * xmlTextReaderConstString: 3742 * @reader: the xmlTextReaderPtr used 3743 * @str: the string to intern. 3744 * 3745 * Get an interned string from the reader, allows for example to 3746 * speedup string name comparisons 3747 * 3748 * Returns an interned copy of the string or NULL in case of error. The 3749 * string will be deallocated with the reader. 3750 */ 3751 const xmlChar * 3752 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { 3753 if (reader == NULL) 3754 return(NULL); 3755 return(CONSTSTR(str)); 3756 } 3757 3758 /** 3759 * xmlTextReaderNormalization: 3760 * @reader: the xmlTextReaderPtr used 3761 * 3762 * The value indicating whether to normalize white space and attribute values. 3763 * Since attribute value and end of line normalizations are a MUST in the XML 3764 * specification only the value true is accepted. The broken bahaviour of 3765 * accepting out of range character entities like � is of course not 3766 * supported either. 3767 * 3768 * Returns 1 or -1 in case of error. 3769 */ 3770 int 3771 xmlTextReaderNormalization(xmlTextReaderPtr reader) { 3772 if (reader == NULL) 3773 return(-1); 3774 return(1); 3775 } 3776 3777 /************************************************************************ 3778 * * 3779 * Extensions to the base APIs * 3780 * * 3781 ************************************************************************/ 3782 3783 /** 3784 * xmlTextReaderSetParserProp: 3785 * @reader: the xmlTextReaderPtr used 3786 * @prop: the xmlParserProperties to set 3787 * @value: usually 0 or 1 to (de)activate it 3788 * 3789 * Change the parser processing behaviour by changing some of its internal 3790 * properties. Note that some properties can only be changed before any 3791 * read has been done. 3792 * 3793 * Returns 0 if the call was successful, or -1 in case of error 3794 */ 3795 int 3796 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { 3797 xmlParserProperties p = (xmlParserProperties) prop; 3798 xmlParserCtxtPtr ctxt; 3799 3800 if ((reader == NULL) || (reader->ctxt == NULL)) 3801 return(-1); 3802 ctxt = reader->ctxt; 3803 3804 switch (p) { 3805 case XML_PARSER_LOADDTD: 3806 if (value != 0) { 3807 if (ctxt->loadsubset == 0) { 3808 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 3809 return(-1); 3810 ctxt->loadsubset = XML_DETECT_IDS; 3811 } 3812 } else { 3813 ctxt->loadsubset = 0; 3814 } 3815 return(0); 3816 case XML_PARSER_DEFAULTATTRS: 3817 if (value != 0) { 3818 ctxt->loadsubset |= XML_COMPLETE_ATTRS; 3819 } else { 3820 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3821 ctxt->loadsubset -= XML_COMPLETE_ATTRS; 3822 } 3823 return(0); 3824 case XML_PARSER_VALIDATE: 3825 if (value != 0) { 3826 ctxt->validate = 1; 3827 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 3828 } else { 3829 ctxt->validate = 0; 3830 } 3831 return(0); 3832 case XML_PARSER_SUBST_ENTITIES: 3833 if (value != 0) { 3834 ctxt->replaceEntities = 1; 3835 } else { 3836 ctxt->replaceEntities = 0; 3837 } 3838 return(0); 3839 } 3840 return(-1); 3841 } 3842 3843 /** 3844 * xmlTextReaderGetParserProp: 3845 * @reader: the xmlTextReaderPtr used 3846 * @prop: the xmlParserProperties to get 3847 * 3848 * Read the parser internal property. 3849 * 3850 * Returns the value, usually 0 or 1, or -1 in case of error. 3851 */ 3852 int 3853 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) { 3854 xmlParserProperties p = (xmlParserProperties) prop; 3855 xmlParserCtxtPtr ctxt; 3856 3857 if ((reader == NULL) || (reader->ctxt == NULL)) 3858 return(-1); 3859 ctxt = reader->ctxt; 3860 3861 switch (p) { 3862 case XML_PARSER_LOADDTD: 3863 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0)) 3864 return(1); 3865 return(0); 3866 case XML_PARSER_DEFAULTATTRS: 3867 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3868 return(1); 3869 return(0); 3870 case XML_PARSER_VALIDATE: 3871 return(reader->validate); 3872 case XML_PARSER_SUBST_ENTITIES: 3873 return(ctxt->replaceEntities); 3874 } 3875 return(-1); 3876 } 3877 3878 3879 /** 3880 * xmlTextReaderGetParserLineNumber: 3881 * @reader: the user data (XML reader context) 3882 * 3883 * Provide the line number of the current parsing point. 3884 * 3885 * Returns an int or 0 if not available 3886 */ 3887 int 3888 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader) 3889 { 3890 if ((reader == NULL) || (reader->ctxt == NULL) || 3891 (reader->ctxt->input == NULL)) { 3892 return (0); 3893 } 3894 return (reader->ctxt->input->line); 3895 } 3896 3897 /** 3898 * xmlTextReaderGetParserColumnNumber: 3899 * @reader: the user data (XML reader context) 3900 * 3901 * Provide the column number of the current parsing point. 3902 * 3903 * Returns an int or 0 if not available 3904 */ 3905 int 3906 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader) 3907 { 3908 if ((reader == NULL) || (reader->ctxt == NULL) || 3909 (reader->ctxt->input == NULL)) { 3910 return (0); 3911 } 3912 return (reader->ctxt->input->col); 3913 } 3914 3915 /** 3916 * xmlTextReaderCurrentNode: 3917 * @reader: the xmlTextReaderPtr used 3918 * 3919 * Hacking interface allowing to get the xmlNodePtr correponding to the 3920 * current node being accessed by the xmlTextReader. This is dangerous 3921 * because the underlying node may be destroyed on the next Reads. 3922 * 3923 * Returns the xmlNodePtr or NULL in case of error. 3924 */ 3925 xmlNodePtr 3926 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) { 3927 if (reader == NULL) 3928 return(NULL); 3929 3930 if (reader->curnode != NULL) 3931 return(reader->curnode); 3932 return(reader->node); 3933 } 3934 3935 /** 3936 * xmlTextReaderPreserve: 3937 * @reader: the xmlTextReaderPtr used 3938 * 3939 * This tells the XML Reader to preserve the current node. 3940 * The caller must also use xmlTextReaderCurrentDoc() to 3941 * keep an handle on the resulting document once parsing has finished 3942 * 3943 * Returns the xmlNodePtr or NULL in case of error. 3944 */ 3945 xmlNodePtr 3946 xmlTextReaderPreserve(xmlTextReaderPtr reader) { 3947 xmlNodePtr cur, parent; 3948 3949 if (reader == NULL) 3950 return(NULL); 3951 3952 if (reader->curnode != NULL) 3953 cur = reader->curnode; 3954 else 3955 cur = reader->node; 3956 if (cur == NULL) 3957 return(NULL); 3958 3959 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) { 3960 cur->extra |= NODE_IS_PRESERVED; 3961 cur->extra |= NODE_IS_SPRESERVED; 3962 } 3963 reader->preserves++; 3964 3965 parent = cur->parent;; 3966 while (parent != NULL) { 3967 if (parent->type == XML_ELEMENT_NODE) 3968 parent->extra |= NODE_IS_PRESERVED; 3969 parent = parent->parent; 3970 } 3971 return(cur); 3972 } 3973 3974 #ifdef LIBXML_PATTERN_ENABLED 3975 /** 3976 * xmlTextReaderPreservePattern: 3977 * @reader: the xmlTextReaderPtr used 3978 * @pattern: an XPath subset pattern 3979 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL 3980 * 3981 * This tells the XML Reader to preserve all nodes matched by the 3982 * pattern. The caller must also use xmlTextReaderCurrentDoc() to 3983 * keep an handle on the resulting document once parsing has finished 3984 * 3985 * Returns a non-negative number in case of success and -1 in case of error 3986 */ 3987 int 3988 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, 3989 const xmlChar **namespaces) 3990 { 3991 xmlPatternPtr comp; 3992 3993 if ((reader == NULL) || (pattern == NULL)) 3994 return(-1); 3995 3996 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces); 3997 if (comp == NULL) 3998 return(-1); 3999 4000 if (reader->patternMax <= 0) { 4001 reader->patternMax = 4; 4002 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * 4003 sizeof(reader->patternTab[0])); 4004 if (reader->patternTab == NULL) { 4005 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 4006 return (-1); 4007 } 4008 } 4009 if (reader->patternNr >= reader->patternMax) { 4010 xmlPatternPtr *tmp; 4011 reader->patternMax *= 2; 4012 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab, 4013 reader->patternMax * 4014 sizeof(reader->patternTab[0])); 4015 if (tmp == NULL) { 4016 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 4017 reader->patternMax /= 2; 4018 return (-1); 4019 } 4020 reader->patternTab = tmp; 4021 } 4022 reader->patternTab[reader->patternNr] = comp; 4023 return(reader->patternNr++); 4024 } 4025 #endif 4026 4027 /** 4028 * xmlTextReaderCurrentDoc: 4029 * @reader: the xmlTextReaderPtr used 4030 * 4031 * Hacking interface allowing to get the xmlDocPtr correponding to the 4032 * current document being accessed by the xmlTextReader. 4033 * NOTE: as a result of this call, the reader will not destroy the 4034 * associated XML document and calling xmlFreeDoc() on the result 4035 * is needed once the reader parsing has finished. 4036 * 4037 * Returns the xmlDocPtr or NULL in case of error. 4038 */ 4039 xmlDocPtr 4040 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { 4041 if (reader == NULL) 4042 return(NULL); 4043 if (reader->doc != NULL) 4044 return(reader->doc); 4045 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL)) 4046 return(NULL); 4047 4048 reader->preserve = 1; 4049 return(reader->ctxt->myDoc); 4050 } 4051 4052 #ifdef LIBXML_SCHEMAS_ENABLED 4053 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0); 4054 4055 static void XMLCDECL 4056 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4057 4058 static void XMLCDECL 4059 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4060 4061 static void XMLCDECL 4062 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4063 4064 static void XMLCDECL 4065 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4066 4067 static void XMLCDECL 4068 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) 4069 { 4070 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; 4071 4072 char *str; 4073 4074 va_list ap; 4075 4076 va_start(ap, msg); 4077 str = xmlTextReaderBuildMessage(msg, ap); 4078 if (!reader->errorFunc) { 4079 xmlTextReaderValidityError(ctx, "%s", str); 4080 } else { 4081 reader->errorFunc(reader->errorFuncArg, str, 4082 XML_PARSER_SEVERITY_VALIDITY_ERROR, 4083 NULL /* locator */ ); 4084 } 4085 if (str != NULL) 4086 xmlFree(str); 4087 va_end(ap); 4088 } 4089 4090 static void XMLCDECL 4091 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) 4092 { 4093 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; 4094 4095 char *str; 4096 4097 va_list ap; 4098 4099 va_start(ap, msg); 4100 str = xmlTextReaderBuildMessage(msg, ap); 4101 if (!reader->errorFunc) { 4102 xmlTextReaderValidityWarning(ctx, "%s", str); 4103 } else { 4104 reader->errorFunc(reader->errorFuncArg, str, 4105 XML_PARSER_SEVERITY_VALIDITY_WARNING, 4106 NULL /* locator */ ); 4107 } 4108 if (str != NULL) 4109 xmlFree(str); 4110 va_end(ap); 4111 } 4112 4113 static void 4114 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error); 4115 4116 static void 4117 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error) 4118 { 4119 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; 4120 4121 if (reader->sErrorFunc) { 4122 reader->sErrorFunc(reader->errorFuncArg, error); 4123 } else { 4124 xmlTextReaderStructuredError(reader, error); 4125 } 4126 } 4127 /** 4128 * xmlTextReaderRelaxNGSetSchema: 4129 * @reader: the xmlTextReaderPtr used 4130 * @schema: a precompiled RelaxNG schema 4131 * 4132 * Use RelaxNG to validate the document as it is processed. 4133 * Activation is only possible before the first Read(). 4134 * if @schema is NULL, then RelaxNG validation is desactivated. 4135 @ The @schema should not be freed until the reader is deallocated 4136 * or its use has been deactivated. 4137 * 4138 * Returns 0 in case the RelaxNG validation could be (des)activated and 4139 * -1 in case of error. 4140 */ 4141 int 4142 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { 4143 if (reader == NULL) 4144 return(-1); 4145 if (schema == NULL) { 4146 if (reader->rngSchemas != NULL) { 4147 xmlRelaxNGFree(reader->rngSchemas); 4148 reader->rngSchemas = NULL; 4149 } 4150 if (reader->rngValidCtxt != NULL) { 4151 if (! reader->rngPreserveCtxt) 4152 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4153 reader->rngValidCtxt = NULL; 4154 } 4155 reader->rngPreserveCtxt = 0; 4156 return(0); 4157 } 4158 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 4159 return(-1); 4160 if (reader->rngSchemas != NULL) { 4161 xmlRelaxNGFree(reader->rngSchemas); 4162 reader->rngSchemas = NULL; 4163 } 4164 if (reader->rngValidCtxt != NULL) { 4165 if (! reader->rngPreserveCtxt) 4166 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4167 reader->rngValidCtxt = NULL; 4168 } 4169 reader->rngPreserveCtxt = 0; 4170 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); 4171 if (reader->rngValidCtxt == NULL) 4172 return(-1); 4173 if (reader->errorFunc != NULL) { 4174 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4175 xmlTextReaderValidityErrorRelay, 4176 xmlTextReaderValidityWarningRelay, 4177 reader); 4178 } 4179 if (reader->sErrorFunc != NULL) { 4180 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4181 xmlTextReaderValidityStructuredRelay, 4182 reader); 4183 } 4184 reader->rngValidErrors = 0; 4185 reader->rngFullNode = NULL; 4186 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 4187 return(0); 4188 } 4189 4190 /** 4191 * xmlTextReaderLocator: 4192 * @ctx: the xmlTextReaderPtr used 4193 * @file: returned file information 4194 * @line: returned line information 4195 * 4196 * Internal locator function for the readers 4197 * 4198 * Returns 0 in case the Schema validation could be (des)activated and 4199 * -1 in case of error. 4200 */ 4201 static int 4202 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) { 4203 xmlTextReaderPtr reader; 4204 4205 if ((ctx == NULL) || ((file == NULL) && (line == NULL))) 4206 return(-1); 4207 4208 if (file != NULL) 4209 *file = NULL; 4210 if (line != NULL) 4211 *line = 0; 4212 4213 reader = (xmlTextReaderPtr) ctx; 4214 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) { 4215 if (file != NULL) 4216 *file = reader->ctxt->input->filename; 4217 if (line != NULL) 4218 *line = reader->ctxt->input->line; 4219 return(0); 4220 } 4221 if (reader->node != NULL) { 4222 long res; 4223 int ret = 0; 4224 4225 if (line != NULL) { 4226 res = xmlGetLineNo(reader->node); 4227 if (res > 0) 4228 *line = (unsigned long) res; 4229 else 4230 ret = -1; 4231 } 4232 if (file != NULL) { 4233 xmlDocPtr doc = reader->node->doc; 4234 if ((doc != NULL) && (doc->URL != NULL)) 4235 *file = (const char *) doc->URL; 4236 else 4237 ret = -1; 4238 } 4239 return(ret); 4240 } 4241 return(-1); 4242 } 4243 4244 /** 4245 * xmlTextReaderSetSchema: 4246 * @reader: the xmlTextReaderPtr used 4247 * @schema: a precompiled Schema schema 4248 * 4249 * Use XSD Schema to validate the document as it is processed. 4250 * Activation is only possible before the first Read(). 4251 * if @schema is NULL, then Schema validation is desactivated. 4252 @ The @schema should not be freed until the reader is deallocated 4253 * or its use has been deactivated. 4254 * 4255 * Returns 0 in case the Schema validation could be (des)activated and 4256 * -1 in case of error. 4257 */ 4258 int 4259 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { 4260 if (reader == NULL) 4261 return(-1); 4262 if (schema == NULL) { 4263 if (reader->xsdPlug != NULL) { 4264 xmlSchemaSAXUnplug(reader->xsdPlug); 4265 reader->xsdPlug = NULL; 4266 } 4267 if (reader->xsdValidCtxt != NULL) { 4268 if (! reader->xsdPreserveCtxt) 4269 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4270 reader->xsdValidCtxt = NULL; 4271 } 4272 reader->xsdPreserveCtxt = 0; 4273 if (reader->xsdSchemas != NULL) { 4274 xmlSchemaFree(reader->xsdSchemas); 4275 reader->xsdSchemas = NULL; 4276 } 4277 return(0); 4278 } 4279 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 4280 return(-1); 4281 if (reader->xsdPlug != NULL) { 4282 xmlSchemaSAXUnplug(reader->xsdPlug); 4283 reader->xsdPlug = NULL; 4284 } 4285 if (reader->xsdValidCtxt != NULL) { 4286 if (! reader->xsdPreserveCtxt) 4287 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4288 reader->xsdValidCtxt = NULL; 4289 } 4290 reader->xsdPreserveCtxt = 0; 4291 if (reader->xsdSchemas != NULL) { 4292 xmlSchemaFree(reader->xsdSchemas); 4293 reader->xsdSchemas = NULL; 4294 } 4295 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema); 4296 if (reader->xsdValidCtxt == NULL) { 4297 xmlSchemaFree(reader->xsdSchemas); 4298 reader->xsdSchemas = NULL; 4299 return(-1); 4300 } 4301 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4302 &(reader->ctxt->sax), 4303 &(reader->ctxt->userData)); 4304 if (reader->xsdPlug == NULL) { 4305 xmlSchemaFree(reader->xsdSchemas); 4306 reader->xsdSchemas = NULL; 4307 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4308 reader->xsdValidCtxt = NULL; 4309 return(-1); 4310 } 4311 xmlSchemaValidateSetLocator(reader->xsdValidCtxt, 4312 xmlTextReaderLocator, 4313 (void *) reader); 4314 4315 if (reader->errorFunc != NULL) { 4316 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4317 xmlTextReaderValidityErrorRelay, 4318 xmlTextReaderValidityWarningRelay, 4319 reader); 4320 } 4321 if (reader->sErrorFunc != NULL) { 4322 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 4323 xmlTextReaderValidityStructuredRelay, 4324 reader); 4325 } 4326 reader->xsdValidErrors = 0; 4327 reader->validate = XML_TEXTREADER_VALIDATE_XSD; 4328 return(0); 4329 } 4330 4331 /** 4332 * xmlTextReaderRelaxNGValidateInternal: 4333 * @reader: the xmlTextReaderPtr used 4334 * @rng: the path to a RelaxNG schema or NULL 4335 * @ctxt: the RelaxNG schema validation context or NULL 4336 * @options: options (not yet used) 4337 * 4338 * Use RelaxNG to validate the document as it is processed. 4339 * Activation is only possible before the first Read(). 4340 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated. 4341 * 4342 * Returns 0 in case the RelaxNG validation could be (de)activated and 4343 * -1 in case of error. 4344 */ 4345 static int 4346 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, 4347 const char *rng, 4348 xmlRelaxNGValidCtxtPtr ctxt, 4349 int options ATTRIBUTE_UNUSED) 4350 { 4351 if (reader == NULL) 4352 return(-1); 4353 4354 if ((rng != NULL) && (ctxt != NULL)) 4355 return (-1); 4356 4357 if (((rng != NULL) || (ctxt != NULL)) && 4358 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || 4359 (reader->ctxt == NULL))) 4360 return(-1); 4361 4362 /* Cleanup previous validation stuff. */ 4363 if (reader->rngValidCtxt != NULL) { 4364 if ( !reader->rngPreserveCtxt) 4365 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4366 reader->rngValidCtxt = NULL; 4367 } 4368 reader->rngPreserveCtxt = 0; 4369 if (reader->rngSchemas != NULL) { 4370 xmlRelaxNGFree(reader->rngSchemas); 4371 reader->rngSchemas = NULL; 4372 } 4373 4374 if ((rng == NULL) && (ctxt == NULL)) { 4375 /* We just want to deactivate the validation, so get out. */ 4376 return(0); 4377 } 4378 4379 4380 if (rng != NULL) { 4381 xmlRelaxNGParserCtxtPtr pctxt; 4382 /* Parse the schema and create validation environment. */ 4383 4384 pctxt = xmlRelaxNGNewParserCtxt(rng); 4385 if (reader->errorFunc != NULL) { 4386 xmlRelaxNGSetParserErrors(pctxt, 4387 xmlTextReaderValidityErrorRelay, 4388 xmlTextReaderValidityWarningRelay, 4389 reader); 4390 } 4391 if (reader->sErrorFunc != NULL) { 4392 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4393 xmlTextReaderValidityStructuredRelay, 4394 reader); 4395 } 4396 reader->rngSchemas = xmlRelaxNGParse(pctxt); 4397 xmlRelaxNGFreeParserCtxt(pctxt); 4398 if (reader->rngSchemas == NULL) 4399 return(-1); 4400 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); 4401 if (reader->rngValidCtxt == NULL) { 4402 xmlRelaxNGFree(reader->rngSchemas); 4403 reader->rngSchemas = NULL; 4404 return(-1); 4405 } 4406 } else { 4407 /* Use the given validation context. */ 4408 reader->rngValidCtxt = ctxt; 4409 reader->rngPreserveCtxt = 1; 4410 } 4411 /* 4412 * Redirect the validation context's error channels to use 4413 * the reader channels. 4414 * TODO: In case the user provides the validation context we 4415 * could make this redirection optional. 4416 */ 4417 if (reader->errorFunc != NULL) { 4418 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4419 xmlTextReaderValidityErrorRelay, 4420 xmlTextReaderValidityWarningRelay, 4421 reader); 4422 } 4423 if (reader->sErrorFunc != NULL) { 4424 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4425 xmlTextReaderValidityStructuredRelay, 4426 reader); 4427 } 4428 reader->rngValidErrors = 0; 4429 reader->rngFullNode = NULL; 4430 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 4431 return(0); 4432 } 4433 4434 /** 4435 * xmlTextReaderSchemaValidateInternal: 4436 * @reader: the xmlTextReaderPtr used 4437 * @xsd: the path to a W3C XSD schema or NULL 4438 * @ctxt: the XML Schema validation context or NULL 4439 * @options: options (not used yet) 4440 * 4441 * Validate the document as it is processed using XML Schema. 4442 * Activation is only possible before the first Read(). 4443 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated. 4444 * 4445 * Returns 0 in case the schemas validation could be (de)activated and 4446 * -1 in case of error. 4447 */ 4448 static int 4449 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, 4450 const char *xsd, 4451 xmlSchemaValidCtxtPtr ctxt, 4452 int options ATTRIBUTE_UNUSED) 4453 { 4454 if (reader == NULL) 4455 return(-1); 4456 4457 if ((xsd != NULL) && (ctxt != NULL)) 4458 return(-1); 4459 4460 if (((xsd != NULL) || (ctxt != NULL)) && 4461 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || 4462 (reader->ctxt == NULL))) 4463 return(-1); 4464 4465 /* Cleanup previous validation stuff. */ 4466 if (reader->xsdPlug != NULL) { 4467 xmlSchemaSAXUnplug(reader->xsdPlug); 4468 reader->xsdPlug = NULL; 4469 } 4470 if (reader->xsdValidCtxt != NULL) { 4471 if (! reader->xsdPreserveCtxt) 4472 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4473 reader->xsdValidCtxt = NULL; 4474 } 4475 reader->xsdPreserveCtxt = 0; 4476 if (reader->xsdSchemas != NULL) { 4477 xmlSchemaFree(reader->xsdSchemas); 4478 reader->xsdSchemas = NULL; 4479 } 4480 4481 if ((xsd == NULL) && (ctxt == NULL)) { 4482 /* We just want to deactivate the validation, so get out. */ 4483 return(0); 4484 } 4485 4486 if (xsd != NULL) { 4487 xmlSchemaParserCtxtPtr pctxt; 4488 /* Parse the schema and create validation environment. */ 4489 pctxt = xmlSchemaNewParserCtxt(xsd); 4490 if (reader->errorFunc != NULL) { 4491 xmlSchemaSetParserErrors(pctxt, 4492 xmlTextReaderValidityErrorRelay, 4493 xmlTextReaderValidityWarningRelay, 4494 reader); 4495 } 4496 reader->xsdSchemas = xmlSchemaParse(pctxt); 4497 xmlSchemaFreeParserCtxt(pctxt); 4498 if (reader->xsdSchemas == NULL) 4499 return(-1); 4500 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas); 4501 if (reader->xsdValidCtxt == NULL) { 4502 xmlSchemaFree(reader->xsdSchemas); 4503 reader->xsdSchemas = NULL; 4504 return(-1); 4505 } 4506 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4507 &(reader->ctxt->sax), 4508 &(reader->ctxt->userData)); 4509 if (reader->xsdPlug == NULL) { 4510 xmlSchemaFree(reader->xsdSchemas); 4511 reader->xsdSchemas = NULL; 4512 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4513 reader->xsdValidCtxt = NULL; 4514 return(-1); 4515 } 4516 } else { 4517 /* Use the given validation context. */ 4518 reader->xsdValidCtxt = ctxt; 4519 reader->xsdPreserveCtxt = 1; 4520 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4521 &(reader->ctxt->sax), 4522 &(reader->ctxt->userData)); 4523 if (reader->xsdPlug == NULL) { 4524 reader->xsdValidCtxt = NULL; 4525 reader->xsdPreserveCtxt = 0; 4526 return(-1); 4527 } 4528 } 4529 xmlSchemaValidateSetLocator(reader->xsdValidCtxt, 4530 xmlTextReaderLocator, 4531 (void *) reader); 4532 /* 4533 * Redirect the validation context's error channels to use 4534 * the reader channels. 4535 * TODO: In case the user provides the validation context we 4536 * could make this redirection optional. 4537 */ 4538 if (reader->errorFunc != NULL) { 4539 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4540 xmlTextReaderValidityErrorRelay, 4541 xmlTextReaderValidityWarningRelay, 4542 reader); 4543 } 4544 if (reader->sErrorFunc != NULL) { 4545 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 4546 xmlTextReaderValidityStructuredRelay, 4547 reader); 4548 } 4549 reader->xsdValidErrors = 0; 4550 reader->validate = XML_TEXTREADER_VALIDATE_XSD; 4551 return(0); 4552 } 4553 4554 /** 4555 * xmlTextReaderSchemaValidateCtxt: 4556 * @reader: the xmlTextReaderPtr used 4557 * @ctxt: the XML Schema validation context or NULL 4558 * @options: options (not used yet) 4559 * 4560 * Use W3C XSD schema context to validate the document as it is processed. 4561 * Activation is only possible before the first Read(). 4562 * If @ctxt is NULL, then XML Schema validation is deactivated. 4563 * 4564 * Returns 0 in case the schemas validation could be (de)activated and 4565 * -1 in case of error. 4566 */ 4567 int 4568 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, 4569 xmlSchemaValidCtxtPtr ctxt, 4570 int options) 4571 { 4572 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options)); 4573 } 4574 4575 /** 4576 * xmlTextReaderSchemaValidate: 4577 * @reader: the xmlTextReaderPtr used 4578 * @xsd: the path to a W3C XSD schema or NULL 4579 * 4580 * Use W3C XSD schema to validate the document as it is processed. 4581 * Activation is only possible before the first Read(). 4582 * If @xsd is NULL, then XML Schema validation is deactivated. 4583 * 4584 * Returns 0 in case the schemas validation could be (de)activated and 4585 * -1 in case of error. 4586 */ 4587 int 4588 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) 4589 { 4590 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0)); 4591 } 4592 4593 /** 4594 * xmlTextReaderRelaxNGValidateCtxt: 4595 * @reader: the xmlTextReaderPtr used 4596 * @ctxt: the RelaxNG schema validation context or NULL 4597 * @options: options (not used yet) 4598 * 4599 * Use RelaxNG schema context to validate the document as it is processed. 4600 * Activation is only possible before the first Read(). 4601 * If @ctxt is NULL, then RelaxNG schema validation is deactivated. 4602 * 4603 * Returns 0 in case the schemas validation could be (de)activated and 4604 * -1 in case of error. 4605 */ 4606 int 4607 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader, 4608 xmlRelaxNGValidCtxtPtr ctxt, 4609 int options) 4610 { 4611 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options)); 4612 } 4613 4614 /** 4615 * xmlTextReaderRelaxNGValidate: 4616 * @reader: the xmlTextReaderPtr used 4617 * @rng: the path to a RelaxNG schema or NULL 4618 * 4619 * Use RelaxNG schema to validate the document as it is processed. 4620 * Activation is only possible before the first Read(). 4621 * If @rng is NULL, then RelaxNG schema validation is deactivated. 4622 * 4623 * Returns 0 in case the schemas validation could be (de)activated and 4624 * -1 in case of error. 4625 */ 4626 int 4627 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) 4628 { 4629 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0)); 4630 } 4631 4632 #endif 4633 4634 /** 4635 * xmlTextReaderIsNamespaceDecl: 4636 * @reader: the xmlTextReaderPtr used 4637 * 4638 * Determine whether the current node is a namespace declaration 4639 * rather than a regular attribute. 4640 * 4641 * Returns 1 if the current node is a namespace declaration, 0 if it 4642 * is a regular attribute or other type of node, or -1 in case of 4643 * error. 4644 */ 4645 int 4646 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) { 4647 xmlNodePtr node; 4648 if (reader == NULL) 4649 return(-1); 4650 if (reader->node == NULL) 4651 return(-1); 4652 if (reader->curnode != NULL) 4653 node = reader->curnode; 4654 else 4655 node = reader->node; 4656 4657 if (XML_NAMESPACE_DECL == node->type) 4658 return(1); 4659 else 4660 return(0); 4661 } 4662 4663 /** 4664 * xmlTextReaderConstXmlVersion: 4665 * @reader: the xmlTextReaderPtr used 4666 * 4667 * Determine the XML version of the document being read. 4668 * 4669 * Returns a string containing the XML version of the document or NULL 4670 * in case of error. The string is deallocated with the reader. 4671 */ 4672 const xmlChar * 4673 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) { 4674 xmlDocPtr doc = NULL; 4675 if (reader == NULL) 4676 return(NULL); 4677 if (reader->doc != NULL) 4678 doc = reader->doc; 4679 else if (reader->ctxt != NULL) 4680 doc = reader->ctxt->myDoc; 4681 if (doc == NULL) 4682 return(NULL); 4683 4684 if (doc->version == NULL) 4685 return(NULL); 4686 else 4687 return(CONSTSTR(doc->version)); 4688 } 4689 4690 /** 4691 * xmlTextReaderStandalone: 4692 * @reader: the xmlTextReaderPtr used 4693 * 4694 * Determine the standalone status of the document being read. 4695 * 4696 * Returns 1 if the document was declared to be standalone, 0 if it 4697 * was declared to be not standalone, or -1 if the document did not 4698 * specify its standalone status or in case of error. 4699 */ 4700 int 4701 xmlTextReaderStandalone(xmlTextReaderPtr reader) { 4702 xmlDocPtr doc = NULL; 4703 if (reader == NULL) 4704 return(-1); 4705 if (reader->doc != NULL) 4706 doc = reader->doc; 4707 else if (reader->ctxt != NULL) 4708 doc = reader->ctxt->myDoc; 4709 if (doc == NULL) 4710 return(-1); 4711 4712 return(doc->standalone); 4713 } 4714 4715 /************************************************************************ 4716 * * 4717 * Error Handling Extensions * 4718 * * 4719 ************************************************************************/ 4720 4721 /* helper to build a xmlMalloc'ed string from a format and va_list */ 4722 static char * 4723 xmlTextReaderBuildMessage(const char *msg, va_list ap) { 4724 int size = 0; 4725 int chars; 4726 char *larger; 4727 char *str = NULL; 4728 va_list aq; 4729 4730 while (1) { 4731 VA_COPY(aq, ap); 4732 chars = vsnprintf(str, size, msg, aq); 4733 va_end(aq); 4734 if (chars < 0) { 4735 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n"); 4736 if (str) 4737 xmlFree(str); 4738 return NULL; 4739 } 4740 if ((chars < size) || (size == MAX_ERR_MSG_SIZE)) 4741 break; 4742 if (chars < MAX_ERR_MSG_SIZE) 4743 size = chars + 1; 4744 else 4745 size = MAX_ERR_MSG_SIZE; 4746 if ((larger = (char *) xmlRealloc(str, size)) == NULL) { 4747 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 4748 if (str) 4749 xmlFree(str); 4750 return NULL; 4751 } 4752 str = larger; 4753 } 4754 4755 return str; 4756 } 4757 4758 /** 4759 * xmlTextReaderLocatorLineNumber: 4760 * @locator: the xmlTextReaderLocatorPtr used 4761 * 4762 * Obtain the line number for the given locator. 4763 * 4764 * Returns the line number or -1 in case of error. 4765 */ 4766 int 4767 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) { 4768 /* we know that locator is a xmlParserCtxtPtr */ 4769 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 4770 int ret = -1; 4771 4772 if (locator == NULL) 4773 return(-1); 4774 if (ctx->node != NULL) { 4775 ret = xmlGetLineNo(ctx->node); 4776 } 4777 else { 4778 /* inspired from error.c */ 4779 xmlParserInputPtr input; 4780 input = ctx->input; 4781 if ((input->filename == NULL) && (ctx->inputNr > 1)) 4782 input = ctx->inputTab[ctx->inputNr - 2]; 4783 if (input != NULL) { 4784 ret = input->line; 4785 } 4786 else { 4787 ret = -1; 4788 } 4789 } 4790 4791 return ret; 4792 } 4793 4794 /** 4795 * xmlTextReaderLocatorBaseURI: 4796 * @locator: the xmlTextReaderLocatorPtr used 4797 * 4798 * Obtain the base URI for the given locator. 4799 * 4800 * Returns the base URI or NULL in case of error, 4801 * if non NULL it need to be freed by the caller. 4802 */ 4803 xmlChar * 4804 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { 4805 /* we know that locator is a xmlParserCtxtPtr */ 4806 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 4807 xmlChar *ret = NULL; 4808 4809 if (locator == NULL) 4810 return(NULL); 4811 if (ctx->node != NULL) { 4812 ret = xmlNodeGetBase(NULL,ctx->node); 4813 } 4814 else { 4815 /* inspired from error.c */ 4816 xmlParserInputPtr input; 4817 input = ctx->input; 4818 if ((input->filename == NULL) && (ctx->inputNr > 1)) 4819 input = ctx->inputTab[ctx->inputNr - 2]; 4820 if (input != NULL) { 4821 ret = xmlStrdup(BAD_CAST input->filename); 4822 } 4823 else { 4824 ret = NULL; 4825 } 4826 } 4827 4828 return ret; 4829 } 4830 4831 static void 4832 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, 4833 char *str) 4834 { 4835 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; 4836 4837 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; 4838 4839 if (str != NULL) { 4840 if (reader->errorFunc) 4841 reader->errorFunc(reader->errorFuncArg, str, severity, 4842 (xmlTextReaderLocatorPtr) ctx); 4843 xmlFree(str); 4844 } 4845 } 4846 4847 static void 4848 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) 4849 { 4850 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; 4851 4852 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; 4853 4854 if (error && reader->sErrorFunc) { 4855 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error); 4856 } 4857 } 4858 4859 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3) 4860 xmlTextReaderError(void *ctxt, const char *msg, ...) 4861 { 4862 va_list ap; 4863 4864 va_start(ap, msg); 4865 xmlTextReaderGenericError(ctxt, 4866 XML_PARSER_SEVERITY_ERROR, 4867 xmlTextReaderBuildMessage(msg, ap)); 4868 va_end(ap); 4869 4870 } 4871 4872 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3) 4873 xmlTextReaderWarning(void *ctxt, const char *msg, ...) 4874 { 4875 va_list ap; 4876 4877 va_start(ap, msg); 4878 xmlTextReaderGenericError(ctxt, 4879 XML_PARSER_SEVERITY_WARNING, 4880 xmlTextReaderBuildMessage(msg, ap)); 4881 va_end(ap); 4882 } 4883 4884 static void XMLCDECL 4885 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) 4886 { 4887 va_list ap; 4888 4889 int len = xmlStrlen((const xmlChar *) msg); 4890 4891 if ((len > 1) && (msg[len - 2] != ':')) { 4892 /* 4893 * some callbacks only report locator information: 4894 * skip them (mimicking behaviour in error.c) 4895 */ 4896 va_start(ap, msg); 4897 xmlTextReaderGenericError(ctxt, 4898 XML_PARSER_SEVERITY_VALIDITY_ERROR, 4899 xmlTextReaderBuildMessage(msg, ap)); 4900 va_end(ap); 4901 } 4902 } 4903 4904 static void XMLCDECL 4905 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) 4906 { 4907 va_list ap; 4908 4909 int len = xmlStrlen((const xmlChar *) msg); 4910 4911 if ((len != 0) && (msg[len - 1] != ':')) { 4912 /* 4913 * some callbacks only report locator information: 4914 * skip them (mimicking behaviour in error.c) 4915 */ 4916 va_start(ap, msg); 4917 xmlTextReaderGenericError(ctxt, 4918 XML_PARSER_SEVERITY_VALIDITY_WARNING, 4919 xmlTextReaderBuildMessage(msg, ap)); 4920 va_end(ap); 4921 } 4922 } 4923 4924 /** 4925 * xmlTextReaderSetErrorHandler: 4926 * @reader: the xmlTextReaderPtr used 4927 * @f: the callback function to call on error and warnings 4928 * @arg: a user argument to pass to the callback function 4929 * 4930 * Register a callback function that will be called on error and warnings. 4931 * 4932 * If @f is NULL, the default error and warning handlers are restored. 4933 */ 4934 void 4935 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, 4936 xmlTextReaderErrorFunc f, void *arg) 4937 { 4938 if (f != NULL) { 4939 reader->ctxt->sax->error = xmlTextReaderError; 4940 reader->ctxt->sax->serror = NULL; 4941 reader->ctxt->vctxt.error = xmlTextReaderValidityError; 4942 reader->ctxt->sax->warning = xmlTextReaderWarning; 4943 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; 4944 reader->errorFunc = f; 4945 reader->sErrorFunc = NULL; 4946 reader->errorFuncArg = arg; 4947 #ifdef LIBXML_SCHEMAS_ENABLED 4948 if (reader->rngValidCtxt) { 4949 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4950 xmlTextReaderValidityErrorRelay, 4951 xmlTextReaderValidityWarningRelay, 4952 reader); 4953 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 4954 reader); 4955 } 4956 if (reader->xsdValidCtxt) { 4957 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4958 xmlTextReaderValidityErrorRelay, 4959 xmlTextReaderValidityWarningRelay, 4960 reader); 4961 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 4962 reader); 4963 } 4964 #endif 4965 } else { 4966 /* restore defaults */ 4967 reader->ctxt->sax->error = xmlParserError; 4968 reader->ctxt->vctxt.error = xmlParserValidityError; 4969 reader->ctxt->sax->warning = xmlParserWarning; 4970 reader->ctxt->vctxt.warning = xmlParserValidityWarning; 4971 reader->errorFunc = NULL; 4972 reader->sErrorFunc = NULL; 4973 reader->errorFuncArg = NULL; 4974 #ifdef LIBXML_SCHEMAS_ENABLED 4975 if (reader->rngValidCtxt) { 4976 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 4977 reader); 4978 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 4979 reader); 4980 } 4981 if (reader->xsdValidCtxt) { 4982 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 4983 reader); 4984 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 4985 reader); 4986 } 4987 #endif 4988 } 4989 } 4990 4991 /** 4992 * xmlTextReaderSetStructuredErrorHandler: 4993 * @reader: the xmlTextReaderPtr used 4994 * @f: the callback function to call on error and warnings 4995 * @arg: a user argument to pass to the callback function 4996 * 4997 * Register a callback function that will be called on error and warnings. 4998 * 4999 * If @f is NULL, the default error and warning handlers are restored. 5000 */ 5001 void 5002 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, 5003 xmlStructuredErrorFunc f, void *arg) 5004 { 5005 if (f != NULL) { 5006 reader->ctxt->sax->error = NULL; 5007 reader->ctxt->sax->serror = xmlTextReaderStructuredError; 5008 reader->ctxt->vctxt.error = xmlTextReaderValidityError; 5009 reader->ctxt->sax->warning = xmlTextReaderWarning; 5010 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; 5011 reader->sErrorFunc = f; 5012 reader->errorFunc = NULL; 5013 reader->errorFuncArg = arg; 5014 #ifdef LIBXML_SCHEMAS_ENABLED 5015 if (reader->rngValidCtxt) { 5016 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 5017 reader); 5018 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 5019 xmlTextReaderValidityStructuredRelay, 5020 reader); 5021 } 5022 if (reader->xsdValidCtxt) { 5023 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 5024 reader); 5025 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 5026 xmlTextReaderValidityStructuredRelay, 5027 reader); 5028 } 5029 #endif 5030 } else { 5031 /* restore defaults */ 5032 reader->ctxt->sax->error = xmlParserError; 5033 reader->ctxt->sax->serror = NULL; 5034 reader->ctxt->vctxt.error = xmlParserValidityError; 5035 reader->ctxt->sax->warning = xmlParserWarning; 5036 reader->ctxt->vctxt.warning = xmlParserValidityWarning; 5037 reader->errorFunc = NULL; 5038 reader->sErrorFunc = NULL; 5039 reader->errorFuncArg = NULL; 5040 #ifdef LIBXML_SCHEMAS_ENABLED 5041 if (reader->rngValidCtxt) { 5042 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 5043 reader); 5044 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 5045 reader); 5046 } 5047 if (reader->xsdValidCtxt) { 5048 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 5049 reader); 5050 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 5051 reader); 5052 } 5053 #endif 5054 } 5055 } 5056 5057 /** 5058 * xmlTextReaderIsValid: 5059 * @reader: the xmlTextReaderPtr used 5060 * 5061 * Retrieve the validity status from the parser context 5062 * 5063 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error 5064 */ 5065 int 5066 xmlTextReaderIsValid(xmlTextReaderPtr reader) 5067 { 5068 if (reader == NULL) 5069 return (-1); 5070 #ifdef LIBXML_SCHEMAS_ENABLED 5071 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG) 5072 return (reader->rngValidErrors == 0); 5073 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD) 5074 return (reader->xsdValidErrors == 0); 5075 #endif 5076 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1)) 5077 return (reader->ctxt->valid); 5078 return (0); 5079 } 5080 5081 /** 5082 * xmlTextReaderGetErrorHandler: 5083 * @reader: the xmlTextReaderPtr used 5084 * @f: the callback function or NULL is no callback has been registered 5085 * @arg: a user argument 5086 * 5087 * Retrieve the error callback function and user argument. 5088 */ 5089 void 5090 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, 5091 xmlTextReaderErrorFunc * f, void **arg) 5092 { 5093 if (f != NULL) 5094 *f = reader->errorFunc; 5095 if (arg != NULL) 5096 *arg = reader->errorFuncArg; 5097 } 5098 /************************************************************************ 5099 * * 5100 * New set (2.6.0) of simpler and more flexible APIs * 5101 * * 5102 ************************************************************************/ 5103 5104 /** 5105 * xmlTextReaderSetup: 5106 * @reader: an XML reader 5107 * @input: xmlParserInputBufferPtr used to feed the reader, will 5108 * be destroyed with it. 5109 * @URL: the base URL to use for the document 5110 * @encoding: the document encoding, or NULL 5111 * @options: a combination of xmlParserOption 5112 * 5113 * Setup an XML reader with new options 5114 * 5115 * Returns 0 in case of success and -1 in case of error. 5116 */ 5117 int 5118 xmlTextReaderSetup(xmlTextReaderPtr reader, 5119 xmlParserInputBufferPtr input, const char *URL, 5120 const char *encoding, int options) 5121 { 5122 if (reader == NULL) { 5123 if (input != NULL) 5124 xmlFreeParserInputBuffer(input); 5125 return (-1); 5126 } 5127 5128 /* 5129 * we force the generation of compact text nodes on the reader 5130 * since usr applications should never modify the tree 5131 */ 5132 options |= XML_PARSE_COMPACT; 5133 5134 reader->doc = NULL; 5135 reader->entNr = 0; 5136 reader->parserFlags = options; 5137 reader->validate = XML_TEXTREADER_NOT_VALIDATE; 5138 if ((input != NULL) && (reader->input != NULL) && 5139 (reader->allocs & XML_TEXTREADER_INPUT)) { 5140 xmlFreeParserInputBuffer(reader->input); 5141 reader->input = NULL; 5142 reader->allocs -= XML_TEXTREADER_INPUT; 5143 } 5144 if (input != NULL) { 5145 reader->input = input; 5146 reader->allocs |= XML_TEXTREADER_INPUT; 5147 } 5148 if (reader->buffer == NULL) 5149 reader->buffer = xmlBufCreateSize(100); 5150 if (reader->buffer == NULL) { 5151 xmlGenericError(xmlGenericErrorContext, 5152 "xmlTextReaderSetup : malloc failed\n"); 5153 return (-1); 5154 } 5155 /* no operation on a reader should require a huge buffer */ 5156 xmlBufSetAllocationScheme(reader->buffer, 5157 XML_BUFFER_ALLOC_BOUNDED); 5158 if (reader->sax == NULL) 5159 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 5160 if (reader->sax == NULL) { 5161 xmlGenericError(xmlGenericErrorContext, 5162 "xmlTextReaderSetup : malloc failed\n"); 5163 return (-1); 5164 } 5165 xmlSAXVersion(reader->sax, 2); 5166 reader->startElement = reader->sax->startElement; 5167 reader->sax->startElement = xmlTextReaderStartElement; 5168 reader->endElement = reader->sax->endElement; 5169 reader->sax->endElement = xmlTextReaderEndElement; 5170 #ifdef LIBXML_SAX1_ENABLED 5171 if (reader->sax->initialized == XML_SAX2_MAGIC) { 5172 #endif /* LIBXML_SAX1_ENABLED */ 5173 reader->startElementNs = reader->sax->startElementNs; 5174 reader->sax->startElementNs = xmlTextReaderStartElementNs; 5175 reader->endElementNs = reader->sax->endElementNs; 5176 reader->sax->endElementNs = xmlTextReaderEndElementNs; 5177 #ifdef LIBXML_SAX1_ENABLED 5178 } else { 5179 reader->startElementNs = NULL; 5180 reader->endElementNs = NULL; 5181 } 5182 #endif /* LIBXML_SAX1_ENABLED */ 5183 reader->characters = reader->sax->characters; 5184 reader->sax->characters = xmlTextReaderCharacters; 5185 reader->sax->ignorableWhitespace = xmlTextReaderCharacters; 5186 reader->cdataBlock = reader->sax->cdataBlock; 5187 reader->sax->cdataBlock = xmlTextReaderCDataBlock; 5188 5189 reader->mode = XML_TEXTREADER_MODE_INITIAL; 5190 reader->node = NULL; 5191 reader->curnode = NULL; 5192 if (input != NULL) { 5193 if (xmlBufUse(reader->input->buffer) < 4) { 5194 xmlParserInputBufferRead(input, 4); 5195 } 5196 if (reader->ctxt == NULL) { 5197 if (xmlBufUse(reader->input->buffer) >= 4) { 5198 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, 5199 (const char *) xmlBufContent(reader->input->buffer), 5200 4, URL); 5201 reader->base = 0; 5202 reader->cur = 4; 5203 } else { 5204 reader->ctxt = 5205 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); 5206 reader->base = 0; 5207 reader->cur = 0; 5208 } 5209 } else { 5210 xmlParserInputPtr inputStream; 5211 xmlParserInputBufferPtr buf; 5212 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; 5213 5214 xmlCtxtReset(reader->ctxt); 5215 buf = xmlAllocParserInputBuffer(enc); 5216 if (buf == NULL) return(-1); 5217 inputStream = xmlNewInputStream(reader->ctxt); 5218 if (inputStream == NULL) { 5219 xmlFreeParserInputBuffer(buf); 5220 return(-1); 5221 } 5222 5223 if (URL == NULL) 5224 inputStream->filename = NULL; 5225 else 5226 inputStream->filename = (char *) 5227 xmlCanonicPath((const xmlChar *) URL); 5228 inputStream->buf = buf; 5229 xmlBufResetInput(buf->buffer, inputStream); 5230 5231 inputPush(reader->ctxt, inputStream); 5232 reader->cur = 0; 5233 } 5234 if (reader->ctxt == NULL) { 5235 xmlGenericError(xmlGenericErrorContext, 5236 "xmlTextReaderSetup : malloc failed\n"); 5237 return (-1); 5238 } 5239 } 5240 if (reader->dict != NULL) { 5241 if (reader->ctxt->dict != NULL) { 5242 if (reader->dict != reader->ctxt->dict) { 5243 xmlDictFree(reader->dict); 5244 reader->dict = reader->ctxt->dict; 5245 } 5246 } else { 5247 reader->ctxt->dict = reader->dict; 5248 } 5249 } else { 5250 if (reader->ctxt->dict == NULL) 5251 reader->ctxt->dict = xmlDictCreate(); 5252 reader->dict = reader->ctxt->dict; 5253 } 5254 reader->ctxt->_private = reader; 5255 reader->ctxt->linenumbers = 1; 5256 reader->ctxt->dictNames = 1; 5257 /* 5258 * use the parser dictionary to allocate all elements and attributes names 5259 */ 5260 reader->ctxt->docdict = 1; 5261 reader->ctxt->parseMode = XML_PARSE_READER; 5262 5263 #ifdef LIBXML_XINCLUDE_ENABLED 5264 if (reader->xincctxt != NULL) { 5265 xmlXIncludeFreeContext(reader->xincctxt); 5266 reader->xincctxt = NULL; 5267 } 5268 if (options & XML_PARSE_XINCLUDE) { 5269 reader->xinclude = 1; 5270 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); 5271 options -= XML_PARSE_XINCLUDE; 5272 } else 5273 reader->xinclude = 0; 5274 reader->in_xinclude = 0; 5275 #endif 5276 #ifdef LIBXML_PATTERN_ENABLED 5277 if (reader->patternTab == NULL) { 5278 reader->patternNr = 0; 5279 reader->patternMax = 0; 5280 } 5281 while (reader->patternNr > 0) { 5282 reader->patternNr--; 5283 if (reader->patternTab[reader->patternNr] != NULL) { 5284 xmlFreePattern(reader->patternTab[reader->patternNr]); 5285 reader->patternTab[reader->patternNr] = NULL; 5286 } 5287 } 5288 #endif 5289 5290 if (options & XML_PARSE_DTDVALID) 5291 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 5292 5293 xmlCtxtUseOptions(reader->ctxt, options); 5294 if (encoding != NULL) { 5295 xmlCharEncodingHandlerPtr hdlr; 5296 5297 hdlr = xmlFindCharEncodingHandler(encoding); 5298 if (hdlr != NULL) 5299 xmlSwitchToEncoding(reader->ctxt, hdlr); 5300 } 5301 if ((URL != NULL) && (reader->ctxt->input != NULL) && 5302 (reader->ctxt->input->filename == NULL)) 5303 reader->ctxt->input->filename = (char *) 5304 xmlStrdup((const xmlChar *) URL); 5305 5306 reader->doc = NULL; 5307 5308 return (0); 5309 } 5310 5311 /** 5312 * xmlTextReaderByteConsumed: 5313 * @reader: an XML reader 5314 * 5315 * This function provides the current index of the parser used 5316 * by the reader, relative to the start of the current entity. 5317 * This function actually just wraps a call to xmlBytesConsumed() 5318 * for the parser context associated with the reader. 5319 * See xmlBytesConsumed() for more information. 5320 * 5321 * Returns the index in bytes from the beginning of the entity or -1 5322 * in case the index could not be computed. 5323 */ 5324 long 5325 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) { 5326 if ((reader == NULL) || (reader->ctxt == NULL)) 5327 return(-1); 5328 return(xmlByteConsumed(reader->ctxt)); 5329 } 5330 5331 5332 /** 5333 * xmlReaderWalker: 5334 * @doc: a preparsed document 5335 * 5336 * Create an xmltextReader for a preparsed document. 5337 * 5338 * Returns the new reader or NULL in case of error. 5339 */ 5340 xmlTextReaderPtr 5341 xmlReaderWalker(xmlDocPtr doc) 5342 { 5343 xmlTextReaderPtr ret; 5344 5345 if (doc == NULL) 5346 return(NULL); 5347 5348 ret = xmlMalloc(sizeof(xmlTextReader)); 5349 if (ret == NULL) { 5350 xmlGenericError(xmlGenericErrorContext, 5351 "xmlNewTextReader : malloc failed\n"); 5352 return(NULL); 5353 } 5354 memset(ret, 0, sizeof(xmlTextReader)); 5355 ret->entNr = 0; 5356 ret->input = NULL; 5357 ret->mode = XML_TEXTREADER_MODE_INITIAL; 5358 ret->node = NULL; 5359 ret->curnode = NULL; 5360 ret->base = 0; 5361 ret->cur = 0; 5362 ret->allocs = XML_TEXTREADER_CTXT; 5363 ret->doc = doc; 5364 ret->state = XML_TEXTREADER_START; 5365 ret->dict = xmlDictCreate(); 5366 return(ret); 5367 } 5368 5369 /** 5370 * xmlReaderForDoc: 5371 * @cur: a pointer to a zero terminated string 5372 * @URL: the base URL to use for the document 5373 * @encoding: the document encoding, or NULL 5374 * @options: a combination of xmlParserOption 5375 * 5376 * Create an xmltextReader for an XML in-memory document. 5377 * The parsing flags @options are a combination of xmlParserOption. 5378 * 5379 * Returns the new reader or NULL in case of error. 5380 */ 5381 xmlTextReaderPtr 5382 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, 5383 int options) 5384 { 5385 int len; 5386 5387 if (cur == NULL) 5388 return (NULL); 5389 len = xmlStrlen(cur); 5390 5391 return (xmlReaderForMemory 5392 ((const char *) cur, len, URL, encoding, options)); 5393 } 5394 5395 /** 5396 * xmlReaderForFile: 5397 * @filename: a file or URL 5398 * @encoding: the document encoding, or NULL 5399 * @options: a combination of xmlParserOption 5400 * 5401 * parse an XML file from the filesystem or the network. 5402 * The parsing flags @options are a combination of xmlParserOption. 5403 * 5404 * Returns the new reader or NULL in case of error. 5405 */ 5406 xmlTextReaderPtr 5407 xmlReaderForFile(const char *filename, const char *encoding, int options) 5408 { 5409 xmlTextReaderPtr reader; 5410 5411 reader = xmlNewTextReaderFilename(filename); 5412 if (reader == NULL) 5413 return (NULL); 5414 xmlTextReaderSetup(reader, NULL, NULL, encoding, options); 5415 return (reader); 5416 } 5417 5418 /** 5419 * xmlReaderForMemory: 5420 * @buffer: a pointer to a char array 5421 * @size: the size of the array 5422 * @URL: the base URL to use for the document 5423 * @encoding: the document encoding, or NULL 5424 * @options: a combination of xmlParserOption 5425 * 5426 * Create an xmltextReader for an XML in-memory document. 5427 * The parsing flags @options are a combination of xmlParserOption. 5428 * 5429 * Returns the new reader or NULL in case of error. 5430 */ 5431 xmlTextReaderPtr 5432 xmlReaderForMemory(const char *buffer, int size, const char *URL, 5433 const char *encoding, int options) 5434 { 5435 xmlTextReaderPtr reader; 5436 xmlParserInputBufferPtr buf; 5437 5438 buf = xmlParserInputBufferCreateStatic(buffer, size, 5439 XML_CHAR_ENCODING_NONE); 5440 if (buf == NULL) { 5441 return (NULL); 5442 } 5443 reader = xmlNewTextReader(buf, URL); 5444 if (reader == NULL) { 5445 xmlFreeParserInputBuffer(buf); 5446 return (NULL); 5447 } 5448 reader->allocs |= XML_TEXTREADER_INPUT; 5449 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5450 return (reader); 5451 } 5452 5453 /** 5454 * xmlReaderForFd: 5455 * @fd: an open file descriptor 5456 * @URL: the base URL to use for the document 5457 * @encoding: the document encoding, or NULL 5458 * @options: a combination of xmlParserOption 5459 * 5460 * Create an xmltextReader for an XML from a file descriptor. 5461 * The parsing flags @options are a combination of xmlParserOption. 5462 * NOTE that the file descriptor will not be closed when the 5463 * reader is closed or reset. 5464 * 5465 * Returns the new reader or NULL in case of error. 5466 */ 5467 xmlTextReaderPtr 5468 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) 5469 { 5470 xmlTextReaderPtr reader; 5471 xmlParserInputBufferPtr input; 5472 5473 if (fd < 0) 5474 return (NULL); 5475 5476 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 5477 if (input == NULL) 5478 return (NULL); 5479 input->closecallback = NULL; 5480 reader = xmlNewTextReader(input, URL); 5481 if (reader == NULL) { 5482 xmlFreeParserInputBuffer(input); 5483 return (NULL); 5484 } 5485 reader->allocs |= XML_TEXTREADER_INPUT; 5486 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5487 return (reader); 5488 } 5489 5490 /** 5491 * xmlReaderForIO: 5492 * @ioread: an I/O read function 5493 * @ioclose: an I/O close function 5494 * @ioctx: an I/O handler 5495 * @URL: the base URL to use for the document 5496 * @encoding: the document encoding, or NULL 5497 * @options: a combination of xmlParserOption 5498 * 5499 * Create an xmltextReader for an XML document from I/O functions and source. 5500 * The parsing flags @options are a combination of xmlParserOption. 5501 * 5502 * Returns the new reader or NULL in case of error. 5503 */ 5504 xmlTextReaderPtr 5505 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, 5506 void *ioctx, const char *URL, const char *encoding, 5507 int options) 5508 { 5509 xmlTextReaderPtr reader; 5510 xmlParserInputBufferPtr input; 5511 5512 if (ioread == NULL) 5513 return (NULL); 5514 5515 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 5516 XML_CHAR_ENCODING_NONE); 5517 if (input == NULL) { 5518 if (ioclose != NULL) 5519 ioclose(ioctx); 5520 return (NULL); 5521 } 5522 reader = xmlNewTextReader(input, URL); 5523 if (reader == NULL) { 5524 xmlFreeParserInputBuffer(input); 5525 return (NULL); 5526 } 5527 reader->allocs |= XML_TEXTREADER_INPUT; 5528 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5529 return (reader); 5530 } 5531 5532 /** 5533 * xmlReaderNewWalker: 5534 * @reader: an XML reader 5535 * @doc: a preparsed document 5536 * 5537 * Setup an xmltextReader to parse a preparsed XML document. 5538 * This reuses the existing @reader xmlTextReader. 5539 * 5540 * Returns 0 in case of success and -1 in case of error 5541 */ 5542 int 5543 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc) 5544 { 5545 if (doc == NULL) 5546 return (-1); 5547 if (reader == NULL) 5548 return (-1); 5549 5550 if (reader->input != NULL) { 5551 xmlFreeParserInputBuffer(reader->input); 5552 } 5553 if (reader->ctxt != NULL) { 5554 xmlCtxtReset(reader->ctxt); 5555 } 5556 5557 reader->entNr = 0; 5558 reader->input = NULL; 5559 reader->mode = XML_TEXTREADER_MODE_INITIAL; 5560 reader->node = NULL; 5561 reader->curnode = NULL; 5562 reader->base = 0; 5563 reader->cur = 0; 5564 reader->allocs = XML_TEXTREADER_CTXT; 5565 reader->doc = doc; 5566 reader->state = XML_TEXTREADER_START; 5567 if (reader->dict == NULL) { 5568 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) 5569 reader->dict = reader->ctxt->dict; 5570 else 5571 reader->dict = xmlDictCreate(); 5572 } 5573 return(0); 5574 } 5575 5576 /** 5577 * xmlReaderNewDoc: 5578 * @reader: an XML reader 5579 * @cur: a pointer to a zero terminated string 5580 * @URL: the base URL to use for the document 5581 * @encoding: the document encoding, or NULL 5582 * @options: a combination of xmlParserOption 5583 * 5584 * Setup an xmltextReader to parse an XML in-memory document. 5585 * The parsing flags @options are a combination of xmlParserOption. 5586 * This reuses the existing @reader xmlTextReader. 5587 * 5588 * Returns 0 in case of success and -1 in case of error 5589 */ 5590 int 5591 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, 5592 const char *URL, const char *encoding, int options) 5593 { 5594 5595 int len; 5596 5597 if (cur == NULL) 5598 return (-1); 5599 if (reader == NULL) 5600 return (-1); 5601 5602 len = xmlStrlen(cur); 5603 return (xmlReaderNewMemory(reader, (const char *)cur, len, 5604 URL, encoding, options)); 5605 } 5606 5607 /** 5608 * xmlReaderNewFile: 5609 * @reader: an XML reader 5610 * @filename: a file or URL 5611 * @encoding: the document encoding, or NULL 5612 * @options: a combination of xmlParserOption 5613 * 5614 * parse an XML file from the filesystem or the network. 5615 * The parsing flags @options are a combination of xmlParserOption. 5616 * This reuses the existing @reader xmlTextReader. 5617 * 5618 * Returns 0 in case of success and -1 in case of error 5619 */ 5620 int 5621 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, 5622 const char *encoding, int options) 5623 { 5624 xmlParserInputBufferPtr input; 5625 5626 if (filename == NULL) 5627 return (-1); 5628 if (reader == NULL) 5629 return (-1); 5630 5631 input = 5632 xmlParserInputBufferCreateFilename(filename, 5633 XML_CHAR_ENCODING_NONE); 5634 if (input == NULL) 5635 return (-1); 5636 return (xmlTextReaderSetup(reader, input, filename, encoding, options)); 5637 } 5638 5639 /** 5640 * xmlReaderNewMemory: 5641 * @reader: an XML reader 5642 * @buffer: a pointer to a char array 5643 * @size: the size of the array 5644 * @URL: the base URL to use for the document 5645 * @encoding: the document encoding, or NULL 5646 * @options: a combination of xmlParserOption 5647 * 5648 * Setup an xmltextReader to parse an XML in-memory document. 5649 * The parsing flags @options are a combination of xmlParserOption. 5650 * This reuses the existing @reader xmlTextReader. 5651 * 5652 * Returns 0 in case of success and -1 in case of error 5653 */ 5654 int 5655 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, 5656 const char *URL, const char *encoding, int options) 5657 { 5658 xmlParserInputBufferPtr input; 5659 5660 if (reader == NULL) 5661 return (-1); 5662 if (buffer == NULL) 5663 return (-1); 5664 5665 input = xmlParserInputBufferCreateStatic(buffer, size, 5666 XML_CHAR_ENCODING_NONE); 5667 if (input == NULL) { 5668 return (-1); 5669 } 5670 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5671 } 5672 5673 /** 5674 * xmlReaderNewFd: 5675 * @reader: an XML reader 5676 * @fd: an open file descriptor 5677 * @URL: the base URL to use for the document 5678 * @encoding: the document encoding, or NULL 5679 * @options: a combination of xmlParserOption 5680 * 5681 * Setup an xmltextReader to parse an XML from a file descriptor. 5682 * NOTE that the file descriptor will not be closed when the 5683 * reader is closed or reset. 5684 * The parsing flags @options are a combination of xmlParserOption. 5685 * This reuses the existing @reader xmlTextReader. 5686 * 5687 * Returns 0 in case of success and -1 in case of error 5688 */ 5689 int 5690 xmlReaderNewFd(xmlTextReaderPtr reader, int fd, 5691 const char *URL, const char *encoding, int options) 5692 { 5693 xmlParserInputBufferPtr input; 5694 5695 if (fd < 0) 5696 return (-1); 5697 if (reader == NULL) 5698 return (-1); 5699 5700 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 5701 if (input == NULL) 5702 return (-1); 5703 input->closecallback = NULL; 5704 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5705 } 5706 5707 /** 5708 * xmlReaderNewIO: 5709 * @reader: an XML reader 5710 * @ioread: an I/O read function 5711 * @ioclose: an I/O close function 5712 * @ioctx: an I/O handler 5713 * @URL: the base URL to use for the document 5714 * @encoding: the document encoding, or NULL 5715 * @options: a combination of xmlParserOption 5716 * 5717 * Setup an xmltextReader to parse an XML document from I/O functions 5718 * and source. 5719 * The parsing flags @options are a combination of xmlParserOption. 5720 * This reuses the existing @reader xmlTextReader. 5721 * 5722 * Returns 0 in case of success and -1 in case of error 5723 */ 5724 int 5725 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, 5726 xmlInputCloseCallback ioclose, void *ioctx, 5727 const char *URL, const char *encoding, int options) 5728 { 5729 xmlParserInputBufferPtr input; 5730 5731 if (ioread == NULL) 5732 return (-1); 5733 if (reader == NULL) 5734 return (-1); 5735 5736 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 5737 XML_CHAR_ENCODING_NONE); 5738 if (input == NULL) { 5739 if (ioclose != NULL) 5740 ioclose(ioctx); 5741 return (-1); 5742 } 5743 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5744 } 5745 5746 /************************************************************************ 5747 * * 5748 * Utilities * 5749 * * 5750 ************************************************************************/ 5751 #ifdef NOT_USED_YET 5752 5753 /** 5754 * xmlBase64Decode: 5755 * @in: the input buffer 5756 * @inlen: the size of the input (in), the size read from it (out) 5757 * @to: the output buffer 5758 * @tolen: the size of the output (in), the size written to (out) 5759 * 5760 * Base64 decoder, reads from @in and save in @to 5761 * TODO: tell jody when this is actually exported 5762 * 5763 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, 5764 * 2 if there wasn't enough space on the output or -1 in case of error. 5765 */ 5766 static int 5767 xmlBase64Decode(const unsigned char *in, unsigned long *inlen, 5768 unsigned char *to, unsigned long *tolen) 5769 { 5770 unsigned long incur; /* current index in in[] */ 5771 5772 unsigned long inblk; /* last block index in in[] */ 5773 5774 unsigned long outcur; /* current index in out[] */ 5775 5776 unsigned long inmax; /* size of in[] */ 5777 5778 unsigned long outmax; /* size of out[] */ 5779 5780 unsigned char cur; /* the current value read from in[] */ 5781 5782 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */ 5783 5784 int nbintmp; /* number of byte in intmp[] */ 5785 5786 int is_ignore; /* cur should be ignored */ 5787 5788 int is_end = 0; /* the end of the base64 was found */ 5789 5790 int retval = 1; 5791 5792 int i; 5793 5794 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) 5795 return (-1); 5796 5797 incur = 0; 5798 inblk = 0; 5799 outcur = 0; 5800 inmax = *inlen; 5801 outmax = *tolen; 5802 nbintmp = 0; 5803 5804 while (1) { 5805 if (incur >= inmax) 5806 break; 5807 cur = in[incur++]; 5808 is_ignore = 0; 5809 if ((cur >= 'A') && (cur <= 'Z')) 5810 cur = cur - 'A'; 5811 else if ((cur >= 'a') && (cur <= 'z')) 5812 cur = cur - 'a' + 26; 5813 else if ((cur >= '0') && (cur <= '9')) 5814 cur = cur - '0' + 52; 5815 else if (cur == '+') 5816 cur = 62; 5817 else if (cur == '/') 5818 cur = 63; 5819 else if (cur == '.') 5820 cur = 0; 5821 else if (cur == '=') /*no op , end of the base64 stream */ 5822 is_end = 1; 5823 else { 5824 is_ignore = 1; 5825 if (nbintmp == 0) 5826 inblk = incur; 5827 } 5828 5829 if (!is_ignore) { 5830 int nbouttmp = 3; 5831 5832 int is_break = 0; 5833 5834 if (is_end) { 5835 if (nbintmp == 0) 5836 break; 5837 if ((nbintmp == 1) || (nbintmp == 2)) 5838 nbouttmp = 1; 5839 else 5840 nbouttmp = 2; 5841 nbintmp = 3; 5842 is_break = 1; 5843 } 5844 intmp[nbintmp++] = cur; 5845 /* 5846 * if intmp is full, push the 4byte sequence as a 3 byte 5847 * sequence out 5848 */ 5849 if (nbintmp == 4) { 5850 nbintmp = 0; 5851 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); 5852 outtmp[1] = 5853 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); 5854 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); 5855 if (outcur + 3 >= outmax) { 5856 retval = 2; 5857 break; 5858 } 5859 5860 for (i = 0; i < nbouttmp; i++) 5861 to[outcur++] = outtmp[i]; 5862 inblk = incur; 5863 } 5864 5865 if (is_break) { 5866 retval = 0; 5867 break; 5868 } 5869 } 5870 } 5871 5872 *tolen = outcur; 5873 *inlen = inblk; 5874 return (retval); 5875 } 5876 5877 /* 5878 * Test routine for the xmlBase64Decode function 5879 */ 5880 #if 0 5881 int 5882 main(int argc, char **argv) 5883 { 5884 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== "; 5885 5886 char output[100]; 5887 5888 char output2[100]; 5889 5890 char output3[100]; 5891 5892 unsigned long inlen = strlen(input); 5893 5894 unsigned long outlen = 100; 5895 5896 int ret; 5897 5898 unsigned long cons, tmp, tmp2, prod; 5899 5900 /* 5901 * Direct 5902 */ 5903 ret = xmlBase64Decode(input, &inlen, output, &outlen); 5904 5905 output[outlen] = 0; 5906 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, 5907 outlen, output)indent: Standard input:179: Error:Unmatched #endif 5908 ; 5909 5910 /* 5911 * output chunking 5912 */ 5913 cons = 0; 5914 prod = 0; 5915 while (cons < inlen) { 5916 tmp = 5; 5917 tmp2 = inlen - cons; 5918 5919 printf("%ld %ld\n", cons, prod); 5920 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); 5921 cons += tmp2; 5922 prod += tmp; 5923 printf("%ld %ld\n", cons, prod); 5924 } 5925 output2[outlen] = 0; 5926 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, 5927 prod, output2); 5928 5929 /* 5930 * input chunking 5931 */ 5932 cons = 0; 5933 prod = 0; 5934 while (cons < inlen) { 5935 tmp = 100 - prod; 5936 tmp2 = inlen - cons; 5937 if (tmp2 > 5) 5938 tmp2 = 5; 5939 5940 printf("%ld %ld\n", cons, prod); 5941 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); 5942 cons += tmp2; 5943 prod += tmp; 5944 printf("%ld %ld\n", cons, prod); 5945 } 5946 output3[outlen] = 0; 5947 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, 5948 prod, output3); 5949 return (0); 5950 5951 } 5952 #endif 5953 #endif /* NOT_USED_YET */ 5954 #define bottom_xmlreader 5955 #include "elfgcchack.h" 5956 #endif /* LIBXML_READER_ENABLED */ 5957