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