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