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