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