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