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