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