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->doc; 1715 buff = xmlBufferCreate(); 1716 for (cur_node = reader->node->children; cur_node != NULL; 1717 cur_node = cur_node->next) { 1718 node = xmlDocCopyNode(cur_node, doc, 1); 1719 buff2 = xmlBufferCreate(); 1720 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { 1721 xmlFreeNode(node); 1722 xmlBufferFree(buff2); 1723 xmlBufferFree(buff); 1724 return NULL; 1725 } 1726 xmlBufferCat(buff, buff2->content); 1727 xmlFreeNode(node); 1728 xmlBufferFree(buff2); 1729 } 1730 resbuf = buff->content; 1731 buff->content = NULL; 1732 1733 xmlBufferFree(buff); 1734 return resbuf; 1735 } 1736 #endif 1737 1738 #ifdef LIBXML_WRITER_ENABLED 1739 /** 1740 * xmlTextReaderReadOuterXml: 1741 * @reader: the xmlTextReaderPtr used 1742 * 1743 * Reads the contents of the current node, including child nodes and markup. 1744 * 1745 * Returns a string containing the node and any XML content, or NULL if the 1746 * current node cannot be serialized. The string must be deallocated 1747 * by the caller. 1748 */ 1749 xmlChar * 1750 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) 1751 { 1752 xmlChar *resbuf; 1753 xmlNodePtr node; 1754 xmlBufferPtr buff; 1755 xmlDocPtr doc; 1756 1757 node = reader->node; 1758 doc = reader->doc; 1759 if (xmlTextReaderExpand(reader) == NULL) { 1760 return NULL; 1761 } 1762 if (node->type == XML_DTD_NODE) { 1763 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node); 1764 } else { 1765 node = xmlDocCopyNode(node, doc, 1); 1766 } 1767 buff = xmlBufferCreate(); 1768 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { 1769 xmlFreeNode(node); 1770 xmlBufferFree(buff); 1771 return NULL; 1772 } 1773 1774 resbuf = buff->content; 1775 buff->content = NULL; 1776 1777 xmlFreeNode(node); 1778 xmlBufferFree(buff); 1779 return resbuf; 1780 } 1781 #endif 1782 1783 /** 1784 * xmlTextReaderReadString: 1785 * @reader: the xmlTextReaderPtr used 1786 * 1787 * Reads the contents of an element or a text node as a string. 1788 * 1789 * Returns a string containing the contents of the Element or Text node, 1790 * or NULL if the reader is positioned on any other type of node. 1791 * The string must be deallocated by the caller. 1792 */ 1793 xmlChar * 1794 xmlTextReaderReadString(xmlTextReaderPtr reader) 1795 { 1796 xmlNodePtr node; 1797 1798 if ((reader == NULL) || (reader->node == NULL)) 1799 return(NULL); 1800 1801 node = (reader->curnode != NULL) ? reader->curnode : reader->node; 1802 switch (node->type) { 1803 case XML_TEXT_NODE: 1804 if (node->content != NULL) 1805 return(xmlStrdup(node->content)); 1806 break; 1807 case XML_ELEMENT_NODE: 1808 if (xmlTextReaderDoExpand(reader) != -1) { 1809 return xmlTextReaderCollectSiblings(node->children); 1810 } 1811 break; 1812 case XML_ATTRIBUTE_NODE: 1813 TODO 1814 break; 1815 default: 1816 break; 1817 } 1818 return(NULL); 1819 } 1820 1821 #if 0 1822 /** 1823 * xmlTextReaderReadBase64: 1824 * @reader: the xmlTextReaderPtr used 1825 * @array: a byte array to store the content. 1826 * @offset: the zero-based index into array where the method should 1827 * begin to write. 1828 * @len: the number of bytes to write. 1829 * 1830 * Reads and decodes the Base64 encoded contents of an element and 1831 * stores the result in a byte buffer. 1832 * 1833 * Returns the number of bytes written to array, or zero if the current 1834 * instance is not positioned on an element or -1 in case of error. 1835 */ 1836 int 1837 xmlTextReaderReadBase64(xmlTextReaderPtr reader, 1838 unsigned char *array ATTRIBUTE_UNUSED, 1839 int offset ATTRIBUTE_UNUSED, 1840 int len ATTRIBUTE_UNUSED) { 1841 if ((reader == NULL) || (reader->ctxt == NULL)) 1842 return(-1); 1843 if (reader->ctxt->wellFormed != 1) 1844 return(-1); 1845 1846 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1847 return(0); 1848 TODO 1849 return(0); 1850 } 1851 1852 /** 1853 * xmlTextReaderReadBinHex: 1854 * @reader: the xmlTextReaderPtr used 1855 * @array: a byte array to store the content. 1856 * @offset: the zero-based index into array where the method should 1857 * begin to write. 1858 * @len: the number of bytes to write. 1859 * 1860 * Reads and decodes the BinHex encoded contents of an element and 1861 * stores the result in a byte buffer. 1862 * 1863 * Returns the number of bytes written to array, or zero if the current 1864 * instance is not positioned on an element or -1 in case of error. 1865 */ 1866 int 1867 xmlTextReaderReadBinHex(xmlTextReaderPtr reader, 1868 unsigned char *array ATTRIBUTE_UNUSED, 1869 int offset ATTRIBUTE_UNUSED, 1870 int len ATTRIBUTE_UNUSED) { 1871 if ((reader == NULL) || (reader->ctxt == NULL)) 1872 return(-1); 1873 if (reader->ctxt->wellFormed != 1) 1874 return(-1); 1875 1876 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1877 return(0); 1878 TODO 1879 return(0); 1880 } 1881 #endif 1882 1883 /************************************************************************ 1884 * * 1885 * Operating on a preparsed tree * 1886 * * 1887 ************************************************************************/ 1888 static int 1889 xmlTextReaderNextTree(xmlTextReaderPtr reader) 1890 { 1891 if (reader == NULL) 1892 return(-1); 1893 1894 if (reader->state == XML_TEXTREADER_END) 1895 return(0); 1896 1897 if (reader->node == NULL) { 1898 if (reader->doc->children == NULL) { 1899 reader->state = XML_TEXTREADER_END; 1900 return(0); 1901 } 1902 1903 reader->node = reader->doc->children; 1904 reader->state = XML_TEXTREADER_START; 1905 return(1); 1906 } 1907 1908 if (reader->state != XML_TEXTREADER_BACKTRACK) { 1909 /* Here removed traversal to child, because we want to skip the subtree, 1910 replace with traversal to sibling to skip subtree */ 1911 if (reader->node->next != 0) { 1912 /* Move to sibling if present,skipping sub-tree */ 1913 reader->node = reader->node->next; 1914 reader->state = XML_TEXTREADER_START; 1915 return(1); 1916 } 1917 1918 /* if reader->node->next is NULL mean no subtree for current node, 1919 so need to move to sibling of parent node if present */ 1920 if ((reader->node->type == XML_ELEMENT_NODE) || 1921 (reader->node->type == XML_ATTRIBUTE_NODE)) { 1922 reader->state = XML_TEXTREADER_BACKTRACK; 1923 /* This will move to parent if present */ 1924 xmlTextReaderRead(reader); 1925 } 1926 } 1927 1928 if (reader->node->next != 0) { 1929 reader->node = reader->node->next; 1930 reader->state = XML_TEXTREADER_START; 1931 return(1); 1932 } 1933 1934 if (reader->node->parent != 0) { 1935 if (reader->node->parent->type == XML_DOCUMENT_NODE) { 1936 reader->state = XML_TEXTREADER_END; 1937 return(0); 1938 } 1939 1940 reader->node = reader->node->parent; 1941 reader->depth--; 1942 reader->state = XML_TEXTREADER_BACKTRACK; 1943 /* Repeat process to move to sibling of parent node if present */ 1944 xmlTextReaderNextTree(reader); 1945 } 1946 1947 reader->state = XML_TEXTREADER_END; 1948 1949 return(1); 1950 } 1951 1952 /** 1953 * xmlTextReaderReadTree: 1954 * @reader: the xmlTextReaderPtr used 1955 * 1956 * Moves the position of the current instance to the next node in 1957 * the stream, exposing its properties. 1958 * 1959 * Returns 1 if the node was read successfully, 0 if there is no more 1960 * nodes to read, or -1 in case of error 1961 */ 1962 static int 1963 xmlTextReaderReadTree(xmlTextReaderPtr reader) { 1964 if (reader->state == XML_TEXTREADER_END) 1965 return(0); 1966 1967 next_node: 1968 if (reader->node == NULL) { 1969 if (reader->doc->children == NULL) { 1970 reader->state = XML_TEXTREADER_END; 1971 return(0); 1972 } 1973 1974 reader->node = reader->doc->children; 1975 reader->state = XML_TEXTREADER_START; 1976 goto found_node; 1977 } 1978 1979 if ((reader->state != XML_TEXTREADER_BACKTRACK) && 1980 (reader->node->type != XML_DTD_NODE) && 1981 (reader->node->type != XML_XINCLUDE_START) && 1982 (reader->node->type != XML_ENTITY_REF_NODE)) { 1983 if (reader->node->children != NULL) { 1984 reader->node = reader->node->children; 1985 reader->depth++; 1986 reader->state = XML_TEXTREADER_START; 1987 goto found_node; 1988 } 1989 1990 if (reader->node->type == XML_ATTRIBUTE_NODE) { 1991 reader->state = XML_TEXTREADER_BACKTRACK; 1992 goto found_node; 1993 } 1994 } 1995 1996 if (reader->node->next != NULL) { 1997 reader->node = reader->node->next; 1998 reader->state = XML_TEXTREADER_START; 1999 goto found_node; 2000 } 2001 2002 if (reader->node->parent != NULL) { 2003 if ((reader->node->parent->type == XML_DOCUMENT_NODE) || 2004 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { 2005 reader->state = XML_TEXTREADER_END; 2006 return(0); 2007 } 2008 2009 reader->node = reader->node->parent; 2010 reader->depth--; 2011 reader->state = XML_TEXTREADER_BACKTRACK; 2012 goto found_node; 2013 } 2014 2015 reader->state = XML_TEXTREADER_END; 2016 2017 found_node: 2018 if ((reader->node->type == XML_XINCLUDE_START) || 2019 (reader->node->type == XML_XINCLUDE_END)) 2020 goto next_node; 2021 2022 return(1); 2023 } 2024 2025 /** 2026 * xmlTextReaderNextSibling: 2027 * @reader: the xmlTextReaderPtr used 2028 * 2029 * Skip to the node following the current one in document order while 2030 * avoiding the subtree if any. 2031 * Currently implemented only for Readers built on a document 2032 * 2033 * Returns 1 if the node was read successfully, 0 if there is no more 2034 * nodes to read, or -1 in case of error 2035 */ 2036 int 2037 xmlTextReaderNextSibling(xmlTextReaderPtr reader) { 2038 if (reader == NULL) 2039 return(-1); 2040 if (reader->doc == NULL) { 2041 /* TODO */ 2042 return(-1); 2043 } 2044 2045 if (reader->state == XML_TEXTREADER_END) 2046 return(0); 2047 2048 if (reader->node == NULL) 2049 return(xmlTextReaderNextTree(reader)); 2050 2051 if (reader->node->next != NULL) { 2052 reader->node = reader->node->next; 2053 reader->state = XML_TEXTREADER_START; 2054 return(1); 2055 } 2056 2057 return(0); 2058 } 2059 2060 /************************************************************************ 2061 * * 2062 * Constructor and destructors * 2063 * * 2064 ************************************************************************/ 2065 /** 2066 * xmlNewTextReader: 2067 * @input: the xmlParserInputBufferPtr used to read data 2068 * @URI: the URI information for the source if available 2069 * 2070 * Create an xmlTextReader structure fed with @input 2071 * 2072 * Returns the new xmlTextReaderPtr or NULL in case of error 2073 */ 2074 xmlTextReaderPtr 2075 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { 2076 xmlTextReaderPtr ret; 2077 2078 if (input == NULL) 2079 return(NULL); 2080 ret = xmlMalloc(sizeof(xmlTextReader)); 2081 if (ret == NULL) { 2082 xmlGenericError(xmlGenericErrorContext, 2083 "xmlNewTextReader : malloc failed\n"); 2084 return(NULL); 2085 } 2086 memset(ret, 0, sizeof(xmlTextReader)); 2087 ret->doc = NULL; 2088 ret->entTab = NULL; 2089 ret->entMax = 0; 2090 ret->entNr = 0; 2091 ret->input = input; 2092 ret->buffer = xmlBufCreateSize(100); 2093 if (ret->buffer == NULL) { 2094 xmlFree(ret); 2095 xmlGenericError(xmlGenericErrorContext, 2096 "xmlNewTextReader : malloc failed\n"); 2097 return(NULL); 2098 } 2099 /* no operation on a reader should require a huge buffer */ 2100 xmlBufSetAllocationScheme(ret->buffer, 2101 XML_BUFFER_ALLOC_BOUNDED); 2102 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 2103 if (ret->sax == NULL) { 2104 xmlBufFree(ret->buffer); 2105 xmlFree(ret); 2106 xmlGenericError(xmlGenericErrorContext, 2107 "xmlNewTextReader : malloc failed\n"); 2108 return(NULL); 2109 } 2110 xmlSAXVersion(ret->sax, 2); 2111 ret->startElement = ret->sax->startElement; 2112 ret->sax->startElement = xmlTextReaderStartElement; 2113 ret->endElement = ret->sax->endElement; 2114 ret->sax->endElement = xmlTextReaderEndElement; 2115 #ifdef LIBXML_SAX1_ENABLED 2116 if (ret->sax->initialized == XML_SAX2_MAGIC) { 2117 #endif /* LIBXML_SAX1_ENABLED */ 2118 ret->startElementNs = ret->sax->startElementNs; 2119 ret->sax->startElementNs = xmlTextReaderStartElementNs; 2120 ret->endElementNs = ret->sax->endElementNs; 2121 ret->sax->endElementNs = xmlTextReaderEndElementNs; 2122 #ifdef LIBXML_SAX1_ENABLED 2123 } else { 2124 ret->startElementNs = NULL; 2125 ret->endElementNs = NULL; 2126 } 2127 #endif /* LIBXML_SAX1_ENABLED */ 2128 ret->characters = ret->sax->characters; 2129 ret->sax->characters = xmlTextReaderCharacters; 2130 ret->sax->ignorableWhitespace = xmlTextReaderCharacters; 2131 ret->cdataBlock = ret->sax->cdataBlock; 2132 ret->sax->cdataBlock = xmlTextReaderCDataBlock; 2133 2134 ret->mode = XML_TEXTREADER_MODE_INITIAL; 2135 ret->node = NULL; 2136 ret->curnode = NULL; 2137 if (xmlBufUse(ret->input->buffer) < 4) { 2138 xmlParserInputBufferRead(input, 4); 2139 } 2140 if (xmlBufUse(ret->input->buffer) >= 4) { 2141 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, 2142 (const char *) xmlBufContent(ret->input->buffer), 2143 4, URI); 2144 ret->base = 0; 2145 ret->cur = 4; 2146 } else { 2147 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); 2148 ret->base = 0; 2149 ret->cur = 0; 2150 } 2151 2152 if (ret->ctxt == NULL) { 2153 xmlGenericError(xmlGenericErrorContext, 2154 "xmlNewTextReader : malloc failed\n"); 2155 xmlBufFree(ret->buffer); 2156 xmlFree(ret->sax); 2157 xmlFree(ret); 2158 return(NULL); 2159 } 2160 ret->ctxt->parseMode = XML_PARSE_READER; 2161 ret->ctxt->_private = ret; 2162 ret->ctxt->linenumbers = 1; 2163 ret->ctxt->dictNames = 1; 2164 ret->allocs = XML_TEXTREADER_CTXT; 2165 /* 2166 * use the parser dictionary to allocate all elements and attributes names 2167 */ 2168 ret->ctxt->docdict = 1; 2169 ret->dict = ret->ctxt->dict; 2170 #ifdef LIBXML_XINCLUDE_ENABLED 2171 ret->xinclude = 0; 2172 #endif 2173 #ifdef LIBXML_PATTERN_ENABLED 2174 ret->patternMax = 0; 2175 ret->patternTab = NULL; 2176 #endif 2177 return(ret); 2178 } 2179 2180 /** 2181 * xmlNewTextReaderFilename: 2182 * @URI: the URI of the resource to process 2183 * 2184 * Create an xmlTextReader structure fed with the resource at @URI 2185 * 2186 * Returns the new xmlTextReaderPtr or NULL in case of error 2187 */ 2188 xmlTextReaderPtr 2189 xmlNewTextReaderFilename(const char *URI) { 2190 xmlParserInputBufferPtr input; 2191 xmlTextReaderPtr ret; 2192 char *directory = NULL; 2193 2194 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); 2195 if (input == NULL) 2196 return(NULL); 2197 ret = xmlNewTextReader(input, URI); 2198 if (ret == NULL) { 2199 xmlFreeParserInputBuffer(input); 2200 return(NULL); 2201 } 2202 ret->allocs |= XML_TEXTREADER_INPUT; 2203 if (ret->ctxt->directory == NULL) 2204 directory = xmlParserGetDirectory(URI); 2205 if ((ret->ctxt->directory == NULL) && (directory != NULL)) 2206 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); 2207 if (directory != NULL) 2208 xmlFree(directory); 2209 return(ret); 2210 } 2211 2212 /** 2213 * xmlFreeTextReader: 2214 * @reader: the xmlTextReaderPtr 2215 * 2216 * Deallocate all the resources associated to the reader 2217 */ 2218 void 2219 xmlFreeTextReader(xmlTextReaderPtr reader) { 2220 if (reader == NULL) 2221 return; 2222 #ifdef LIBXML_SCHEMAS_ENABLED 2223 if (reader->rngSchemas != NULL) { 2224 xmlRelaxNGFree(reader->rngSchemas); 2225 reader->rngSchemas = NULL; 2226 } 2227 if (reader->rngValidCtxt != NULL) { 2228 if (! reader->rngPreserveCtxt) 2229 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 2230 reader->rngValidCtxt = NULL; 2231 } 2232 if (reader->xsdPlug != NULL) { 2233 xmlSchemaSAXUnplug(reader->xsdPlug); 2234 reader->xsdPlug = NULL; 2235 } 2236 if (reader->xsdValidCtxt != NULL) { 2237 if (! reader->xsdPreserveCtxt) 2238 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 2239 reader->xsdValidCtxt = NULL; 2240 } 2241 if (reader->xsdSchemas != NULL) { 2242 xmlSchemaFree(reader->xsdSchemas); 2243 reader->xsdSchemas = NULL; 2244 } 2245 #endif 2246 #ifdef LIBXML_XINCLUDE_ENABLED 2247 if (reader->xincctxt != NULL) 2248 xmlXIncludeFreeContext(reader->xincctxt); 2249 #endif 2250 #ifdef LIBXML_PATTERN_ENABLED 2251 if (reader->patternTab != NULL) { 2252 int i; 2253 for (i = 0;i < reader->patternNr;i++) { 2254 if (reader->patternTab[i] != NULL) 2255 xmlFreePattern(reader->patternTab[i]); 2256 } 2257 xmlFree(reader->patternTab); 2258 } 2259 #endif 2260 if (reader->faketext != NULL) { 2261 xmlFreeNode(reader->faketext); 2262 } 2263 if (reader->ctxt != NULL) { 2264 if (reader->dict == reader->ctxt->dict) 2265 reader->dict = NULL; 2266 if (reader->ctxt->myDoc != NULL) { 2267 if (reader->preserve == 0) 2268 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2269 reader->ctxt->myDoc = NULL; 2270 } 2271 if ((reader->ctxt->vctxt.vstateTab != NULL) && 2272 (reader->ctxt->vctxt.vstateMax > 0)){ 2273 xmlFree(reader->ctxt->vctxt.vstateTab); 2274 reader->ctxt->vctxt.vstateTab = NULL; 2275 reader->ctxt->vctxt.vstateMax = 0; 2276 } 2277 if (reader->allocs & XML_TEXTREADER_CTXT) 2278 xmlFreeParserCtxt(reader->ctxt); 2279 } 2280 if (reader->sax != NULL) 2281 xmlFree(reader->sax); 2282 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) 2283 xmlFreeParserInputBuffer(reader->input); 2284 if (reader->buffer != NULL) 2285 xmlBufFree(reader->buffer); 2286 if (reader->entTab != NULL) 2287 xmlFree(reader->entTab); 2288 if (reader->dict != NULL) 2289 xmlDictFree(reader->dict); 2290 xmlFree(reader); 2291 } 2292 2293 /************************************************************************ 2294 * * 2295 * Methods for XmlTextReader * 2296 * * 2297 ************************************************************************/ 2298 /** 2299 * xmlTextReaderClose: 2300 * @reader: the xmlTextReaderPtr used 2301 * 2302 * This method releases any resources allocated by the current instance 2303 * changes the state to Closed and close any underlying input. 2304 * 2305 * Returns 0 or -1 in case of error 2306 */ 2307 int 2308 xmlTextReaderClose(xmlTextReaderPtr reader) { 2309 if (reader == NULL) 2310 return(-1); 2311 reader->node = NULL; 2312 reader->curnode = NULL; 2313 reader->mode = XML_TEXTREADER_MODE_CLOSED; 2314 if (reader->ctxt != NULL) { 2315 xmlStopParser(reader->ctxt); 2316 if (reader->ctxt->myDoc != NULL) { 2317 if (reader->preserve == 0) 2318 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2319 reader->ctxt->myDoc = NULL; 2320 } 2321 } 2322 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { 2323 xmlFreeParserInputBuffer(reader->input); 2324 reader->allocs -= XML_TEXTREADER_INPUT; 2325 } 2326 return(0); 2327 } 2328 2329 /** 2330 * xmlTextReaderGetAttributeNo: 2331 * @reader: the xmlTextReaderPtr used 2332 * @no: the zero-based index of the attribute relative to the containing element 2333 * 2334 * Provides the value of the attribute with the specified index relative 2335 * to the containing element. 2336 * 2337 * Returns a string containing the value of the specified attribute, or NULL 2338 * in case of error. The string must be deallocated by the caller. 2339 */ 2340 xmlChar * 2341 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { 2342 xmlChar *ret; 2343 int i; 2344 xmlAttrPtr cur; 2345 xmlNsPtr ns; 2346 2347 if (reader == NULL) 2348 return(NULL); 2349 if (reader->node == NULL) 2350 return(NULL); 2351 if (reader->curnode != NULL) 2352 return(NULL); 2353 /* TODO: handle the xmlDecl */ 2354 if (reader->node->type != XML_ELEMENT_NODE) 2355 return(NULL); 2356 2357 ns = reader->node->nsDef; 2358 for (i = 0;(i < no) && (ns != NULL);i++) { 2359 ns = ns->next; 2360 } 2361 if (ns != NULL) 2362 return(xmlStrdup(ns->href)); 2363 2364 cur = reader->node->properties; 2365 if (cur == NULL) 2366 return(NULL); 2367 for (;i < no;i++) { 2368 cur = cur->next; 2369 if (cur == NULL) 2370 return(NULL); 2371 } 2372 /* TODO walk the DTD if present */ 2373 2374 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); 2375 if (ret == NULL) return(xmlStrdup((xmlChar *)"")); 2376 return(ret); 2377 } 2378 2379 /** 2380 * xmlTextReaderGetAttribute: 2381 * @reader: the xmlTextReaderPtr used 2382 * @name: the qualified name of the attribute. 2383 * 2384 * Provides the value of the attribute with the specified qualified name. 2385 * 2386 * Returns a string containing the value of the specified attribute, or NULL 2387 * in case of error. The string must be deallocated by the caller. 2388 */ 2389 xmlChar * 2390 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2391 xmlChar *prefix = NULL; 2392 xmlChar *localname; 2393 xmlNsPtr ns; 2394 xmlChar *ret = NULL; 2395 2396 if ((reader == NULL) || (name == NULL)) 2397 return(NULL); 2398 if (reader->node == NULL) 2399 return(NULL); 2400 if (reader->curnode != NULL) 2401 return(NULL); 2402 2403 /* TODO: handle the xmlDecl */ 2404 if (reader->node->type != XML_ELEMENT_NODE) 2405 return(NULL); 2406 2407 localname = xmlSplitQName2(name, &prefix); 2408 if (localname == NULL) { 2409 /* 2410 * Namespace default decl 2411 */ 2412 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 2413 ns = reader->node->nsDef; 2414 while (ns != NULL) { 2415 if (ns->prefix == NULL) { 2416 return(xmlStrdup(ns->href)); 2417 } 2418 ns = ns->next; 2419 } 2420 return NULL; 2421 } 2422 return(xmlGetNoNsProp(reader->node, name)); 2423 } 2424 2425 /* 2426 * Namespace default decl 2427 */ 2428 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { 2429 ns = reader->node->nsDef; 2430 while (ns != NULL) { 2431 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { 2432 ret = xmlStrdup(ns->href); 2433 break; 2434 } 2435 ns = ns->next; 2436 } 2437 } else { 2438 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2439 if (ns != NULL) 2440 ret = xmlGetNsProp(reader->node, localname, ns->href); 2441 } 2442 2443 xmlFree(localname); 2444 if (prefix != NULL) 2445 xmlFree(prefix); 2446 return(ret); 2447 } 2448 2449 2450 /** 2451 * xmlTextReaderGetAttributeNs: 2452 * @reader: the xmlTextReaderPtr used 2453 * @localName: the local name of the attribute. 2454 * @namespaceURI: the namespace URI of the attribute. 2455 * 2456 * Provides the value of the specified attribute 2457 * 2458 * Returns a string containing the value of the specified attribute, or NULL 2459 * in case of error. The string must be deallocated by the caller. 2460 */ 2461 xmlChar * 2462 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, 2463 const xmlChar *namespaceURI) { 2464 xmlChar *prefix = NULL; 2465 xmlNsPtr ns; 2466 2467 if ((reader == NULL) || (localName == NULL)) 2468 return(NULL); 2469 if (reader->node == NULL) 2470 return(NULL); 2471 if (reader->curnode != NULL) 2472 return(NULL); 2473 2474 /* TODO: handle the xmlDecl */ 2475 if (reader->node->type != XML_ELEMENT_NODE) 2476 return(NULL); 2477 2478 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { 2479 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { 2480 prefix = BAD_CAST localName; 2481 } 2482 ns = reader->node->nsDef; 2483 while (ns != NULL) { 2484 if ((prefix == NULL && ns->prefix == NULL) || 2485 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { 2486 return xmlStrdup(ns->href); 2487 } 2488 ns = ns->next; 2489 } 2490 return NULL; 2491 } 2492 2493 return(xmlGetNsProp(reader->node, localName, namespaceURI)); 2494 } 2495 2496 /** 2497 * xmlTextReaderGetRemainder: 2498 * @reader: the xmlTextReaderPtr used 2499 * 2500 * Method to get the remainder of the buffered XML. this method stops the 2501 * parser, set its state to End Of File and return the input stream with 2502 * what is left that the parser did not use. 2503 * 2504 * The implementation is not good, the parser certainly procgressed past 2505 * what's left in reader->input, and there is an allocation problem. Best 2506 * would be to rewrite it differently. 2507 * 2508 * Returns the xmlParserInputBufferPtr attached to the XML or NULL 2509 * in case of error. 2510 */ 2511 xmlParserInputBufferPtr 2512 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { 2513 xmlParserInputBufferPtr ret = NULL; 2514 2515 if (reader == NULL) 2516 return(NULL); 2517 if (reader->node == NULL) 2518 return(NULL); 2519 2520 reader->node = NULL; 2521 reader->curnode = NULL; 2522 reader->mode = XML_TEXTREADER_MODE_EOF; 2523 if (reader->ctxt != NULL) { 2524 xmlStopParser(reader->ctxt); 2525 if (reader->ctxt->myDoc != NULL) { 2526 if (reader->preserve == 0) 2527 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2528 reader->ctxt->myDoc = NULL; 2529 } 2530 } 2531 if (reader->allocs & XML_TEXTREADER_INPUT) { 2532 ret = reader->input; 2533 reader->input = NULL; 2534 reader->allocs -= XML_TEXTREADER_INPUT; 2535 } else { 2536 /* 2537 * Hum, one may need to duplicate the data structure because 2538 * without reference counting the input may be freed twice: 2539 * - by the layer which allocated it. 2540 * - by the layer to which would have been returned to. 2541 */ 2542 TODO 2543 return(NULL); 2544 } 2545 return(ret); 2546 } 2547 2548 /** 2549 * xmlTextReaderLookupNamespace: 2550 * @reader: the xmlTextReaderPtr used 2551 * @prefix: the prefix whose namespace URI is to be resolved. To return 2552 * the default namespace, specify NULL 2553 * 2554 * Resolves a namespace prefix in the scope of the current element. 2555 * 2556 * Returns a string containing the namespace URI to which the prefix maps 2557 * or NULL in case of error. The string must be deallocated by the caller. 2558 */ 2559 xmlChar * 2560 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { 2561 xmlNsPtr ns; 2562 2563 if (reader == NULL) 2564 return(NULL); 2565 if (reader->node == NULL) 2566 return(NULL); 2567 2568 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2569 if (ns == NULL) 2570 return(NULL); 2571 return(xmlStrdup(ns->href)); 2572 } 2573 2574 /** 2575 * xmlTextReaderMoveToAttributeNo: 2576 * @reader: the xmlTextReaderPtr used 2577 * @no: the zero-based index of the attribute relative to the containing 2578 * element. 2579 * 2580 * Moves the position of the current instance to the attribute with 2581 * the specified index relative to the containing element. 2582 * 2583 * Returns 1 in case of success, -1 in case of error, 0 if not found 2584 */ 2585 int 2586 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { 2587 int i; 2588 xmlAttrPtr cur; 2589 xmlNsPtr ns; 2590 2591 if (reader == NULL) 2592 return(-1); 2593 if (reader->node == NULL) 2594 return(-1); 2595 /* TODO: handle the xmlDecl */ 2596 if (reader->node->type != XML_ELEMENT_NODE) 2597 return(-1); 2598 2599 reader->curnode = NULL; 2600 2601 ns = reader->node->nsDef; 2602 for (i = 0;(i < no) && (ns != NULL);i++) { 2603 ns = ns->next; 2604 } 2605 if (ns != NULL) { 2606 reader->curnode = (xmlNodePtr) ns; 2607 return(1); 2608 } 2609 2610 cur = reader->node->properties; 2611 if (cur == NULL) 2612 return(0); 2613 for (;i < no;i++) { 2614 cur = cur->next; 2615 if (cur == NULL) 2616 return(0); 2617 } 2618 /* TODO walk the DTD if present */ 2619 2620 reader->curnode = (xmlNodePtr) cur; 2621 return(1); 2622 } 2623 2624 /** 2625 * xmlTextReaderMoveToAttribute: 2626 * @reader: the xmlTextReaderPtr used 2627 * @name: the qualified name of the attribute. 2628 * 2629 * Moves the position of the current instance to the attribute with 2630 * the specified qualified name. 2631 * 2632 * Returns 1 in case of success, -1 in case of error, 0 if not found 2633 */ 2634 int 2635 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2636 xmlChar *prefix = NULL; 2637 xmlChar *localname; 2638 xmlNsPtr ns; 2639 xmlAttrPtr prop; 2640 2641 if ((reader == NULL) || (name == NULL)) 2642 return(-1); 2643 if (reader->node == NULL) 2644 return(-1); 2645 2646 /* TODO: handle the xmlDecl */ 2647 if (reader->node->type != XML_ELEMENT_NODE) 2648 return(0); 2649 2650 localname = xmlSplitQName2(name, &prefix); 2651 if (localname == NULL) { 2652 /* 2653 * Namespace default decl 2654 */ 2655 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 2656 ns = reader->node->nsDef; 2657 while (ns != NULL) { 2658 if (ns->prefix == NULL) { 2659 reader->curnode = (xmlNodePtr) ns; 2660 return(1); 2661 } 2662 ns = ns->next; 2663 } 2664 return(0); 2665 } 2666 2667 prop = reader->node->properties; 2668 while (prop != NULL) { 2669 /* 2670 * One need to have 2671 * - same attribute names 2672 * - and the attribute carrying that namespace 2673 */ 2674 if ((xmlStrEqual(prop->name, name)) && 2675 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { 2676 reader->curnode = (xmlNodePtr) prop; 2677 return(1); 2678 } 2679 prop = prop->next; 2680 } 2681 return(0); 2682 } 2683 2684 /* 2685 * Namespace default decl 2686 */ 2687 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { 2688 ns = reader->node->nsDef; 2689 while (ns != NULL) { 2690 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { 2691 reader->curnode = (xmlNodePtr) ns; 2692 goto found; 2693 } 2694 ns = ns->next; 2695 } 2696 goto not_found; 2697 } 2698 prop = reader->node->properties; 2699 while (prop != NULL) { 2700 /* 2701 * One need to have 2702 * - same attribute names 2703 * - and the attribute carrying that namespace 2704 */ 2705 if ((xmlStrEqual(prop->name, localname)) && 2706 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) { 2707 reader->curnode = (xmlNodePtr) prop; 2708 goto found; 2709 } 2710 prop = prop->next; 2711 } 2712 not_found: 2713 if (localname != NULL) 2714 xmlFree(localname); 2715 if (prefix != NULL) 2716 xmlFree(prefix); 2717 return(0); 2718 2719 found: 2720 if (localname != NULL) 2721 xmlFree(localname); 2722 if (prefix != NULL) 2723 xmlFree(prefix); 2724 return(1); 2725 } 2726 2727 /** 2728 * xmlTextReaderMoveToAttributeNs: 2729 * @reader: the xmlTextReaderPtr used 2730 * @localName: the local name of the attribute. 2731 * @namespaceURI: the namespace URI of the attribute. 2732 * 2733 * Moves the position of the current instance to the attribute with the 2734 * specified local name and namespace URI. 2735 * 2736 * Returns 1 in case of success, -1 in case of error, 0 if not found 2737 */ 2738 int 2739 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, 2740 const xmlChar *localName, const xmlChar *namespaceURI) { 2741 xmlAttrPtr prop; 2742 xmlNodePtr node; 2743 xmlNsPtr ns; 2744 xmlChar *prefix = NULL; 2745 2746 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL)) 2747 return(-1); 2748 if (reader->node == NULL) 2749 return(-1); 2750 if (reader->node->type != XML_ELEMENT_NODE) 2751 return(0); 2752 node = reader->node; 2753 2754 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { 2755 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { 2756 prefix = BAD_CAST localName; 2757 } 2758 ns = reader->node->nsDef; 2759 while (ns != NULL) { 2760 if ((prefix == NULL && ns->prefix == NULL) || 2761 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { 2762 reader->curnode = (xmlNodePtr) ns; 2763 return(1); 2764 } 2765 ns = ns->next; 2766 } 2767 return(0); 2768 } 2769 2770 prop = node->properties; 2771 while (prop != NULL) { 2772 /* 2773 * One need to have 2774 * - same attribute names 2775 * - and the attribute carrying that namespace 2776 */ 2777 if (xmlStrEqual(prop->name, localName) && 2778 ((prop->ns != NULL) && 2779 (xmlStrEqual(prop->ns->href, namespaceURI)))) { 2780 reader->curnode = (xmlNodePtr) prop; 2781 return(1); 2782 } 2783 prop = prop->next; 2784 } 2785 return(0); 2786 } 2787 2788 /** 2789 * xmlTextReaderMoveToFirstAttribute: 2790 * @reader: the xmlTextReaderPtr used 2791 * 2792 * Moves the position of the current instance to the first attribute 2793 * associated with the current node. 2794 * 2795 * Returns 1 in case of success, -1 in case of error, 0 if not found 2796 */ 2797 int 2798 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) { 2799 if (reader == NULL) 2800 return(-1); 2801 if (reader->node == NULL) 2802 return(-1); 2803 if (reader->node->type != XML_ELEMENT_NODE) 2804 return(0); 2805 2806 if (reader->node->nsDef != NULL) { 2807 reader->curnode = (xmlNodePtr) reader->node->nsDef; 2808 return(1); 2809 } 2810 if (reader->node->properties != NULL) { 2811 reader->curnode = (xmlNodePtr) reader->node->properties; 2812 return(1); 2813 } 2814 return(0); 2815 } 2816 2817 /** 2818 * xmlTextReaderMoveToNextAttribute: 2819 * @reader: the xmlTextReaderPtr used 2820 * 2821 * Moves the position of the current instance to the next attribute 2822 * associated with the current node. 2823 * 2824 * Returns 1 in case of success, -1 in case of error, 0 if not found 2825 */ 2826 int 2827 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) { 2828 if (reader == NULL) 2829 return(-1); 2830 if (reader->node == NULL) 2831 return(-1); 2832 if (reader->node->type != XML_ELEMENT_NODE) 2833 return(0); 2834 if (reader->curnode == NULL) 2835 return(xmlTextReaderMoveToFirstAttribute(reader)); 2836 2837 if (reader->curnode->type == XML_NAMESPACE_DECL) { 2838 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2839 if (ns->next != NULL) { 2840 reader->curnode = (xmlNodePtr) ns->next; 2841 return(1); 2842 } 2843 if (reader->node->properties != NULL) { 2844 reader->curnode = (xmlNodePtr) reader->node->properties; 2845 return(1); 2846 } 2847 return(0); 2848 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) && 2849 (reader->curnode->next != NULL)) { 2850 reader->curnode = reader->curnode->next; 2851 return(1); 2852 } 2853 return(0); 2854 } 2855 2856 /** 2857 * xmlTextReaderMoveToElement: 2858 * @reader: the xmlTextReaderPtr used 2859 * 2860 * Moves the position of the current instance to the node that 2861 * contains the current Attribute node. 2862 * 2863 * Returns 1 in case of success, -1 in case of error, 0 if not moved 2864 */ 2865 int 2866 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) { 2867 if (reader == NULL) 2868 return(-1); 2869 if (reader->node == NULL) 2870 return(-1); 2871 if (reader->node->type != XML_ELEMENT_NODE) 2872 return(0); 2873 if (reader->curnode != NULL) { 2874 reader->curnode = NULL; 2875 return(1); 2876 } 2877 return(0); 2878 } 2879 2880 /** 2881 * xmlTextReaderReadAttributeValue: 2882 * @reader: the xmlTextReaderPtr used 2883 * 2884 * Parses an attribute value into one or more Text and EntityReference nodes. 2885 * 2886 * Returns 1 in case of success, 0 if the reader was not positionned on an 2887 * ttribute node or all the attribute values have been read, or -1 2888 * in case of error. 2889 */ 2890 int 2891 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { 2892 if (reader == NULL) 2893 return(-1); 2894 if (reader->node == NULL) 2895 return(-1); 2896 if (reader->curnode == NULL) 2897 return(0); 2898 if (reader->curnode->type == XML_ATTRIBUTE_NODE) { 2899 if (reader->curnode->children == NULL) 2900 return(0); 2901 reader->curnode = reader->curnode->children; 2902 } else if (reader->curnode->type == XML_NAMESPACE_DECL) { 2903 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2904 2905 if (reader->faketext == NULL) { 2906 reader->faketext = xmlNewDocText(reader->node->doc, 2907 ns->href); 2908 } else { 2909 if ((reader->faketext->content != NULL) && 2910 (reader->faketext->content != 2911 (xmlChar *) &(reader->faketext->properties))) 2912 xmlFree(reader->faketext->content); 2913 reader->faketext->content = xmlStrdup(ns->href); 2914 } 2915 reader->curnode = reader->faketext; 2916 } else { 2917 if (reader->curnode->next == NULL) 2918 return(0); 2919 reader->curnode = reader->curnode->next; 2920 } 2921 return(1); 2922 } 2923 2924 /** 2925 * xmlTextReaderConstEncoding: 2926 * @reader: the xmlTextReaderPtr used 2927 * 2928 * Determine the encoding of the document being read. 2929 * 2930 * Returns a string containing the encoding of the document or NULL in 2931 * case of error. The string is deallocated with the reader. 2932 */ 2933 const xmlChar * 2934 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { 2935 xmlDocPtr doc = NULL; 2936 if (reader == NULL) 2937 return(NULL); 2938 if (reader->doc != NULL) 2939 doc = reader->doc; 2940 else if (reader->ctxt != NULL) 2941 doc = reader->ctxt->myDoc; 2942 if (doc == NULL) 2943 return(NULL); 2944 2945 if (doc->encoding == NULL) 2946 return(NULL); 2947 else 2948 return(CONSTSTR(doc->encoding)); 2949 } 2950 2951 2952 /************************************************************************ 2953 * * 2954 * Acces API to the current node * 2955 * * 2956 ************************************************************************/ 2957 /** 2958 * xmlTextReaderAttributeCount: 2959 * @reader: the xmlTextReaderPtr used 2960 * 2961 * Provides the number of attributes of the current node 2962 * 2963 * Returns 0 i no attributes, -1 in case of error or the attribute count 2964 */ 2965 int 2966 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) { 2967 int ret; 2968 xmlAttrPtr attr; 2969 xmlNsPtr ns; 2970 xmlNodePtr node; 2971 2972 if (reader == NULL) 2973 return(-1); 2974 if (reader->node == NULL) 2975 return(0); 2976 2977 if (reader->curnode != NULL) 2978 node = reader->curnode; 2979 else 2980 node = reader->node; 2981 2982 if (node->type != XML_ELEMENT_NODE) 2983 return(0); 2984 if ((reader->state == XML_TEXTREADER_END) || 2985 (reader->state == XML_TEXTREADER_BACKTRACK)) 2986 return(0); 2987 ret = 0; 2988 attr = node->properties; 2989 while (attr != NULL) { 2990 ret++; 2991 attr = attr->next; 2992 } 2993 ns = node->nsDef; 2994 while (ns != NULL) { 2995 ret++; 2996 ns = ns->next; 2997 } 2998 return(ret); 2999 } 3000 3001 /** 3002 * xmlTextReaderNodeType: 3003 * @reader: the xmlTextReaderPtr used 3004 * 3005 * Get the node type of the current node 3006 * Reference: 3007 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html 3008 * 3009 * Returns the xmlNodeType of the current node or -1 in case of error 3010 */ 3011 int 3012 xmlTextReaderNodeType(xmlTextReaderPtr reader) { 3013 xmlNodePtr node; 3014 3015 if (reader == NULL) 3016 return(-1); 3017 if (reader->node == NULL) 3018 return(XML_READER_TYPE_NONE); 3019 if (reader->curnode != NULL) 3020 node = reader->curnode; 3021 else 3022 node = reader->node; 3023 switch (node->type) { 3024 case XML_ELEMENT_NODE: 3025 if ((reader->state == XML_TEXTREADER_END) || 3026 (reader->state == XML_TEXTREADER_BACKTRACK)) 3027 return(XML_READER_TYPE_END_ELEMENT); 3028 return(XML_READER_TYPE_ELEMENT); 3029 case XML_NAMESPACE_DECL: 3030 case XML_ATTRIBUTE_NODE: 3031 return(XML_READER_TYPE_ATTRIBUTE); 3032 case XML_TEXT_NODE: 3033 if (xmlIsBlankNode(reader->node)) { 3034 if (xmlNodeGetSpacePreserve(reader->node)) 3035 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE); 3036 else 3037 return(XML_READER_TYPE_WHITESPACE); 3038 } else { 3039 return(XML_READER_TYPE_TEXT); 3040 } 3041 case XML_CDATA_SECTION_NODE: 3042 return(XML_READER_TYPE_CDATA); 3043 case XML_ENTITY_REF_NODE: 3044 return(XML_READER_TYPE_ENTITY_REFERENCE); 3045 case XML_ENTITY_NODE: 3046 return(XML_READER_TYPE_ENTITY); 3047 case XML_PI_NODE: 3048 return(XML_READER_TYPE_PROCESSING_INSTRUCTION); 3049 case XML_COMMENT_NODE: 3050 return(XML_READER_TYPE_COMMENT); 3051 case XML_DOCUMENT_NODE: 3052 case XML_HTML_DOCUMENT_NODE: 3053 #ifdef LIBXML_DOCB_ENABLED 3054 case XML_DOCB_DOCUMENT_NODE: 3055 #endif 3056 return(XML_READER_TYPE_DOCUMENT); 3057 case XML_DOCUMENT_FRAG_NODE: 3058 return(XML_READER_TYPE_DOCUMENT_FRAGMENT); 3059 case XML_NOTATION_NODE: 3060 return(XML_READER_TYPE_NOTATION); 3061 case XML_DOCUMENT_TYPE_NODE: 3062 case XML_DTD_NODE: 3063 return(XML_READER_TYPE_DOCUMENT_TYPE); 3064 3065 case XML_ELEMENT_DECL: 3066 case XML_ATTRIBUTE_DECL: 3067 case XML_ENTITY_DECL: 3068 case XML_XINCLUDE_START: 3069 case XML_XINCLUDE_END: 3070 return(XML_READER_TYPE_NONE); 3071 } 3072 return(-1); 3073 } 3074 3075 /** 3076 * xmlTextReaderIsEmptyElement: 3077 * @reader: the xmlTextReaderPtr used 3078 * 3079 * Check if the current node is empty 3080 * 3081 * Returns 1 if empty, 0 if not and -1 in case of error 3082 */ 3083 int 3084 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) { 3085 if ((reader == NULL) || (reader->node == NULL)) 3086 return(-1); 3087 if (reader->node->type != XML_ELEMENT_NODE) 3088 return(0); 3089 if (reader->curnode != NULL) 3090 return(0); 3091 if (reader->node->children != NULL) 3092 return(0); 3093 if (reader->state == XML_TEXTREADER_END) 3094 return(0); 3095 if (reader->doc != NULL) 3096 return(1); 3097 #ifdef LIBXML_XINCLUDE_ENABLED 3098 if (reader->in_xinclude > 0) 3099 return(1); 3100 #endif 3101 return((reader->node->extra & NODE_IS_EMPTY) != 0); 3102 } 3103 3104 /** 3105 * xmlTextReaderLocalName: 3106 * @reader: the xmlTextReaderPtr used 3107 * 3108 * The local name of the node. 3109 * 3110 * Returns the local name or NULL if not available, 3111 * if non NULL it need to be freed by the caller. 3112 */ 3113 xmlChar * 3114 xmlTextReaderLocalName(xmlTextReaderPtr reader) { 3115 xmlNodePtr node; 3116 if ((reader == NULL) || (reader->node == NULL)) 3117 return(NULL); 3118 if (reader->curnode != NULL) 3119 node = reader->curnode; 3120 else 3121 node = reader->node; 3122 if (node->type == XML_NAMESPACE_DECL) { 3123 xmlNsPtr ns = (xmlNsPtr) node; 3124 if (ns->prefix == NULL) 3125 return(xmlStrdup(BAD_CAST "xmlns")); 3126 else 3127 return(xmlStrdup(ns->prefix)); 3128 } 3129 if ((node->type != XML_ELEMENT_NODE) && 3130 (node->type != XML_ATTRIBUTE_NODE)) 3131 return(xmlTextReaderName(reader)); 3132 return(xmlStrdup(node->name)); 3133 } 3134 3135 /** 3136 * xmlTextReaderConstLocalName: 3137 * @reader: the xmlTextReaderPtr used 3138 * 3139 * The local name of the node. 3140 * 3141 * Returns the local name or NULL if not available, the 3142 * string will be deallocated with the reader. 3143 */ 3144 const xmlChar * 3145 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { 3146 xmlNodePtr node; 3147 if ((reader == NULL) || (reader->node == NULL)) 3148 return(NULL); 3149 if (reader->curnode != NULL) 3150 node = reader->curnode; 3151 else 3152 node = reader->node; 3153 if (node->type == XML_NAMESPACE_DECL) { 3154 xmlNsPtr ns = (xmlNsPtr) node; 3155 if (ns->prefix == NULL) 3156 return(CONSTSTR(BAD_CAST "xmlns")); 3157 else 3158 return(ns->prefix); 3159 } 3160 if ((node->type != XML_ELEMENT_NODE) && 3161 (node->type != XML_ATTRIBUTE_NODE)) 3162 return(xmlTextReaderConstName(reader)); 3163 return(node->name); 3164 } 3165 3166 /** 3167 * xmlTextReaderName: 3168 * @reader: the xmlTextReaderPtr used 3169 * 3170 * The qualified name of the node, equal to Prefix :LocalName. 3171 * 3172 * Returns the local name or NULL if not available, 3173 * if non NULL it need to be freed by the caller. 3174 */ 3175 xmlChar * 3176 xmlTextReaderName(xmlTextReaderPtr reader) { 3177 xmlNodePtr node; 3178 xmlChar *ret; 3179 3180 if ((reader == NULL) || (reader->node == NULL)) 3181 return(NULL); 3182 if (reader->curnode != NULL) 3183 node = reader->curnode; 3184 else 3185 node = reader->node; 3186 switch (node->type) { 3187 case XML_ELEMENT_NODE: 3188 case XML_ATTRIBUTE_NODE: 3189 if ((node->ns == NULL) || 3190 (node->ns->prefix == NULL)) 3191 return(xmlStrdup(node->name)); 3192 3193 ret = xmlStrdup(node->ns->prefix); 3194 ret = xmlStrcat(ret, BAD_CAST ":"); 3195 ret = xmlStrcat(ret, node->name); 3196 return(ret); 3197 case XML_TEXT_NODE: 3198 return(xmlStrdup(BAD_CAST "#text")); 3199 case XML_CDATA_SECTION_NODE: 3200 return(xmlStrdup(BAD_CAST "#cdata-section")); 3201 case XML_ENTITY_NODE: 3202 case XML_ENTITY_REF_NODE: 3203 return(xmlStrdup(node->name)); 3204 case XML_PI_NODE: 3205 return(xmlStrdup(node->name)); 3206 case XML_COMMENT_NODE: 3207 return(xmlStrdup(BAD_CAST "#comment")); 3208 case XML_DOCUMENT_NODE: 3209 case XML_HTML_DOCUMENT_NODE: 3210 #ifdef LIBXML_DOCB_ENABLED 3211 case XML_DOCB_DOCUMENT_NODE: 3212 #endif 3213 return(xmlStrdup(BAD_CAST "#document")); 3214 case XML_DOCUMENT_FRAG_NODE: 3215 return(xmlStrdup(BAD_CAST "#document-fragment")); 3216 case XML_NOTATION_NODE: 3217 return(xmlStrdup(node->name)); 3218 case XML_DOCUMENT_TYPE_NODE: 3219 case XML_DTD_NODE: 3220 return(xmlStrdup(node->name)); 3221 case XML_NAMESPACE_DECL: { 3222 xmlNsPtr ns = (xmlNsPtr) node; 3223 3224 ret = xmlStrdup(BAD_CAST "xmlns"); 3225 if (ns->prefix == NULL) 3226 return(ret); 3227 ret = xmlStrcat(ret, BAD_CAST ":"); 3228 ret = xmlStrcat(ret, ns->prefix); 3229 return(ret); 3230 } 3231 3232 case XML_ELEMENT_DECL: 3233 case XML_ATTRIBUTE_DECL: 3234 case XML_ENTITY_DECL: 3235 case XML_XINCLUDE_START: 3236 case XML_XINCLUDE_END: 3237 return(NULL); 3238 } 3239 return(NULL); 3240 } 3241 3242 /** 3243 * xmlTextReaderConstName: 3244 * @reader: the xmlTextReaderPtr used 3245 * 3246 * The qualified name of the node, equal to Prefix :LocalName. 3247 * 3248 * Returns the local name or NULL if not available, the string is 3249 * deallocated with the reader. 3250 */ 3251 const xmlChar * 3252 xmlTextReaderConstName(xmlTextReaderPtr reader) { 3253 xmlNodePtr node; 3254 3255 if ((reader == NULL) || (reader->node == NULL)) 3256 return(NULL); 3257 if (reader->curnode != NULL) 3258 node = reader->curnode; 3259 else 3260 node = reader->node; 3261 switch (node->type) { 3262 case XML_ELEMENT_NODE: 3263 case XML_ATTRIBUTE_NODE: 3264 if ((node->ns == NULL) || 3265 (node->ns->prefix == NULL)) 3266 return(node->name); 3267 return(CONSTQSTR(node->ns->prefix, node->name)); 3268 case XML_TEXT_NODE: 3269 return(CONSTSTR(BAD_CAST "#text")); 3270 case XML_CDATA_SECTION_NODE: 3271 return(CONSTSTR(BAD_CAST "#cdata-section")); 3272 case XML_ENTITY_NODE: 3273 case XML_ENTITY_REF_NODE: 3274 return(CONSTSTR(node->name)); 3275 case XML_PI_NODE: 3276 return(CONSTSTR(node->name)); 3277 case XML_COMMENT_NODE: 3278 return(CONSTSTR(BAD_CAST "#comment")); 3279 case XML_DOCUMENT_NODE: 3280 case XML_HTML_DOCUMENT_NODE: 3281 #ifdef LIBXML_DOCB_ENABLED 3282 case XML_DOCB_DOCUMENT_NODE: 3283 #endif 3284 return(CONSTSTR(BAD_CAST "#document")); 3285 case XML_DOCUMENT_FRAG_NODE: 3286 return(CONSTSTR(BAD_CAST "#document-fragment")); 3287 case XML_NOTATION_NODE: 3288 return(CONSTSTR(node->name)); 3289 case XML_DOCUMENT_TYPE_NODE: 3290 case XML_DTD_NODE: 3291 return(CONSTSTR(node->name)); 3292 case XML_NAMESPACE_DECL: { 3293 xmlNsPtr ns = (xmlNsPtr) node; 3294 3295 if (ns->prefix == NULL) 3296 return(CONSTSTR(BAD_CAST "xmlns")); 3297 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); 3298 } 3299 3300 case XML_ELEMENT_DECL: 3301 case XML_ATTRIBUTE_DECL: 3302 case XML_ENTITY_DECL: 3303 case XML_XINCLUDE_START: 3304 case XML_XINCLUDE_END: 3305 return(NULL); 3306 } 3307 return(NULL); 3308 } 3309 3310 /** 3311 * xmlTextReaderPrefix: 3312 * @reader: the xmlTextReaderPtr used 3313 * 3314 * A shorthand reference to the namespace associated with the node. 3315 * 3316 * Returns the prefix or NULL if not available, 3317 * if non NULL it need to be freed by the caller. 3318 */ 3319 xmlChar * 3320 xmlTextReaderPrefix(xmlTextReaderPtr reader) { 3321 xmlNodePtr node; 3322 if ((reader == NULL) || (reader->node == NULL)) 3323 return(NULL); 3324 if (reader->curnode != NULL) 3325 node = reader->curnode; 3326 else 3327 node = reader->node; 3328 if (node->type == XML_NAMESPACE_DECL) { 3329 xmlNsPtr ns = (xmlNsPtr) node; 3330 if (ns->prefix == NULL) 3331 return(NULL); 3332 return(xmlStrdup(BAD_CAST "xmlns")); 3333 } 3334 if ((node->type != XML_ELEMENT_NODE) && 3335 (node->type != XML_ATTRIBUTE_NODE)) 3336 return(NULL); 3337 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 3338 return(xmlStrdup(node->ns->prefix)); 3339 return(NULL); 3340 } 3341 3342 /** 3343 * xmlTextReaderConstPrefix: 3344 * @reader: the xmlTextReaderPtr used 3345 * 3346 * A shorthand reference to the namespace associated with the node. 3347 * 3348 * Returns the prefix or NULL if not available, the string is deallocated 3349 * with the reader. 3350 */ 3351 const xmlChar * 3352 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { 3353 xmlNodePtr node; 3354 if ((reader == NULL) || (reader->node == NULL)) 3355 return(NULL); 3356 if (reader->curnode != NULL) 3357 node = reader->curnode; 3358 else 3359 node = reader->node; 3360 if (node->type == XML_NAMESPACE_DECL) { 3361 xmlNsPtr ns = (xmlNsPtr) node; 3362 if (ns->prefix == NULL) 3363 return(NULL); 3364 return(CONSTSTR(BAD_CAST "xmlns")); 3365 } 3366 if ((node->type != XML_ELEMENT_NODE) && 3367 (node->type != XML_ATTRIBUTE_NODE)) 3368 return(NULL); 3369 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 3370 return(CONSTSTR(node->ns->prefix)); 3371 return(NULL); 3372 } 3373 3374 /** 3375 * xmlTextReaderNamespaceUri: 3376 * @reader: the xmlTextReaderPtr used 3377 * 3378 * The URI defining the namespace associated with the node. 3379 * 3380 * Returns the namespace URI or NULL if not available, 3381 * if non NULL it need to be freed by the caller. 3382 */ 3383 xmlChar * 3384 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { 3385 xmlNodePtr node; 3386 if ((reader == NULL) || (reader->node == NULL)) 3387 return(NULL); 3388 if (reader->curnode != NULL) 3389 node = reader->curnode; 3390 else 3391 node = reader->node; 3392 if (node->type == XML_NAMESPACE_DECL) 3393 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3394 if ((node->type != XML_ELEMENT_NODE) && 3395 (node->type != XML_ATTRIBUTE_NODE)) 3396 return(NULL); 3397 if (node->ns != NULL) 3398 return(xmlStrdup(node->ns->href)); 3399 return(NULL); 3400 } 3401 3402 /** 3403 * xmlTextReaderConstNamespaceUri: 3404 * @reader: the xmlTextReaderPtr used 3405 * 3406 * The URI defining the namespace associated with the node. 3407 * 3408 * Returns the namespace URI or NULL if not available, the string 3409 * will be deallocated with the reader 3410 */ 3411 const xmlChar * 3412 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { 3413 xmlNodePtr node; 3414 if ((reader == NULL) || (reader->node == NULL)) 3415 return(NULL); 3416 if (reader->curnode != NULL) 3417 node = reader->curnode; 3418 else 3419 node = reader->node; 3420 if (node->type == XML_NAMESPACE_DECL) 3421 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3422 if ((node->type != XML_ELEMENT_NODE) && 3423 (node->type != XML_ATTRIBUTE_NODE)) 3424 return(NULL); 3425 if (node->ns != NULL) 3426 return(CONSTSTR(node->ns->href)); 3427 return(NULL); 3428 } 3429 3430 /** 3431 * xmlTextReaderBaseUri: 3432 * @reader: the xmlTextReaderPtr used 3433 * 3434 * The base URI of the node. 3435 * 3436 * Returns the base URI or NULL if not available, 3437 * if non NULL it need to be freed by the caller. 3438 */ 3439 xmlChar * 3440 xmlTextReaderBaseUri(xmlTextReaderPtr reader) { 3441 if ((reader == NULL) || (reader->node == NULL)) 3442 return(NULL); 3443 return(xmlNodeGetBase(NULL, reader->node)); 3444 } 3445 3446 /** 3447 * xmlTextReaderConstBaseUri: 3448 * @reader: the xmlTextReaderPtr used 3449 * 3450 * The base URI of the node. 3451 * 3452 * Returns the base URI or NULL if not available, the string 3453 * will be deallocated with the reader 3454 */ 3455 const xmlChar * 3456 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { 3457 xmlChar *tmp; 3458 const xmlChar *ret; 3459 3460 if ((reader == NULL) || (reader->node == NULL)) 3461 return(NULL); 3462 tmp = xmlNodeGetBase(NULL, reader->node); 3463 if (tmp == NULL) 3464 return(NULL); 3465 ret = CONSTSTR(tmp); 3466 xmlFree(tmp); 3467 return(ret); 3468 } 3469 3470 /** 3471 * xmlTextReaderDepth: 3472 * @reader: the xmlTextReaderPtr used 3473 * 3474 * The depth of the node in the tree. 3475 * 3476 * Returns the depth or -1 in case of error 3477 */ 3478 int 3479 xmlTextReaderDepth(xmlTextReaderPtr reader) { 3480 if (reader == NULL) 3481 return(-1); 3482 if (reader->node == NULL) 3483 return(0); 3484 3485 if (reader->curnode != NULL) { 3486 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) || 3487 (reader->curnode->type == XML_NAMESPACE_DECL)) 3488 return(reader->depth + 1); 3489 return(reader->depth + 2); 3490 } 3491 return(reader->depth); 3492 } 3493 3494 /** 3495 * xmlTextReaderHasAttributes: 3496 * @reader: the xmlTextReaderPtr used 3497 * 3498 * Whether the node has attributes. 3499 * 3500 * Returns 1 if true, 0 if false, and -1 in case or error 3501 */ 3502 int 3503 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) { 3504 xmlNodePtr node; 3505 if (reader == NULL) 3506 return(-1); 3507 if (reader->node == NULL) 3508 return(0); 3509 if (reader->curnode != NULL) 3510 node = reader->curnode; 3511 else 3512 node = reader->node; 3513 3514 if ((node->type == XML_ELEMENT_NODE) && 3515 ((node->properties != NULL) || (node->nsDef != NULL))) 3516 return(1); 3517 /* TODO: handle the xmlDecl */ 3518 return(0); 3519 } 3520 3521 /** 3522 * xmlTextReaderHasValue: 3523 * @reader: the xmlTextReaderPtr used 3524 * 3525 * Whether the node can have a text value. 3526 * 3527 * Returns 1 if true, 0 if false, and -1 in case or error 3528 */ 3529 int 3530 xmlTextReaderHasValue(xmlTextReaderPtr reader) { 3531 xmlNodePtr node; 3532 if (reader == NULL) 3533 return(-1); 3534 if (reader->node == NULL) 3535 return(0); 3536 if (reader->curnode != NULL) 3537 node = reader->curnode; 3538 else 3539 node = reader->node; 3540 3541 switch (node->type) { 3542 case XML_ATTRIBUTE_NODE: 3543 case XML_TEXT_NODE: 3544 case XML_CDATA_SECTION_NODE: 3545 case XML_PI_NODE: 3546 case XML_COMMENT_NODE: 3547 case XML_NAMESPACE_DECL: 3548 return(1); 3549 default: 3550 break; 3551 } 3552 return(0); 3553 } 3554 3555 /** 3556 * xmlTextReaderValue: 3557 * @reader: the xmlTextReaderPtr used 3558 * 3559 * Provides the text value of the node if present 3560 * 3561 * Returns the string or NULL if not available. The result must be deallocated 3562 * with xmlFree() 3563 */ 3564 xmlChar * 3565 xmlTextReaderValue(xmlTextReaderPtr reader) { 3566 xmlNodePtr node; 3567 if (reader == NULL) 3568 return(NULL); 3569 if (reader->node == NULL) 3570 return(NULL); 3571 if (reader->curnode != NULL) 3572 node = reader->curnode; 3573 else 3574 node = reader->node; 3575 3576 switch (node->type) { 3577 case XML_NAMESPACE_DECL: 3578 return(xmlStrdup(((xmlNsPtr) node)->href)); 3579 case XML_ATTRIBUTE_NODE:{ 3580 xmlAttrPtr attr = (xmlAttrPtr) node; 3581 3582 if (attr->parent != NULL) 3583 return (xmlNodeListGetString 3584 (attr->parent->doc, attr->children, 1)); 3585 else 3586 return (xmlNodeListGetString(NULL, attr->children, 1)); 3587 break; 3588 } 3589 case XML_TEXT_NODE: 3590 case XML_CDATA_SECTION_NODE: 3591 case XML_PI_NODE: 3592 case XML_COMMENT_NODE: 3593 if (node->content != NULL) 3594 return (xmlStrdup(node->content)); 3595 default: 3596 break; 3597 } 3598 return(NULL); 3599 } 3600 3601 /** 3602 * xmlTextReaderConstValue: 3603 * @reader: the xmlTextReaderPtr used 3604 * 3605 * Provides the text value of the node if present 3606 * 3607 * Returns the string or NULL if not available. The result will be 3608 * deallocated on the next Read() operation. 3609 */ 3610 const xmlChar * 3611 xmlTextReaderConstValue(xmlTextReaderPtr reader) { 3612 xmlNodePtr node; 3613 if (reader == NULL) 3614 return(NULL); 3615 if (reader->node == NULL) 3616 return(NULL); 3617 if (reader->curnode != NULL) 3618 node = reader->curnode; 3619 else 3620 node = reader->node; 3621 3622 switch (node->type) { 3623 case XML_NAMESPACE_DECL: 3624 return(((xmlNsPtr) node)->href); 3625 case XML_ATTRIBUTE_NODE:{ 3626 xmlAttrPtr attr = (xmlAttrPtr) node; 3627 const xmlChar *ret; 3628 3629 if ((attr->children != NULL) && 3630 (attr->children->type == XML_TEXT_NODE) && 3631 (attr->children->next == NULL)) 3632 return(attr->children->content); 3633 else { 3634 if (reader->buffer == NULL) { 3635 reader->buffer = xmlBufCreateSize(100); 3636 if (reader->buffer == NULL) { 3637 xmlGenericError(xmlGenericErrorContext, 3638 "xmlTextReaderSetup : malloc failed\n"); 3639 return (NULL); 3640 } 3641 xmlBufSetAllocationScheme(reader->buffer, 3642 XML_BUFFER_ALLOC_BOUNDED); 3643 } else 3644 xmlBufEmpty(reader->buffer); 3645 xmlBufGetNodeContent(reader->buffer, node); 3646 ret = xmlBufContent(reader->buffer); 3647 if (ret == NULL) { 3648 /* error on the buffer best to reallocate */ 3649 xmlBufFree(reader->buffer); 3650 reader->buffer = xmlBufCreateSize(100); 3651 xmlBufSetAllocationScheme(reader->buffer, 3652 XML_BUFFER_ALLOC_BOUNDED); 3653 ret = BAD_CAST ""; 3654 } 3655 return(ret); 3656 } 3657 break; 3658 } 3659 case XML_TEXT_NODE: 3660 case XML_CDATA_SECTION_NODE: 3661 case XML_PI_NODE: 3662 case XML_COMMENT_NODE: 3663 return(node->content); 3664 default: 3665 break; 3666 } 3667 return(NULL); 3668 } 3669 3670 /** 3671 * xmlTextReaderIsDefault: 3672 * @reader: the xmlTextReaderPtr used 3673 * 3674 * Whether an Attribute node was generated from the default value 3675 * defined in the DTD or schema. 3676 * 3677 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error 3678 */ 3679 int 3680 xmlTextReaderIsDefault(xmlTextReaderPtr reader) { 3681 if (reader == NULL) 3682 return(-1); 3683 return(0); 3684 } 3685 3686 /** 3687 * xmlTextReaderQuoteChar: 3688 * @reader: the xmlTextReaderPtr used 3689 * 3690 * The quotation mark character used to enclose the value of an attribute. 3691 * 3692 * Returns " or ' and -1 in case of error 3693 */ 3694 int 3695 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) { 3696 if (reader == NULL) 3697 return(-1); 3698 /* TODO maybe lookup the attribute value for " first */ 3699 return((int) '"'); 3700 } 3701 3702 /** 3703 * xmlTextReaderXmlLang: 3704 * @reader: the xmlTextReaderPtr used 3705 * 3706 * The xml:lang scope within which the node resides. 3707 * 3708 * Returns the xml:lang value or NULL if none exists., 3709 * if non NULL it need to be freed by the caller. 3710 */ 3711 xmlChar * 3712 xmlTextReaderXmlLang(xmlTextReaderPtr reader) { 3713 if (reader == NULL) 3714 return(NULL); 3715 if (reader->node == NULL) 3716 return(NULL); 3717 return(xmlNodeGetLang(reader->node)); 3718 } 3719 3720 /** 3721 * xmlTextReaderConstXmlLang: 3722 * @reader: the xmlTextReaderPtr used 3723 * 3724 * The xml:lang scope within which the node resides. 3725 * 3726 * Returns the xml:lang value or NULL if none exists. 3727 */ 3728 const xmlChar * 3729 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { 3730 xmlChar *tmp; 3731 const xmlChar *ret; 3732 3733 if (reader == NULL) 3734 return(NULL); 3735 if (reader->node == NULL) 3736 return(NULL); 3737 tmp = xmlNodeGetLang(reader->node); 3738 if (tmp == NULL) 3739 return(NULL); 3740 ret = CONSTSTR(tmp); 3741 xmlFree(tmp); 3742 return(ret); 3743 } 3744 3745 /** 3746 * xmlTextReaderConstString: 3747 * @reader: the xmlTextReaderPtr used 3748 * @str: the string to intern. 3749 * 3750 * Get an interned string from the reader, allows for example to 3751 * speedup string name comparisons 3752 * 3753 * Returns an interned copy of the string or NULL in case of error. The 3754 * string will be deallocated with the reader. 3755 */ 3756 const xmlChar * 3757 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { 3758 if (reader == NULL) 3759 return(NULL); 3760 return(CONSTSTR(str)); 3761 } 3762 3763 /** 3764 * xmlTextReaderNormalization: 3765 * @reader: the xmlTextReaderPtr used 3766 * 3767 * The value indicating whether to normalize white space and attribute values. 3768 * Since attribute value and end of line normalizations are a MUST in the XML 3769 * specification only the value true is accepted. The broken bahaviour of 3770 * accepting out of range character entities like � is of course not 3771 * supported either. 3772 * 3773 * Returns 1 or -1 in case of error. 3774 */ 3775 int 3776 xmlTextReaderNormalization(xmlTextReaderPtr reader) { 3777 if (reader == NULL) 3778 return(-1); 3779 return(1); 3780 } 3781 3782 /************************************************************************ 3783 * * 3784 * Extensions to the base APIs * 3785 * * 3786 ************************************************************************/ 3787 3788 /** 3789 * xmlTextReaderSetParserProp: 3790 * @reader: the xmlTextReaderPtr used 3791 * @prop: the xmlParserProperties to set 3792 * @value: usually 0 or 1 to (de)activate it 3793 * 3794 * Change the parser processing behaviour by changing some of its internal 3795 * properties. Note that some properties can only be changed before any 3796 * read has been done. 3797 * 3798 * Returns 0 if the call was successful, or -1 in case of error 3799 */ 3800 int 3801 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { 3802 xmlParserProperties p = (xmlParserProperties) prop; 3803 xmlParserCtxtPtr ctxt; 3804 3805 if ((reader == NULL) || (reader->ctxt == NULL)) 3806 return(-1); 3807 ctxt = reader->ctxt; 3808 3809 switch (p) { 3810 case XML_PARSER_LOADDTD: 3811 if (value != 0) { 3812 if (ctxt->loadsubset == 0) { 3813 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 3814 return(-1); 3815 ctxt->loadsubset = XML_DETECT_IDS; 3816 } 3817 } else { 3818 ctxt->loadsubset = 0; 3819 } 3820 return(0); 3821 case XML_PARSER_DEFAULTATTRS: 3822 if (value != 0) { 3823 ctxt->loadsubset |= XML_COMPLETE_ATTRS; 3824 } else { 3825 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3826 ctxt->loadsubset -= XML_COMPLETE_ATTRS; 3827 } 3828 return(0); 3829 case XML_PARSER_VALIDATE: 3830 if (value != 0) { 3831 ctxt->validate = 1; 3832 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 3833 } else { 3834 ctxt->validate = 0; 3835 } 3836 return(0); 3837 case XML_PARSER_SUBST_ENTITIES: 3838 if (value != 0) { 3839 ctxt->replaceEntities = 1; 3840 } else { 3841 ctxt->replaceEntities = 0; 3842 } 3843 return(0); 3844 } 3845 return(-1); 3846 } 3847 3848 /** 3849 * xmlTextReaderGetParserProp: 3850 * @reader: the xmlTextReaderPtr used 3851 * @prop: the xmlParserProperties to get 3852 * 3853 * Read the parser internal property. 3854 * 3855 * Returns the value, usually 0 or 1, or -1 in case of error. 3856 */ 3857 int 3858 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) { 3859 xmlParserProperties p = (xmlParserProperties) prop; 3860 xmlParserCtxtPtr ctxt; 3861 3862 if ((reader == NULL) || (reader->ctxt == NULL)) 3863 return(-1); 3864 ctxt = reader->ctxt; 3865 3866 switch (p) { 3867 case XML_PARSER_LOADDTD: 3868 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0)) 3869 return(1); 3870 return(0); 3871 case XML_PARSER_DEFAULTATTRS: 3872 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3873 return(1); 3874 return(0); 3875 case XML_PARSER_VALIDATE: 3876 return(reader->validate); 3877 case XML_PARSER_SUBST_ENTITIES: 3878 return(ctxt->replaceEntities); 3879 } 3880 return(-1); 3881 } 3882 3883 3884 /** 3885 * xmlTextReaderGetParserLineNumber: 3886 * @reader: the user data (XML reader context) 3887 * 3888 * Provide the line number of the current parsing point. 3889 * 3890 * Returns an int or 0 if not available 3891 */ 3892 int 3893 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader) 3894 { 3895 if ((reader == NULL) || (reader->ctxt == NULL) || 3896 (reader->ctxt->input == NULL)) { 3897 return (0); 3898 } 3899 return (reader->ctxt->input->line); 3900 } 3901 3902 /** 3903 * xmlTextReaderGetParserColumnNumber: 3904 * @reader: the user data (XML reader context) 3905 * 3906 * Provide the column number of the current parsing point. 3907 * 3908 * Returns an int or 0 if not available 3909 */ 3910 int 3911 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader) 3912 { 3913 if ((reader == NULL) || (reader->ctxt == NULL) || 3914 (reader->ctxt->input == NULL)) { 3915 return (0); 3916 } 3917 return (reader->ctxt->input->col); 3918 } 3919 3920 /** 3921 * xmlTextReaderCurrentNode: 3922 * @reader: the xmlTextReaderPtr used 3923 * 3924 * Hacking interface allowing to get the xmlNodePtr correponding to the 3925 * current node being accessed by the xmlTextReader. This is dangerous 3926 * because the underlying node may be destroyed on the next Reads. 3927 * 3928 * Returns the xmlNodePtr or NULL in case of error. 3929 */ 3930 xmlNodePtr 3931 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) { 3932 if (reader == NULL) 3933 return(NULL); 3934 3935 if (reader->curnode != NULL) 3936 return(reader->curnode); 3937 return(reader->node); 3938 } 3939 3940 /** 3941 * xmlTextReaderPreserve: 3942 * @reader: the xmlTextReaderPtr used 3943 * 3944 * This tells the XML Reader to preserve the current node. 3945 * The caller must also use xmlTextReaderCurrentDoc() to 3946 * keep an handle on the resulting document once parsing has finished 3947 * 3948 * Returns the xmlNodePtr or NULL in case of error. 3949 */ 3950 xmlNodePtr 3951 xmlTextReaderPreserve(xmlTextReaderPtr reader) { 3952 xmlNodePtr cur, parent; 3953 3954 if (reader == NULL) 3955 return(NULL); 3956 3957 if (reader->curnode != NULL) 3958 cur = reader->curnode; 3959 else 3960 cur = reader->node; 3961 if (cur == NULL) 3962 return(NULL); 3963 3964 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) { 3965 cur->extra |= NODE_IS_PRESERVED; 3966 cur->extra |= NODE_IS_SPRESERVED; 3967 } 3968 reader->preserves++; 3969 3970 parent = cur->parent;; 3971 while (parent != NULL) { 3972 if (parent->type == XML_ELEMENT_NODE) 3973 parent->extra |= NODE_IS_PRESERVED; 3974 parent = parent->parent; 3975 } 3976 return(cur); 3977 } 3978 3979 #ifdef LIBXML_PATTERN_ENABLED 3980 /** 3981 * xmlTextReaderPreservePattern: 3982 * @reader: the xmlTextReaderPtr used 3983 * @pattern: an XPath subset pattern 3984 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL 3985 * 3986 * This tells the XML Reader to preserve all nodes matched by the 3987 * pattern. The caller must also use xmlTextReaderCurrentDoc() to 3988 * keep an handle on the resulting document once parsing has finished 3989 * 3990 * Returns a non-negative number in case of success and -1 in case of error 3991 */ 3992 int 3993 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, 3994 const xmlChar **namespaces) 3995 { 3996 xmlPatternPtr comp; 3997 3998 if ((reader == NULL) || (pattern == NULL)) 3999 return(-1); 4000 4001 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces); 4002 if (comp == NULL) 4003 return(-1); 4004 4005 if (reader->patternMax <= 0) { 4006 reader->patternMax = 4; 4007 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * 4008 sizeof(reader->patternTab[0])); 4009 if (reader->patternTab == NULL) { 4010 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 4011 return (-1); 4012 } 4013 } 4014 if (reader->patternNr >= reader->patternMax) { 4015 xmlPatternPtr *tmp; 4016 reader->patternMax *= 2; 4017 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab, 4018 reader->patternMax * 4019 sizeof(reader->patternTab[0])); 4020 if (tmp == NULL) { 4021 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 4022 reader->patternMax /= 2; 4023 return (-1); 4024 } 4025 reader->patternTab = tmp; 4026 } 4027 reader->patternTab[reader->patternNr] = comp; 4028 return(reader->patternNr++); 4029 } 4030 #endif 4031 4032 /** 4033 * xmlTextReaderCurrentDoc: 4034 * @reader: the xmlTextReaderPtr used 4035 * 4036 * Hacking interface allowing to get the xmlDocPtr correponding to the 4037 * current document being accessed by the xmlTextReader. 4038 * NOTE: as a result of this call, the reader will not destroy the 4039 * associated XML document and calling xmlFreeDoc() on the result 4040 * is needed once the reader parsing has finished. 4041 * 4042 * Returns the xmlDocPtr or NULL in case of error. 4043 */ 4044 xmlDocPtr 4045 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { 4046 if (reader == NULL) 4047 return(NULL); 4048 if (reader->doc != NULL) 4049 return(reader->doc); 4050 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL)) 4051 return(NULL); 4052 4053 reader->preserve = 1; 4054 return(reader->ctxt->myDoc); 4055 } 4056 4057 #ifdef LIBXML_SCHEMAS_ENABLED 4058 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0); 4059 4060 static void XMLCDECL 4061 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4062 4063 static void XMLCDECL 4064 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4065 4066 static void XMLCDECL 4067 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4068 4069 static void XMLCDECL 4070 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); 4071 4072 static void XMLCDECL 4073 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) 4074 { 4075 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; 4076 4077 char *str; 4078 4079 va_list ap; 4080 4081 va_start(ap, msg); 4082 str = xmlTextReaderBuildMessage(msg, ap); 4083 if (!reader->errorFunc) { 4084 xmlTextReaderValidityError(ctx, "%s", str); 4085 } else { 4086 reader->errorFunc(reader->errorFuncArg, str, 4087 XML_PARSER_SEVERITY_VALIDITY_ERROR, 4088 NULL /* locator */ ); 4089 } 4090 if (str != NULL) 4091 xmlFree(str); 4092 va_end(ap); 4093 } 4094 4095 static void XMLCDECL 4096 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) 4097 { 4098 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; 4099 4100 char *str; 4101 4102 va_list ap; 4103 4104 va_start(ap, msg); 4105 str = xmlTextReaderBuildMessage(msg, ap); 4106 if (!reader->errorFunc) { 4107 xmlTextReaderValidityWarning(ctx, "%s", str); 4108 } else { 4109 reader->errorFunc(reader->errorFuncArg, str, 4110 XML_PARSER_SEVERITY_VALIDITY_WARNING, 4111 NULL /* locator */ ); 4112 } 4113 if (str != NULL) 4114 xmlFree(str); 4115 va_end(ap); 4116 } 4117 4118 static void 4119 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error); 4120 4121 static void 4122 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error) 4123 { 4124 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; 4125 4126 if (reader->sErrorFunc) { 4127 reader->sErrorFunc(reader->errorFuncArg, error); 4128 } else { 4129 xmlTextReaderStructuredError(reader, error); 4130 } 4131 } 4132 /** 4133 * xmlTextReaderRelaxNGSetSchema: 4134 * @reader: the xmlTextReaderPtr used 4135 * @schema: a precompiled RelaxNG schema 4136 * 4137 * Use RelaxNG to validate the document as it is processed. 4138 * Activation is only possible before the first Read(). 4139 * if @schema is NULL, then RelaxNG validation is desactivated. 4140 @ The @schema should not be freed until the reader is deallocated 4141 * or its use has been deactivated. 4142 * 4143 * Returns 0 in case the RelaxNG validation could be (des)activated and 4144 * -1 in case of error. 4145 */ 4146 int 4147 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { 4148 if (reader == NULL) 4149 return(-1); 4150 if (schema == NULL) { 4151 if (reader->rngSchemas != NULL) { 4152 xmlRelaxNGFree(reader->rngSchemas); 4153 reader->rngSchemas = NULL; 4154 } 4155 if (reader->rngValidCtxt != NULL) { 4156 if (! reader->rngPreserveCtxt) 4157 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4158 reader->rngValidCtxt = NULL; 4159 } 4160 reader->rngPreserveCtxt = 0; 4161 return(0); 4162 } 4163 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 4164 return(-1); 4165 if (reader->rngSchemas != NULL) { 4166 xmlRelaxNGFree(reader->rngSchemas); 4167 reader->rngSchemas = NULL; 4168 } 4169 if (reader->rngValidCtxt != NULL) { 4170 if (! reader->rngPreserveCtxt) 4171 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4172 reader->rngValidCtxt = NULL; 4173 } 4174 reader->rngPreserveCtxt = 0; 4175 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); 4176 if (reader->rngValidCtxt == NULL) 4177 return(-1); 4178 if (reader->errorFunc != NULL) { 4179 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4180 xmlTextReaderValidityErrorRelay, 4181 xmlTextReaderValidityWarningRelay, 4182 reader); 4183 } 4184 if (reader->sErrorFunc != NULL) { 4185 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4186 xmlTextReaderValidityStructuredRelay, 4187 reader); 4188 } 4189 reader->rngValidErrors = 0; 4190 reader->rngFullNode = NULL; 4191 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 4192 return(0); 4193 } 4194 4195 /** 4196 * xmlTextReaderLocator: 4197 * @ctx: the xmlTextReaderPtr used 4198 * @file: returned file information 4199 * @line: returned line information 4200 * 4201 * Internal locator function for the readers 4202 * 4203 * Returns 0 in case the Schema validation could be (des)activated and 4204 * -1 in case of error. 4205 */ 4206 static int 4207 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) { 4208 xmlTextReaderPtr reader; 4209 4210 if ((ctx == NULL) || ((file == NULL) && (line == NULL))) 4211 return(-1); 4212 4213 if (file != NULL) 4214 *file = NULL; 4215 if (line != NULL) 4216 *line = 0; 4217 4218 reader = (xmlTextReaderPtr) ctx; 4219 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) { 4220 if (file != NULL) 4221 *file = reader->ctxt->input->filename; 4222 if (line != NULL) 4223 *line = reader->ctxt->input->line; 4224 return(0); 4225 } 4226 if (reader->node != NULL) { 4227 long res; 4228 int ret = 0; 4229 4230 if (line != NULL) { 4231 res = xmlGetLineNo(reader->node); 4232 if (res > 0) 4233 *line = (unsigned long) res; 4234 else 4235 ret = -1; 4236 } 4237 if (file != NULL) { 4238 xmlDocPtr doc = reader->node->doc; 4239 if ((doc != NULL) && (doc->URL != NULL)) 4240 *file = (const char *) doc->URL; 4241 else 4242 ret = -1; 4243 } 4244 return(ret); 4245 } 4246 return(-1); 4247 } 4248 4249 /** 4250 * xmlTextReaderSetSchema: 4251 * @reader: the xmlTextReaderPtr used 4252 * @schema: a precompiled Schema schema 4253 * 4254 * Use XSD Schema to validate the document as it is processed. 4255 * Activation is only possible before the first Read(). 4256 * if @schema is NULL, then Schema validation is desactivated. 4257 @ The @schema should not be freed until the reader is deallocated 4258 * or its use has been deactivated. 4259 * 4260 * Returns 0 in case the Schema validation could be (des)activated and 4261 * -1 in case of error. 4262 */ 4263 int 4264 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { 4265 if (reader == NULL) 4266 return(-1); 4267 if (schema == NULL) { 4268 if (reader->xsdPlug != NULL) { 4269 xmlSchemaSAXUnplug(reader->xsdPlug); 4270 reader->xsdPlug = NULL; 4271 } 4272 if (reader->xsdValidCtxt != NULL) { 4273 if (! reader->xsdPreserveCtxt) 4274 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4275 reader->xsdValidCtxt = NULL; 4276 } 4277 reader->xsdPreserveCtxt = 0; 4278 if (reader->xsdSchemas != NULL) { 4279 xmlSchemaFree(reader->xsdSchemas); 4280 reader->xsdSchemas = NULL; 4281 } 4282 return(0); 4283 } 4284 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 4285 return(-1); 4286 if (reader->xsdPlug != NULL) { 4287 xmlSchemaSAXUnplug(reader->xsdPlug); 4288 reader->xsdPlug = NULL; 4289 } 4290 if (reader->xsdValidCtxt != NULL) { 4291 if (! reader->xsdPreserveCtxt) 4292 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4293 reader->xsdValidCtxt = NULL; 4294 } 4295 reader->xsdPreserveCtxt = 0; 4296 if (reader->xsdSchemas != NULL) { 4297 xmlSchemaFree(reader->xsdSchemas); 4298 reader->xsdSchemas = NULL; 4299 } 4300 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema); 4301 if (reader->xsdValidCtxt == NULL) { 4302 xmlSchemaFree(reader->xsdSchemas); 4303 reader->xsdSchemas = NULL; 4304 return(-1); 4305 } 4306 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4307 &(reader->ctxt->sax), 4308 &(reader->ctxt->userData)); 4309 if (reader->xsdPlug == NULL) { 4310 xmlSchemaFree(reader->xsdSchemas); 4311 reader->xsdSchemas = NULL; 4312 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4313 reader->xsdValidCtxt = NULL; 4314 return(-1); 4315 } 4316 xmlSchemaValidateSetLocator(reader->xsdValidCtxt, 4317 xmlTextReaderLocator, 4318 (void *) reader); 4319 4320 if (reader->errorFunc != NULL) { 4321 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4322 xmlTextReaderValidityErrorRelay, 4323 xmlTextReaderValidityWarningRelay, 4324 reader); 4325 } 4326 if (reader->sErrorFunc != NULL) { 4327 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 4328 xmlTextReaderValidityStructuredRelay, 4329 reader); 4330 } 4331 reader->xsdValidErrors = 0; 4332 reader->validate = XML_TEXTREADER_VALIDATE_XSD; 4333 return(0); 4334 } 4335 4336 /** 4337 * xmlTextReaderRelaxNGValidateInternal: 4338 * @reader: the xmlTextReaderPtr used 4339 * @rng: the path to a RelaxNG schema or NULL 4340 * @ctxt: the RelaxNG schema validation context or NULL 4341 * @options: options (not yet used) 4342 * 4343 * Use RelaxNG to validate the document as it is processed. 4344 * Activation is only possible before the first Read(). 4345 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated. 4346 * 4347 * Returns 0 in case the RelaxNG validation could be (de)activated and 4348 * -1 in case of error. 4349 */ 4350 static int 4351 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, 4352 const char *rng, 4353 xmlRelaxNGValidCtxtPtr ctxt, 4354 int options ATTRIBUTE_UNUSED) 4355 { 4356 if (reader == NULL) 4357 return(-1); 4358 4359 if ((rng != NULL) && (ctxt != NULL)) 4360 return (-1); 4361 4362 if (((rng != NULL) || (ctxt != NULL)) && 4363 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || 4364 (reader->ctxt == NULL))) 4365 return(-1); 4366 4367 /* Cleanup previous validation stuff. */ 4368 if (reader->rngValidCtxt != NULL) { 4369 if ( !reader->rngPreserveCtxt) 4370 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 4371 reader->rngValidCtxt = NULL; 4372 } 4373 reader->rngPreserveCtxt = 0; 4374 if (reader->rngSchemas != NULL) { 4375 xmlRelaxNGFree(reader->rngSchemas); 4376 reader->rngSchemas = NULL; 4377 } 4378 4379 if ((rng == NULL) && (ctxt == NULL)) { 4380 /* We just want to deactivate the validation, so get out. */ 4381 return(0); 4382 } 4383 4384 4385 if (rng != NULL) { 4386 xmlRelaxNGParserCtxtPtr pctxt; 4387 /* Parse the schema and create validation environment. */ 4388 4389 pctxt = xmlRelaxNGNewParserCtxt(rng); 4390 if (reader->errorFunc != NULL) { 4391 xmlRelaxNGSetParserErrors(pctxt, 4392 xmlTextReaderValidityErrorRelay, 4393 xmlTextReaderValidityWarningRelay, 4394 reader); 4395 } 4396 if (reader->sErrorFunc != NULL) { 4397 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4398 xmlTextReaderValidityStructuredRelay, 4399 reader); 4400 } 4401 reader->rngSchemas = xmlRelaxNGParse(pctxt); 4402 xmlRelaxNGFreeParserCtxt(pctxt); 4403 if (reader->rngSchemas == NULL) 4404 return(-1); 4405 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); 4406 if (reader->rngValidCtxt == NULL) { 4407 xmlRelaxNGFree(reader->rngSchemas); 4408 reader->rngSchemas = NULL; 4409 return(-1); 4410 } 4411 } else { 4412 /* Use the given validation context. */ 4413 reader->rngValidCtxt = ctxt; 4414 reader->rngPreserveCtxt = 1; 4415 } 4416 /* 4417 * Redirect the validation context's error channels to use 4418 * the reader channels. 4419 * TODO: In case the user provides the validation context we 4420 * could make this redirection optional. 4421 */ 4422 if (reader->errorFunc != NULL) { 4423 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4424 xmlTextReaderValidityErrorRelay, 4425 xmlTextReaderValidityWarningRelay, 4426 reader); 4427 } 4428 if (reader->sErrorFunc != NULL) { 4429 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 4430 xmlTextReaderValidityStructuredRelay, 4431 reader); 4432 } 4433 reader->rngValidErrors = 0; 4434 reader->rngFullNode = NULL; 4435 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 4436 return(0); 4437 } 4438 4439 /** 4440 * xmlTextReaderSchemaValidateInternal: 4441 * @reader: the xmlTextReaderPtr used 4442 * @xsd: the path to a W3C XSD schema or NULL 4443 * @ctxt: the XML Schema validation context or NULL 4444 * @options: options (not used yet) 4445 * 4446 * Validate the document as it is processed using XML Schema. 4447 * Activation is only possible before the first Read(). 4448 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated. 4449 * 4450 * Returns 0 in case the schemas validation could be (de)activated and 4451 * -1 in case of error. 4452 */ 4453 static int 4454 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, 4455 const char *xsd, 4456 xmlSchemaValidCtxtPtr ctxt, 4457 int options ATTRIBUTE_UNUSED) 4458 { 4459 if (reader == NULL) 4460 return(-1); 4461 4462 if ((xsd != NULL) && (ctxt != NULL)) 4463 return(-1); 4464 4465 if (((xsd != NULL) || (ctxt != NULL)) && 4466 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || 4467 (reader->ctxt == NULL))) 4468 return(-1); 4469 4470 /* Cleanup previous validation stuff. */ 4471 if (reader->xsdPlug != NULL) { 4472 xmlSchemaSAXUnplug(reader->xsdPlug); 4473 reader->xsdPlug = NULL; 4474 } 4475 if (reader->xsdValidCtxt != NULL) { 4476 if (! reader->xsdPreserveCtxt) 4477 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4478 reader->xsdValidCtxt = NULL; 4479 } 4480 reader->xsdPreserveCtxt = 0; 4481 if (reader->xsdSchemas != NULL) { 4482 xmlSchemaFree(reader->xsdSchemas); 4483 reader->xsdSchemas = NULL; 4484 } 4485 4486 if ((xsd == NULL) && (ctxt == NULL)) { 4487 /* We just want to deactivate the validation, so get out. */ 4488 return(0); 4489 } 4490 4491 if (xsd != NULL) { 4492 xmlSchemaParserCtxtPtr pctxt; 4493 /* Parse the schema and create validation environment. */ 4494 pctxt = xmlSchemaNewParserCtxt(xsd); 4495 if (reader->errorFunc != NULL) { 4496 xmlSchemaSetParserErrors(pctxt, 4497 xmlTextReaderValidityErrorRelay, 4498 xmlTextReaderValidityWarningRelay, 4499 reader); 4500 } 4501 reader->xsdSchemas = xmlSchemaParse(pctxt); 4502 xmlSchemaFreeParserCtxt(pctxt); 4503 if (reader->xsdSchemas == NULL) 4504 return(-1); 4505 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas); 4506 if (reader->xsdValidCtxt == NULL) { 4507 xmlSchemaFree(reader->xsdSchemas); 4508 reader->xsdSchemas = NULL; 4509 return(-1); 4510 } 4511 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4512 &(reader->ctxt->sax), 4513 &(reader->ctxt->userData)); 4514 if (reader->xsdPlug == NULL) { 4515 xmlSchemaFree(reader->xsdSchemas); 4516 reader->xsdSchemas = NULL; 4517 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); 4518 reader->xsdValidCtxt = NULL; 4519 return(-1); 4520 } 4521 } else { 4522 /* Use the given validation context. */ 4523 reader->xsdValidCtxt = ctxt; 4524 reader->xsdPreserveCtxt = 1; 4525 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, 4526 &(reader->ctxt->sax), 4527 &(reader->ctxt->userData)); 4528 if (reader->xsdPlug == NULL) { 4529 reader->xsdValidCtxt = NULL; 4530 reader->xsdPreserveCtxt = 0; 4531 return(-1); 4532 } 4533 } 4534 xmlSchemaValidateSetLocator(reader->xsdValidCtxt, 4535 xmlTextReaderLocator, 4536 (void *) reader); 4537 /* 4538 * Redirect the validation context's error channels to use 4539 * the reader channels. 4540 * TODO: In case the user provides the validation context we 4541 * could make this redirection optional. 4542 */ 4543 if (reader->errorFunc != NULL) { 4544 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4545 xmlTextReaderValidityErrorRelay, 4546 xmlTextReaderValidityWarningRelay, 4547 reader); 4548 } 4549 if (reader->sErrorFunc != NULL) { 4550 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 4551 xmlTextReaderValidityStructuredRelay, 4552 reader); 4553 } 4554 reader->xsdValidErrors = 0; 4555 reader->validate = XML_TEXTREADER_VALIDATE_XSD; 4556 return(0); 4557 } 4558 4559 /** 4560 * xmlTextReaderSchemaValidateCtxt: 4561 * @reader: the xmlTextReaderPtr used 4562 * @ctxt: the XML Schema validation context or NULL 4563 * @options: options (not used yet) 4564 * 4565 * Use W3C XSD schema context to validate the document as it is processed. 4566 * Activation is only possible before the first Read(). 4567 * If @ctxt is NULL, then XML Schema validation is deactivated. 4568 * 4569 * Returns 0 in case the schemas validation could be (de)activated and 4570 * -1 in case of error. 4571 */ 4572 int 4573 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, 4574 xmlSchemaValidCtxtPtr ctxt, 4575 int options) 4576 { 4577 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options)); 4578 } 4579 4580 /** 4581 * xmlTextReaderSchemaValidate: 4582 * @reader: the xmlTextReaderPtr used 4583 * @xsd: the path to a W3C XSD schema or NULL 4584 * 4585 * Use W3C XSD schema to validate the document as it is processed. 4586 * Activation is only possible before the first Read(). 4587 * If @xsd is NULL, then XML Schema validation is deactivated. 4588 * 4589 * Returns 0 in case the schemas validation could be (de)activated and 4590 * -1 in case of error. 4591 */ 4592 int 4593 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) 4594 { 4595 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0)); 4596 } 4597 4598 /** 4599 * xmlTextReaderRelaxNGValidateCtxt: 4600 * @reader: the xmlTextReaderPtr used 4601 * @ctxt: the RelaxNG schema validation context or NULL 4602 * @options: options (not used yet) 4603 * 4604 * Use RelaxNG schema context to validate the document as it is processed. 4605 * Activation is only possible before the first Read(). 4606 * If @ctxt is NULL, then RelaxNG schema validation is deactivated. 4607 * 4608 * Returns 0 in case the schemas validation could be (de)activated and 4609 * -1 in case of error. 4610 */ 4611 int 4612 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader, 4613 xmlRelaxNGValidCtxtPtr ctxt, 4614 int options) 4615 { 4616 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options)); 4617 } 4618 4619 /** 4620 * xmlTextReaderRelaxNGValidate: 4621 * @reader: the xmlTextReaderPtr used 4622 * @rng: the path to a RelaxNG schema or NULL 4623 * 4624 * Use RelaxNG schema to validate the document as it is processed. 4625 * Activation is only possible before the first Read(). 4626 * If @rng is NULL, then RelaxNG schema validation is deactivated. 4627 * 4628 * Returns 0 in case the schemas validation could be (de)activated and 4629 * -1 in case of error. 4630 */ 4631 int 4632 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) 4633 { 4634 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0)); 4635 } 4636 4637 #endif 4638 4639 /** 4640 * xmlTextReaderIsNamespaceDecl: 4641 * @reader: the xmlTextReaderPtr used 4642 * 4643 * Determine whether the current node is a namespace declaration 4644 * rather than a regular attribute. 4645 * 4646 * Returns 1 if the current node is a namespace declaration, 0 if it 4647 * is a regular attribute or other type of node, or -1 in case of 4648 * error. 4649 */ 4650 int 4651 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) { 4652 xmlNodePtr node; 4653 if (reader == NULL) 4654 return(-1); 4655 if (reader->node == NULL) 4656 return(-1); 4657 if (reader->curnode != NULL) 4658 node = reader->curnode; 4659 else 4660 node = reader->node; 4661 4662 if (XML_NAMESPACE_DECL == node->type) 4663 return(1); 4664 else 4665 return(0); 4666 } 4667 4668 /** 4669 * xmlTextReaderConstXmlVersion: 4670 * @reader: the xmlTextReaderPtr used 4671 * 4672 * Determine the XML version of the document being read. 4673 * 4674 * Returns a string containing the XML version of the document or NULL 4675 * in case of error. The string is deallocated with the reader. 4676 */ 4677 const xmlChar * 4678 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) { 4679 xmlDocPtr doc = NULL; 4680 if (reader == NULL) 4681 return(NULL); 4682 if (reader->doc != NULL) 4683 doc = reader->doc; 4684 else if (reader->ctxt != NULL) 4685 doc = reader->ctxt->myDoc; 4686 if (doc == NULL) 4687 return(NULL); 4688 4689 if (doc->version == NULL) 4690 return(NULL); 4691 else 4692 return(CONSTSTR(doc->version)); 4693 } 4694 4695 /** 4696 * xmlTextReaderStandalone: 4697 * @reader: the xmlTextReaderPtr used 4698 * 4699 * Determine the standalone status of the document being read. 4700 * 4701 * Returns 1 if the document was declared to be standalone, 0 if it 4702 * was declared to be not standalone, or -1 if the document did not 4703 * specify its standalone status or in case of error. 4704 */ 4705 int 4706 xmlTextReaderStandalone(xmlTextReaderPtr reader) { 4707 xmlDocPtr doc = NULL; 4708 if (reader == NULL) 4709 return(-1); 4710 if (reader->doc != NULL) 4711 doc = reader->doc; 4712 else if (reader->ctxt != NULL) 4713 doc = reader->ctxt->myDoc; 4714 if (doc == NULL) 4715 return(-1); 4716 4717 return(doc->standalone); 4718 } 4719 4720 /************************************************************************ 4721 * * 4722 * Error Handling Extensions * 4723 * * 4724 ************************************************************************/ 4725 4726 /* helper to build a xmlMalloc'ed string from a format and va_list */ 4727 static char * 4728 xmlTextReaderBuildMessage(const char *msg, va_list ap) { 4729 int size = 0; 4730 int chars; 4731 char *larger; 4732 char *str = NULL; 4733 va_list aq; 4734 4735 while (1) { 4736 VA_COPY(aq, ap); 4737 chars = vsnprintf(str, size, msg, aq); 4738 va_end(aq); 4739 if (chars < 0) { 4740 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n"); 4741 if (str) 4742 xmlFree(str); 4743 return NULL; 4744 } 4745 if ((chars < size) || (size == MAX_ERR_MSG_SIZE)) 4746 break; 4747 if (chars < MAX_ERR_MSG_SIZE) 4748 size = chars + 1; 4749 else 4750 size = MAX_ERR_MSG_SIZE; 4751 if ((larger = (char *) xmlRealloc(str, size)) == NULL) { 4752 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 4753 if (str) 4754 xmlFree(str); 4755 return NULL; 4756 } 4757 str = larger; 4758 } 4759 4760 return str; 4761 } 4762 4763 /** 4764 * xmlTextReaderLocatorLineNumber: 4765 * @locator: the xmlTextReaderLocatorPtr used 4766 * 4767 * Obtain the line number for the given locator. 4768 * 4769 * Returns the line number or -1 in case of error. 4770 */ 4771 int 4772 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) { 4773 /* we know that locator is a xmlParserCtxtPtr */ 4774 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 4775 int ret = -1; 4776 4777 if (locator == NULL) 4778 return(-1); 4779 if (ctx->node != NULL) { 4780 ret = xmlGetLineNo(ctx->node); 4781 } 4782 else { 4783 /* inspired from error.c */ 4784 xmlParserInputPtr input; 4785 input = ctx->input; 4786 if ((input->filename == NULL) && (ctx->inputNr > 1)) 4787 input = ctx->inputTab[ctx->inputNr - 2]; 4788 if (input != NULL) { 4789 ret = input->line; 4790 } 4791 else { 4792 ret = -1; 4793 } 4794 } 4795 4796 return ret; 4797 } 4798 4799 /** 4800 * xmlTextReaderLocatorBaseURI: 4801 * @locator: the xmlTextReaderLocatorPtr used 4802 * 4803 * Obtain the base URI for the given locator. 4804 * 4805 * Returns the base URI or NULL in case of error, 4806 * if non NULL it need to be freed by the caller. 4807 */ 4808 xmlChar * 4809 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { 4810 /* we know that locator is a xmlParserCtxtPtr */ 4811 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 4812 xmlChar *ret = NULL; 4813 4814 if (locator == NULL) 4815 return(NULL); 4816 if (ctx->node != NULL) { 4817 ret = xmlNodeGetBase(NULL,ctx->node); 4818 } 4819 else { 4820 /* inspired from error.c */ 4821 xmlParserInputPtr input; 4822 input = ctx->input; 4823 if ((input->filename == NULL) && (ctx->inputNr > 1)) 4824 input = ctx->inputTab[ctx->inputNr - 2]; 4825 if (input != NULL) { 4826 ret = xmlStrdup(BAD_CAST input->filename); 4827 } 4828 else { 4829 ret = NULL; 4830 } 4831 } 4832 4833 return ret; 4834 } 4835 4836 static void 4837 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, 4838 char *str) 4839 { 4840 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; 4841 4842 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; 4843 4844 if (str != NULL) { 4845 if (reader->errorFunc) 4846 reader->errorFunc(reader->errorFuncArg, str, severity, 4847 (xmlTextReaderLocatorPtr) ctx); 4848 xmlFree(str); 4849 } 4850 } 4851 4852 static void 4853 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) 4854 { 4855 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; 4856 4857 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; 4858 4859 if (error && reader->sErrorFunc) { 4860 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error); 4861 } 4862 } 4863 4864 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3) 4865 xmlTextReaderError(void *ctxt, const char *msg, ...) 4866 { 4867 va_list ap; 4868 4869 va_start(ap, msg); 4870 xmlTextReaderGenericError(ctxt, 4871 XML_PARSER_SEVERITY_ERROR, 4872 xmlTextReaderBuildMessage(msg, ap)); 4873 va_end(ap); 4874 4875 } 4876 4877 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3) 4878 xmlTextReaderWarning(void *ctxt, const char *msg, ...) 4879 { 4880 va_list ap; 4881 4882 va_start(ap, msg); 4883 xmlTextReaderGenericError(ctxt, 4884 XML_PARSER_SEVERITY_WARNING, 4885 xmlTextReaderBuildMessage(msg, ap)); 4886 va_end(ap); 4887 } 4888 4889 static void XMLCDECL 4890 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) 4891 { 4892 va_list ap; 4893 4894 int len = xmlStrlen((const xmlChar *) msg); 4895 4896 if ((len > 1) && (msg[len - 2] != ':')) { 4897 /* 4898 * some callbacks only report locator information: 4899 * skip them (mimicking behaviour in error.c) 4900 */ 4901 va_start(ap, msg); 4902 xmlTextReaderGenericError(ctxt, 4903 XML_PARSER_SEVERITY_VALIDITY_ERROR, 4904 xmlTextReaderBuildMessage(msg, ap)); 4905 va_end(ap); 4906 } 4907 } 4908 4909 static void XMLCDECL 4910 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) 4911 { 4912 va_list ap; 4913 4914 int len = xmlStrlen((const xmlChar *) msg); 4915 4916 if ((len != 0) && (msg[len - 1] != ':')) { 4917 /* 4918 * some callbacks only report locator information: 4919 * skip them (mimicking behaviour in error.c) 4920 */ 4921 va_start(ap, msg); 4922 xmlTextReaderGenericError(ctxt, 4923 XML_PARSER_SEVERITY_VALIDITY_WARNING, 4924 xmlTextReaderBuildMessage(msg, ap)); 4925 va_end(ap); 4926 } 4927 } 4928 4929 /** 4930 * xmlTextReaderSetErrorHandler: 4931 * @reader: the xmlTextReaderPtr used 4932 * @f: the callback function to call on error and warnings 4933 * @arg: a user argument to pass to the callback function 4934 * 4935 * Register a callback function that will be called on error and warnings. 4936 * 4937 * If @f is NULL, the default error and warning handlers are restored. 4938 */ 4939 void 4940 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, 4941 xmlTextReaderErrorFunc f, void *arg) 4942 { 4943 if (f != NULL) { 4944 reader->ctxt->sax->error = xmlTextReaderError; 4945 reader->ctxt->sax->serror = NULL; 4946 reader->ctxt->vctxt.error = xmlTextReaderValidityError; 4947 reader->ctxt->sax->warning = xmlTextReaderWarning; 4948 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; 4949 reader->errorFunc = f; 4950 reader->sErrorFunc = NULL; 4951 reader->errorFuncArg = arg; 4952 #ifdef LIBXML_SCHEMAS_ENABLED 4953 if (reader->rngValidCtxt) { 4954 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 4955 xmlTextReaderValidityErrorRelay, 4956 xmlTextReaderValidityWarningRelay, 4957 reader); 4958 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 4959 reader); 4960 } 4961 if (reader->xsdValidCtxt) { 4962 xmlSchemaSetValidErrors(reader->xsdValidCtxt, 4963 xmlTextReaderValidityErrorRelay, 4964 xmlTextReaderValidityWarningRelay, 4965 reader); 4966 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 4967 reader); 4968 } 4969 #endif 4970 } else { 4971 /* restore defaults */ 4972 reader->ctxt->sax->error = xmlParserError; 4973 reader->ctxt->vctxt.error = xmlParserValidityError; 4974 reader->ctxt->sax->warning = xmlParserWarning; 4975 reader->ctxt->vctxt.warning = xmlParserValidityWarning; 4976 reader->errorFunc = NULL; 4977 reader->sErrorFunc = NULL; 4978 reader->errorFuncArg = NULL; 4979 #ifdef LIBXML_SCHEMAS_ENABLED 4980 if (reader->rngValidCtxt) { 4981 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 4982 reader); 4983 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 4984 reader); 4985 } 4986 if (reader->xsdValidCtxt) { 4987 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 4988 reader); 4989 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 4990 reader); 4991 } 4992 #endif 4993 } 4994 } 4995 4996 /** 4997 * xmlTextReaderSetStructuredErrorHandler: 4998 * @reader: the xmlTextReaderPtr used 4999 * @f: the callback function to call on error and warnings 5000 * @arg: a user argument to pass to the callback function 5001 * 5002 * Register a callback function that will be called on error and warnings. 5003 * 5004 * If @f is NULL, the default error and warning handlers are restored. 5005 */ 5006 void 5007 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, 5008 xmlStructuredErrorFunc f, void *arg) 5009 { 5010 if (f != NULL) { 5011 reader->ctxt->sax->error = NULL; 5012 reader->ctxt->sax->serror = xmlTextReaderStructuredError; 5013 reader->ctxt->vctxt.error = xmlTextReaderValidityError; 5014 reader->ctxt->sax->warning = xmlTextReaderWarning; 5015 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; 5016 reader->sErrorFunc = f; 5017 reader->errorFunc = NULL; 5018 reader->errorFuncArg = arg; 5019 #ifdef LIBXML_SCHEMAS_ENABLED 5020 if (reader->rngValidCtxt) { 5021 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 5022 reader); 5023 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, 5024 xmlTextReaderValidityStructuredRelay, 5025 reader); 5026 } 5027 if (reader->xsdValidCtxt) { 5028 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 5029 reader); 5030 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, 5031 xmlTextReaderValidityStructuredRelay, 5032 reader); 5033 } 5034 #endif 5035 } else { 5036 /* restore defaults */ 5037 reader->ctxt->sax->error = xmlParserError; 5038 reader->ctxt->sax->serror = NULL; 5039 reader->ctxt->vctxt.error = xmlParserValidityError; 5040 reader->ctxt->sax->warning = xmlParserWarning; 5041 reader->ctxt->vctxt.warning = xmlParserValidityWarning; 5042 reader->errorFunc = NULL; 5043 reader->sErrorFunc = NULL; 5044 reader->errorFuncArg = NULL; 5045 #ifdef LIBXML_SCHEMAS_ENABLED 5046 if (reader->rngValidCtxt) { 5047 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, 5048 reader); 5049 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, 5050 reader); 5051 } 5052 if (reader->xsdValidCtxt) { 5053 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, 5054 reader); 5055 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, 5056 reader); 5057 } 5058 #endif 5059 } 5060 } 5061 5062 /** 5063 * xmlTextReaderIsValid: 5064 * @reader: the xmlTextReaderPtr used 5065 * 5066 * Retrieve the validity status from the parser context 5067 * 5068 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error 5069 */ 5070 int 5071 xmlTextReaderIsValid(xmlTextReaderPtr reader) 5072 { 5073 if (reader == NULL) 5074 return (-1); 5075 #ifdef LIBXML_SCHEMAS_ENABLED 5076 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG) 5077 return (reader->rngValidErrors == 0); 5078 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD) 5079 return (reader->xsdValidErrors == 0); 5080 #endif 5081 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1)) 5082 return (reader->ctxt->valid); 5083 return (0); 5084 } 5085 5086 /** 5087 * xmlTextReaderGetErrorHandler: 5088 * @reader: the xmlTextReaderPtr used 5089 * @f: the callback function or NULL is no callback has been registered 5090 * @arg: a user argument 5091 * 5092 * Retrieve the error callback function and user argument. 5093 */ 5094 void 5095 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, 5096 xmlTextReaderErrorFunc * f, void **arg) 5097 { 5098 if (f != NULL) 5099 *f = reader->errorFunc; 5100 if (arg != NULL) 5101 *arg = reader->errorFuncArg; 5102 } 5103 /************************************************************************ 5104 * * 5105 * New set (2.6.0) of simpler and more flexible APIs * 5106 * * 5107 ************************************************************************/ 5108 5109 /** 5110 * xmlTextReaderSetup: 5111 * @reader: an XML reader 5112 * @input: xmlParserInputBufferPtr used to feed the reader, will 5113 * be destroyed with it. 5114 * @URL: the base URL to use for the document 5115 * @encoding: the document encoding, or NULL 5116 * @options: a combination of xmlParserOption 5117 * 5118 * Setup an XML reader with new options 5119 * 5120 * Returns 0 in case of success and -1 in case of error. 5121 */ 5122 int 5123 xmlTextReaderSetup(xmlTextReaderPtr reader, 5124 xmlParserInputBufferPtr input, const char *URL, 5125 const char *encoding, int options) 5126 { 5127 if (reader == NULL) { 5128 if (input != NULL) 5129 xmlFreeParserInputBuffer(input); 5130 return (-1); 5131 } 5132 5133 /* 5134 * we force the generation of compact text nodes on the reader 5135 * since usr applications should never modify the tree 5136 */ 5137 options |= XML_PARSE_COMPACT; 5138 5139 reader->doc = NULL; 5140 reader->entNr = 0; 5141 reader->parserFlags = options; 5142 reader->validate = XML_TEXTREADER_NOT_VALIDATE; 5143 if ((input != NULL) && (reader->input != NULL) && 5144 (reader->allocs & XML_TEXTREADER_INPUT)) { 5145 xmlFreeParserInputBuffer(reader->input); 5146 reader->input = NULL; 5147 reader->allocs -= XML_TEXTREADER_INPUT; 5148 } 5149 if (input != NULL) { 5150 reader->input = input; 5151 reader->allocs |= XML_TEXTREADER_INPUT; 5152 } 5153 if (reader->buffer == NULL) 5154 reader->buffer = xmlBufCreateSize(100); 5155 if (reader->buffer == NULL) { 5156 xmlGenericError(xmlGenericErrorContext, 5157 "xmlTextReaderSetup : malloc failed\n"); 5158 return (-1); 5159 } 5160 /* no operation on a reader should require a huge buffer */ 5161 xmlBufSetAllocationScheme(reader->buffer, 5162 XML_BUFFER_ALLOC_BOUNDED); 5163 if (reader->sax == NULL) 5164 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 5165 if (reader->sax == NULL) { 5166 xmlGenericError(xmlGenericErrorContext, 5167 "xmlTextReaderSetup : malloc failed\n"); 5168 return (-1); 5169 } 5170 xmlSAXVersion(reader->sax, 2); 5171 reader->startElement = reader->sax->startElement; 5172 reader->sax->startElement = xmlTextReaderStartElement; 5173 reader->endElement = reader->sax->endElement; 5174 reader->sax->endElement = xmlTextReaderEndElement; 5175 #ifdef LIBXML_SAX1_ENABLED 5176 if (reader->sax->initialized == XML_SAX2_MAGIC) { 5177 #endif /* LIBXML_SAX1_ENABLED */ 5178 reader->startElementNs = reader->sax->startElementNs; 5179 reader->sax->startElementNs = xmlTextReaderStartElementNs; 5180 reader->endElementNs = reader->sax->endElementNs; 5181 reader->sax->endElementNs = xmlTextReaderEndElementNs; 5182 #ifdef LIBXML_SAX1_ENABLED 5183 } else { 5184 reader->startElementNs = NULL; 5185 reader->endElementNs = NULL; 5186 } 5187 #endif /* LIBXML_SAX1_ENABLED */ 5188 reader->characters = reader->sax->characters; 5189 reader->sax->characters = xmlTextReaderCharacters; 5190 reader->sax->ignorableWhitespace = xmlTextReaderCharacters; 5191 reader->cdataBlock = reader->sax->cdataBlock; 5192 reader->sax->cdataBlock = xmlTextReaderCDataBlock; 5193 5194 reader->mode = XML_TEXTREADER_MODE_INITIAL; 5195 reader->node = NULL; 5196 reader->curnode = NULL; 5197 if (input != NULL) { 5198 if (xmlBufUse(reader->input->buffer) < 4) { 5199 xmlParserInputBufferRead(input, 4); 5200 } 5201 if (reader->ctxt == NULL) { 5202 if (xmlBufUse(reader->input->buffer) >= 4) { 5203 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, 5204 (const char *) xmlBufContent(reader->input->buffer), 5205 4, URL); 5206 reader->base = 0; 5207 reader->cur = 4; 5208 } else { 5209 reader->ctxt = 5210 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); 5211 reader->base = 0; 5212 reader->cur = 0; 5213 } 5214 } else { 5215 xmlParserInputPtr inputStream; 5216 xmlParserInputBufferPtr buf; 5217 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; 5218 5219 xmlCtxtReset(reader->ctxt); 5220 buf = xmlAllocParserInputBuffer(enc); 5221 if (buf == NULL) return(-1); 5222 inputStream = xmlNewInputStream(reader->ctxt); 5223 if (inputStream == NULL) { 5224 xmlFreeParserInputBuffer(buf); 5225 return(-1); 5226 } 5227 5228 if (URL == NULL) 5229 inputStream->filename = NULL; 5230 else 5231 inputStream->filename = (char *) 5232 xmlCanonicPath((const xmlChar *) URL); 5233 inputStream->buf = buf; 5234 xmlBufResetInput(buf->buffer, inputStream); 5235 5236 inputPush(reader->ctxt, inputStream); 5237 reader->cur = 0; 5238 } 5239 if (reader->ctxt == NULL) { 5240 xmlGenericError(xmlGenericErrorContext, 5241 "xmlTextReaderSetup : malloc failed\n"); 5242 return (-1); 5243 } 5244 } 5245 if (reader->dict != NULL) { 5246 if (reader->ctxt->dict != NULL) { 5247 if (reader->dict != reader->ctxt->dict) { 5248 xmlDictFree(reader->dict); 5249 reader->dict = reader->ctxt->dict; 5250 } 5251 } else { 5252 reader->ctxt->dict = reader->dict; 5253 } 5254 } else { 5255 if (reader->ctxt->dict == NULL) 5256 reader->ctxt->dict = xmlDictCreate(); 5257 reader->dict = reader->ctxt->dict; 5258 } 5259 reader->ctxt->_private = reader; 5260 reader->ctxt->linenumbers = 1; 5261 reader->ctxt->dictNames = 1; 5262 /* 5263 * use the parser dictionary to allocate all elements and attributes names 5264 */ 5265 reader->ctxt->docdict = 1; 5266 reader->ctxt->parseMode = XML_PARSE_READER; 5267 5268 #ifdef LIBXML_XINCLUDE_ENABLED 5269 if (reader->xincctxt != NULL) { 5270 xmlXIncludeFreeContext(reader->xincctxt); 5271 reader->xincctxt = NULL; 5272 } 5273 if (options & XML_PARSE_XINCLUDE) { 5274 reader->xinclude = 1; 5275 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); 5276 options -= XML_PARSE_XINCLUDE; 5277 } else 5278 reader->xinclude = 0; 5279 reader->in_xinclude = 0; 5280 #endif 5281 #ifdef LIBXML_PATTERN_ENABLED 5282 if (reader->patternTab == NULL) { 5283 reader->patternNr = 0; 5284 reader->patternMax = 0; 5285 } 5286 while (reader->patternNr > 0) { 5287 reader->patternNr--; 5288 if (reader->patternTab[reader->patternNr] != NULL) { 5289 xmlFreePattern(reader->patternTab[reader->patternNr]); 5290 reader->patternTab[reader->patternNr] = NULL; 5291 } 5292 } 5293 #endif 5294 5295 if (options & XML_PARSE_DTDVALID) 5296 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 5297 5298 xmlCtxtUseOptions(reader->ctxt, options); 5299 if (encoding != NULL) { 5300 xmlCharEncodingHandlerPtr hdlr; 5301 5302 hdlr = xmlFindCharEncodingHandler(encoding); 5303 if (hdlr != NULL) 5304 xmlSwitchToEncoding(reader->ctxt, hdlr); 5305 } 5306 if ((URL != NULL) && (reader->ctxt->input != NULL) && 5307 (reader->ctxt->input->filename == NULL)) 5308 reader->ctxt->input->filename = (char *) 5309 xmlStrdup((const xmlChar *) URL); 5310 5311 reader->doc = NULL; 5312 5313 return (0); 5314 } 5315 5316 /** 5317 * xmlTextReaderByteConsumed: 5318 * @reader: an XML reader 5319 * 5320 * This function provides the current index of the parser used 5321 * by the reader, relative to the start of the current entity. 5322 * This function actually just wraps a call to xmlBytesConsumed() 5323 * for the parser context associated with the reader. 5324 * See xmlBytesConsumed() for more information. 5325 * 5326 * Returns the index in bytes from the beginning of the entity or -1 5327 * in case the index could not be computed. 5328 */ 5329 long 5330 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) { 5331 if ((reader == NULL) || (reader->ctxt == NULL)) 5332 return(-1); 5333 return(xmlByteConsumed(reader->ctxt)); 5334 } 5335 5336 5337 /** 5338 * xmlReaderWalker: 5339 * @doc: a preparsed document 5340 * 5341 * Create an xmltextReader for a preparsed document. 5342 * 5343 * Returns the new reader or NULL in case of error. 5344 */ 5345 xmlTextReaderPtr 5346 xmlReaderWalker(xmlDocPtr doc) 5347 { 5348 xmlTextReaderPtr ret; 5349 5350 if (doc == NULL) 5351 return(NULL); 5352 5353 ret = xmlMalloc(sizeof(xmlTextReader)); 5354 if (ret == NULL) { 5355 xmlGenericError(xmlGenericErrorContext, 5356 "xmlNewTextReader : malloc failed\n"); 5357 return(NULL); 5358 } 5359 memset(ret, 0, sizeof(xmlTextReader)); 5360 ret->entNr = 0; 5361 ret->input = NULL; 5362 ret->mode = XML_TEXTREADER_MODE_INITIAL; 5363 ret->node = NULL; 5364 ret->curnode = NULL; 5365 ret->base = 0; 5366 ret->cur = 0; 5367 ret->allocs = XML_TEXTREADER_CTXT; 5368 ret->doc = doc; 5369 ret->state = XML_TEXTREADER_START; 5370 ret->dict = xmlDictCreate(); 5371 return(ret); 5372 } 5373 5374 /** 5375 * xmlReaderForDoc: 5376 * @cur: a pointer to a zero terminated string 5377 * @URL: the base URL to use for the document 5378 * @encoding: the document encoding, or NULL 5379 * @options: a combination of xmlParserOption 5380 * 5381 * Create an xmltextReader for an XML in-memory document. 5382 * The parsing flags @options are a combination of xmlParserOption. 5383 * 5384 * Returns the new reader or NULL in case of error. 5385 */ 5386 xmlTextReaderPtr 5387 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, 5388 int options) 5389 { 5390 int len; 5391 5392 if (cur == NULL) 5393 return (NULL); 5394 len = xmlStrlen(cur); 5395 5396 return (xmlReaderForMemory 5397 ((const char *) cur, len, URL, encoding, options)); 5398 } 5399 5400 /** 5401 * xmlReaderForFile: 5402 * @filename: a file or URL 5403 * @encoding: the document encoding, or NULL 5404 * @options: a combination of xmlParserOption 5405 * 5406 * parse an XML file from the filesystem or the network. 5407 * The parsing flags @options are a combination of xmlParserOption. 5408 * 5409 * Returns the new reader or NULL in case of error. 5410 */ 5411 xmlTextReaderPtr 5412 xmlReaderForFile(const char *filename, const char *encoding, int options) 5413 { 5414 xmlTextReaderPtr reader; 5415 5416 reader = xmlNewTextReaderFilename(filename); 5417 if (reader == NULL) 5418 return (NULL); 5419 xmlTextReaderSetup(reader, NULL, NULL, encoding, options); 5420 return (reader); 5421 } 5422 5423 /** 5424 * xmlReaderForMemory: 5425 * @buffer: a pointer to a char array 5426 * @size: the size of the array 5427 * @URL: the base URL to use for the document 5428 * @encoding: the document encoding, or NULL 5429 * @options: a combination of xmlParserOption 5430 * 5431 * Create an xmltextReader for an XML in-memory document. 5432 * The parsing flags @options are a combination of xmlParserOption. 5433 * 5434 * Returns the new reader or NULL in case of error. 5435 */ 5436 xmlTextReaderPtr 5437 xmlReaderForMemory(const char *buffer, int size, const char *URL, 5438 const char *encoding, int options) 5439 { 5440 xmlTextReaderPtr reader; 5441 xmlParserInputBufferPtr buf; 5442 5443 buf = xmlParserInputBufferCreateStatic(buffer, size, 5444 XML_CHAR_ENCODING_NONE); 5445 if (buf == NULL) { 5446 return (NULL); 5447 } 5448 reader = xmlNewTextReader(buf, URL); 5449 if (reader == NULL) { 5450 xmlFreeParserInputBuffer(buf); 5451 return (NULL); 5452 } 5453 reader->allocs |= XML_TEXTREADER_INPUT; 5454 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5455 return (reader); 5456 } 5457 5458 /** 5459 * xmlReaderForFd: 5460 * @fd: an open file descriptor 5461 * @URL: the base URL to use for the document 5462 * @encoding: the document encoding, or NULL 5463 * @options: a combination of xmlParserOption 5464 * 5465 * Create an xmltextReader for an XML from a file descriptor. 5466 * The parsing flags @options are a combination of xmlParserOption. 5467 * NOTE that the file descriptor will not be closed when the 5468 * reader is closed or reset. 5469 * 5470 * Returns the new reader or NULL in case of error. 5471 */ 5472 xmlTextReaderPtr 5473 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) 5474 { 5475 xmlTextReaderPtr reader; 5476 xmlParserInputBufferPtr input; 5477 5478 if (fd < 0) 5479 return (NULL); 5480 5481 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 5482 if (input == NULL) 5483 return (NULL); 5484 input->closecallback = NULL; 5485 reader = xmlNewTextReader(input, URL); 5486 if (reader == NULL) { 5487 xmlFreeParserInputBuffer(input); 5488 return (NULL); 5489 } 5490 reader->allocs |= XML_TEXTREADER_INPUT; 5491 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5492 return (reader); 5493 } 5494 5495 /** 5496 * xmlReaderForIO: 5497 * @ioread: an I/O read function 5498 * @ioclose: an I/O close function 5499 * @ioctx: an I/O handler 5500 * @URL: the base URL to use for the document 5501 * @encoding: the document encoding, or NULL 5502 * @options: a combination of xmlParserOption 5503 * 5504 * Create an xmltextReader for an XML document from I/O functions and source. 5505 * The parsing flags @options are a combination of xmlParserOption. 5506 * 5507 * Returns the new reader or NULL in case of error. 5508 */ 5509 xmlTextReaderPtr 5510 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, 5511 void *ioctx, const char *URL, const char *encoding, 5512 int options) 5513 { 5514 xmlTextReaderPtr reader; 5515 xmlParserInputBufferPtr input; 5516 5517 if (ioread == NULL) 5518 return (NULL); 5519 5520 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 5521 XML_CHAR_ENCODING_NONE); 5522 if (input == NULL) { 5523 if (ioclose != NULL) 5524 ioclose(ioctx); 5525 return (NULL); 5526 } 5527 reader = xmlNewTextReader(input, URL); 5528 if (reader == NULL) { 5529 xmlFreeParserInputBuffer(input); 5530 return (NULL); 5531 } 5532 reader->allocs |= XML_TEXTREADER_INPUT; 5533 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 5534 return (reader); 5535 } 5536 5537 /** 5538 * xmlReaderNewWalker: 5539 * @reader: an XML reader 5540 * @doc: a preparsed document 5541 * 5542 * Setup an xmltextReader to parse a preparsed XML document. 5543 * This reuses the existing @reader xmlTextReader. 5544 * 5545 * Returns 0 in case of success and -1 in case of error 5546 */ 5547 int 5548 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc) 5549 { 5550 if (doc == NULL) 5551 return (-1); 5552 if (reader == NULL) 5553 return (-1); 5554 5555 if (reader->input != NULL) { 5556 xmlFreeParserInputBuffer(reader->input); 5557 } 5558 if (reader->ctxt != NULL) { 5559 xmlCtxtReset(reader->ctxt); 5560 } 5561 5562 reader->entNr = 0; 5563 reader->input = NULL; 5564 reader->mode = XML_TEXTREADER_MODE_INITIAL; 5565 reader->node = NULL; 5566 reader->curnode = NULL; 5567 reader->base = 0; 5568 reader->cur = 0; 5569 reader->allocs = XML_TEXTREADER_CTXT; 5570 reader->doc = doc; 5571 reader->state = XML_TEXTREADER_START; 5572 if (reader->dict == NULL) { 5573 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) 5574 reader->dict = reader->ctxt->dict; 5575 else 5576 reader->dict = xmlDictCreate(); 5577 } 5578 return(0); 5579 } 5580 5581 /** 5582 * xmlReaderNewDoc: 5583 * @reader: an XML reader 5584 * @cur: a pointer to a zero terminated string 5585 * @URL: the base URL to use for the document 5586 * @encoding: the document encoding, or NULL 5587 * @options: a combination of xmlParserOption 5588 * 5589 * Setup an xmltextReader to parse an XML in-memory document. 5590 * The parsing flags @options are a combination of xmlParserOption. 5591 * This reuses the existing @reader xmlTextReader. 5592 * 5593 * Returns 0 in case of success and -1 in case of error 5594 */ 5595 int 5596 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, 5597 const char *URL, const char *encoding, int options) 5598 { 5599 5600 int len; 5601 5602 if (cur == NULL) 5603 return (-1); 5604 if (reader == NULL) 5605 return (-1); 5606 5607 len = xmlStrlen(cur); 5608 return (xmlReaderNewMemory(reader, (const char *)cur, len, 5609 URL, encoding, options)); 5610 } 5611 5612 /** 5613 * xmlReaderNewFile: 5614 * @reader: an XML reader 5615 * @filename: a file or URL 5616 * @encoding: the document encoding, or NULL 5617 * @options: a combination of xmlParserOption 5618 * 5619 * parse an XML file from the filesystem or the network. 5620 * The parsing flags @options are a combination of xmlParserOption. 5621 * This reuses the existing @reader xmlTextReader. 5622 * 5623 * Returns 0 in case of success and -1 in case of error 5624 */ 5625 int 5626 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, 5627 const char *encoding, int options) 5628 { 5629 xmlParserInputBufferPtr input; 5630 5631 if (filename == NULL) 5632 return (-1); 5633 if (reader == NULL) 5634 return (-1); 5635 5636 input = 5637 xmlParserInputBufferCreateFilename(filename, 5638 XML_CHAR_ENCODING_NONE); 5639 if (input == NULL) 5640 return (-1); 5641 return (xmlTextReaderSetup(reader, input, filename, encoding, options)); 5642 } 5643 5644 /** 5645 * xmlReaderNewMemory: 5646 * @reader: an XML reader 5647 * @buffer: a pointer to a char array 5648 * @size: the size of the array 5649 * @URL: the base URL to use for the document 5650 * @encoding: the document encoding, or NULL 5651 * @options: a combination of xmlParserOption 5652 * 5653 * Setup an xmltextReader to parse an XML in-memory document. 5654 * The parsing flags @options are a combination of xmlParserOption. 5655 * This reuses the existing @reader xmlTextReader. 5656 * 5657 * Returns 0 in case of success and -1 in case of error 5658 */ 5659 int 5660 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, 5661 const char *URL, const char *encoding, int options) 5662 { 5663 xmlParserInputBufferPtr input; 5664 5665 if (reader == NULL) 5666 return (-1); 5667 if (buffer == NULL) 5668 return (-1); 5669 5670 input = xmlParserInputBufferCreateStatic(buffer, size, 5671 XML_CHAR_ENCODING_NONE); 5672 if (input == NULL) { 5673 return (-1); 5674 } 5675 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5676 } 5677 5678 /** 5679 * xmlReaderNewFd: 5680 * @reader: an XML reader 5681 * @fd: an open file descriptor 5682 * @URL: the base URL to use for the document 5683 * @encoding: the document encoding, or NULL 5684 * @options: a combination of xmlParserOption 5685 * 5686 * Setup an xmltextReader to parse an XML from a file descriptor. 5687 * NOTE that the file descriptor will not be closed when the 5688 * reader is closed or reset. 5689 * The parsing flags @options are a combination of xmlParserOption. 5690 * This reuses the existing @reader xmlTextReader. 5691 * 5692 * Returns 0 in case of success and -1 in case of error 5693 */ 5694 int 5695 xmlReaderNewFd(xmlTextReaderPtr reader, int fd, 5696 const char *URL, const char *encoding, int options) 5697 { 5698 xmlParserInputBufferPtr input; 5699 5700 if (fd < 0) 5701 return (-1); 5702 if (reader == NULL) 5703 return (-1); 5704 5705 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 5706 if (input == NULL) 5707 return (-1); 5708 input->closecallback = NULL; 5709 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5710 } 5711 5712 /** 5713 * xmlReaderNewIO: 5714 * @reader: an XML reader 5715 * @ioread: an I/O read function 5716 * @ioclose: an I/O close function 5717 * @ioctx: an I/O handler 5718 * @URL: the base URL to use for the document 5719 * @encoding: the document encoding, or NULL 5720 * @options: a combination of xmlParserOption 5721 * 5722 * Setup an xmltextReader to parse an XML document from I/O functions 5723 * and source. 5724 * The parsing flags @options are a combination of xmlParserOption. 5725 * This reuses the existing @reader xmlTextReader. 5726 * 5727 * Returns 0 in case of success and -1 in case of error 5728 */ 5729 int 5730 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, 5731 xmlInputCloseCallback ioclose, void *ioctx, 5732 const char *URL, const char *encoding, int options) 5733 { 5734 xmlParserInputBufferPtr input; 5735 5736 if (ioread == NULL) 5737 return (-1); 5738 if (reader == NULL) 5739 return (-1); 5740 5741 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 5742 XML_CHAR_ENCODING_NONE); 5743 if (input == NULL) { 5744 if (ioclose != NULL) 5745 ioclose(ioctx); 5746 return (-1); 5747 } 5748 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 5749 } 5750 5751 /************************************************************************ 5752 * * 5753 * Utilities * 5754 * * 5755 ************************************************************************/ 5756 #ifdef NOT_USED_YET 5757 5758 /** 5759 * xmlBase64Decode: 5760 * @in: the input buffer 5761 * @inlen: the size of the input (in), the size read from it (out) 5762 * @to: the output buffer 5763 * @tolen: the size of the output (in), the size written to (out) 5764 * 5765 * Base64 decoder, reads from @in and save in @to 5766 * TODO: tell jody when this is actually exported 5767 * 5768 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, 5769 * 2 if there wasn't enough space on the output or -1 in case of error. 5770 */ 5771 static int 5772 xmlBase64Decode(const unsigned char *in, unsigned long *inlen, 5773 unsigned char *to, unsigned long *tolen) 5774 { 5775 unsigned long incur; /* current index in in[] */ 5776 5777 unsigned long inblk; /* last block index in in[] */ 5778 5779 unsigned long outcur; /* current index in out[] */ 5780 5781 unsigned long inmax; /* size of in[] */ 5782 5783 unsigned long outmax; /* size of out[] */ 5784 5785 unsigned char cur; /* the current value read from in[] */ 5786 5787 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */ 5788 5789 int nbintmp; /* number of byte in intmp[] */ 5790 5791 int is_ignore; /* cur should be ignored */ 5792 5793 int is_end = 0; /* the end of the base64 was found */ 5794 5795 int retval = 1; 5796 5797 int i; 5798 5799 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) 5800 return (-1); 5801 5802 incur = 0; 5803 inblk = 0; 5804 outcur = 0; 5805 inmax = *inlen; 5806 outmax = *tolen; 5807 nbintmp = 0; 5808 5809 while (1) { 5810 if (incur >= inmax) 5811 break; 5812 cur = in[incur++]; 5813 is_ignore = 0; 5814 if ((cur >= 'A') && (cur <= 'Z')) 5815 cur = cur - 'A'; 5816 else if ((cur >= 'a') && (cur <= 'z')) 5817 cur = cur - 'a' + 26; 5818 else if ((cur >= '0') && (cur <= '9')) 5819 cur = cur - '0' + 52; 5820 else if (cur == '+') 5821 cur = 62; 5822 else if (cur == '/') 5823 cur = 63; 5824 else if (cur == '.') 5825 cur = 0; 5826 else if (cur == '=') /*no op , end of the base64 stream */ 5827 is_end = 1; 5828 else { 5829 is_ignore = 1; 5830 if (nbintmp == 0) 5831 inblk = incur; 5832 } 5833 5834 if (!is_ignore) { 5835 int nbouttmp = 3; 5836 5837 int is_break = 0; 5838 5839 if (is_end) { 5840 if (nbintmp == 0) 5841 break; 5842 if ((nbintmp == 1) || (nbintmp == 2)) 5843 nbouttmp = 1; 5844 else 5845 nbouttmp = 2; 5846 nbintmp = 3; 5847 is_break = 1; 5848 } 5849 intmp[nbintmp++] = cur; 5850 /* 5851 * if intmp is full, push the 4byte sequence as a 3 byte 5852 * sequence out 5853 */ 5854 if (nbintmp == 4) { 5855 nbintmp = 0; 5856 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); 5857 outtmp[1] = 5858 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); 5859 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); 5860 if (outcur + 3 >= outmax) { 5861 retval = 2; 5862 break; 5863 } 5864 5865 for (i = 0; i < nbouttmp; i++) 5866 to[outcur++] = outtmp[i]; 5867 inblk = incur; 5868 } 5869 5870 if (is_break) { 5871 retval = 0; 5872 break; 5873 } 5874 } 5875 } 5876 5877 *tolen = outcur; 5878 *inlen = inblk; 5879 return (retval); 5880 } 5881 5882 /* 5883 * Test routine for the xmlBase64Decode function 5884 */ 5885 #if 0 5886 int 5887 main(int argc, char **argv) 5888 { 5889 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== "; 5890 5891 char output[100]; 5892 5893 char output2[100]; 5894 5895 char output3[100]; 5896 5897 unsigned long inlen = strlen(input); 5898 5899 unsigned long outlen = 100; 5900 5901 int ret; 5902 5903 unsigned long cons, tmp, tmp2, prod; 5904 5905 /* 5906 * Direct 5907 */ 5908 ret = xmlBase64Decode(input, &inlen, output, &outlen); 5909 5910 output[outlen] = 0; 5911 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, 5912 outlen, output)indent: Standard input:179: Error:Unmatched #endif 5913 ; 5914 5915 /* 5916 * output chunking 5917 */ 5918 cons = 0; 5919 prod = 0; 5920 while (cons < inlen) { 5921 tmp = 5; 5922 tmp2 = inlen - cons; 5923 5924 printf("%ld %ld\n", cons, prod); 5925 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); 5926 cons += tmp2; 5927 prod += tmp; 5928 printf("%ld %ld\n", cons, prod); 5929 } 5930 output2[outlen] = 0; 5931 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, 5932 prod, output2); 5933 5934 /* 5935 * input chunking 5936 */ 5937 cons = 0; 5938 prod = 0; 5939 while (cons < inlen) { 5940 tmp = 100 - prod; 5941 tmp2 = inlen - cons; 5942 if (tmp2 > 5) 5943 tmp2 = 5; 5944 5945 printf("%ld %ld\n", cons, prod); 5946 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); 5947 cons += tmp2; 5948 prod += tmp; 5949 printf("%ld %ld\n", cons, prod); 5950 } 5951 output3[outlen] = 0; 5952 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, 5953 prod, output3); 5954 return (0); 5955 5956 } 5957 #endif 5958 #endif /* NOT_USED_YET */ 5959 #define bottom_xmlreader 5960 #include "elfgcchack.h" 5961 #endif /* LIBXML_READER_ENABLED */ 5962