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