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