xmlreader.c revision e74d2e1cb85b184b327c1b41d2b1c2dfbcc653d7
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) || (reader->ctxt == NULL)) 1486 return(NULL); 1487 if (reader->doc != NULL) 1488 return(reader->node); 1489 if (xmlTextReaderDoExpand(reader) < 0) 1490 return(NULL); 1491 return(reader->node); 1492} 1493 1494/** 1495 * xmlTextReaderNext: 1496 * @reader: the xmlTextReaderPtr used 1497 * 1498 * Skip to the node following the current one in document order while 1499 * avoiding the subtree if any. 1500 * 1501 * Returns 1 if the node was read successfully, 0 if there is no more 1502 * nodes to read, or -1 in case of error 1503 */ 1504int 1505xmlTextReaderNext(xmlTextReaderPtr reader) { 1506 int ret; 1507 xmlNodePtr cur; 1508 1509 if (reader == NULL) 1510 return(-1); 1511 if (reader->doc != NULL) 1512 return(xmlTextReaderNextTree(reader)); 1513 cur = reader->node; 1514 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) 1515 return(xmlTextReaderRead(reader)); 1516 if (reader->state == XML_TEXTREADER_END) 1517 return(xmlTextReaderRead(reader)); 1518 if (cur->extra & NODE_IS_EMPTY) 1519 return(xmlTextReaderRead(reader)); 1520 do { 1521 ret = xmlTextReaderRead(reader); 1522 if (ret != 1) 1523 return(ret); 1524 } while (reader->node != cur); 1525 return(xmlTextReaderRead(reader)); 1526} 1527 1528/** 1529 * xmlTextReaderReadInnerXml: 1530 * @reader: the xmlTextReaderPtr used 1531 * 1532 * Reads the contents of the current node, including child nodes and markup. 1533 * 1534 * Returns a string containing the XML content, or NULL if the current node 1535 * is neither an element nor attribute, or has no child nodes. The 1536 * string must be deallocated by the caller. 1537 */ 1538xmlChar * 1539xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { 1540 TODO 1541 return(NULL); 1542} 1543 1544/** 1545 * xmlTextReaderReadOuterXml: 1546 * @reader: the xmlTextReaderPtr used 1547 * 1548 * Reads the contents of the current node, including child nodes and markup. 1549 * 1550 * Returns a string containing the XML content, or NULL if the current node 1551 * is neither an element nor attribute, or has no child nodes. The 1552 * string must be deallocated by the caller. 1553 */ 1554xmlChar * 1555xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { 1556 TODO 1557 return(NULL); 1558} 1559 1560/** 1561 * xmlTextReaderReadString: 1562 * @reader: the xmlTextReaderPtr used 1563 * 1564 * Reads the contents of an element or a text node as a string. 1565 * 1566 * Returns a string containing the contents of the Element or Text node, 1567 * or NULL if the reader is positioned on any other type of node. 1568 * The string must be deallocated by the caller. 1569 */ 1570xmlChar * 1571xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { 1572 TODO 1573 return(NULL); 1574} 1575 1576#if 0 1577/** 1578 * xmlTextReaderReadBase64: 1579 * @reader: the xmlTextReaderPtr used 1580 * @array: a byte array to store the content. 1581 * @offset: the zero-based index into array where the method should 1582 * begin to write. 1583 * @len: the number of bytes to write. 1584 * 1585 * Reads and decodes the Base64 encoded contents of an element and 1586 * stores the result in a byte buffer. 1587 * 1588 * Returns the number of bytes written to array, or zero if the current 1589 * instance is not positioned on an element or -1 in case of error. 1590 */ 1591int 1592xmlTextReaderReadBase64(xmlTextReaderPtr reader, 1593 unsigned char *array ATTRIBUTE_UNUSED, 1594 int offset ATTRIBUTE_UNUSED, 1595 int len ATTRIBUTE_UNUSED) { 1596 if ((reader == NULL) || (reader->ctxt == NULL)) 1597 return(-1); 1598 if (reader->ctxt->wellFormed != 1) 1599 return(-1); 1600 1601 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1602 return(0); 1603 TODO 1604 return(0); 1605} 1606 1607/** 1608 * xmlTextReaderReadBinHex: 1609 * @reader: the xmlTextReaderPtr used 1610 * @array: a byte array to store the content. 1611 * @offset: the zero-based index into array where the method should 1612 * begin to write. 1613 * @len: the number of bytes to write. 1614 * 1615 * Reads and decodes the BinHex encoded contents of an element and 1616 * stores the result in a byte buffer. 1617 * 1618 * Returns the number of bytes written to array, or zero if the current 1619 * instance is not positioned on an element or -1 in case of error. 1620 */ 1621int 1622xmlTextReaderReadBinHex(xmlTextReaderPtr reader, 1623 unsigned char *array ATTRIBUTE_UNUSED, 1624 int offset ATTRIBUTE_UNUSED, 1625 int len ATTRIBUTE_UNUSED) { 1626 if ((reader == NULL) || (reader->ctxt == NULL)) 1627 return(-1); 1628 if (reader->ctxt->wellFormed != 1) 1629 return(-1); 1630 1631 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) 1632 return(0); 1633 TODO 1634 return(0); 1635} 1636#endif 1637 1638/************************************************************************ 1639 * * 1640 * Operating on a preparsed tree * 1641 * * 1642 ************************************************************************/ 1643static int 1644xmlTextReaderNextTree(xmlTextReaderPtr reader) 1645{ 1646 if (reader == NULL) 1647 return(-1); 1648 1649 if (reader->state == XML_TEXTREADER_END) 1650 return(0); 1651 1652 if (reader->node == NULL) { 1653 if (reader->doc->children == NULL) { 1654 reader->state = XML_TEXTREADER_END; 1655 return(0); 1656 } 1657 1658 reader->node = reader->doc->children; 1659 reader->state = XML_TEXTREADER_START; 1660 return(1); 1661 } 1662 1663 if (reader->state != XML_TEXTREADER_BACKTRACK) { 1664 if (reader->node->children != 0) { 1665 reader->node = reader->node->children; 1666 reader->depth++; 1667 reader->state = XML_TEXTREADER_START; 1668 return(1); 1669 } 1670 1671 if ((reader->node->type == XML_ELEMENT_NODE) || 1672 (reader->node->type == XML_ATTRIBUTE_NODE)) { 1673 reader->state = XML_TEXTREADER_BACKTRACK; 1674 return(1); 1675 } 1676 } 1677 1678 if (reader->node->next != 0) { 1679 reader->node = reader->node->next; 1680 reader->state = XML_TEXTREADER_START; 1681 return(1); 1682 } 1683 1684 if (reader->node->parent != 0) { 1685 if (reader->node->parent->type == XML_DOCUMENT_NODE) { 1686 reader->state = XML_TEXTREADER_END; 1687 return(0); 1688 } 1689 1690 reader->node = reader->node->parent; 1691 reader->depth--; 1692 reader->state = XML_TEXTREADER_BACKTRACK; 1693 return(1); 1694 } 1695 1696 reader->state = XML_TEXTREADER_END; 1697 1698 return(1); 1699} 1700 1701/** 1702 * xmlTextReaderReadTree: 1703 * @reader: the xmlTextReaderPtr used 1704 * 1705 * Moves the position of the current instance to the next node in 1706 * the stream, exposing its properties. 1707 * 1708 * Returns 1 if the node was read successfully, 0 if there is no more 1709 * nodes to read, or -1 in case of error 1710 */ 1711static int 1712xmlTextReaderReadTree(xmlTextReaderPtr reader) { 1713 if (reader->state == XML_TEXTREADER_END) 1714 return(0); 1715 1716next_node: 1717 if (reader->node == NULL) { 1718 if (reader->doc->children == NULL) { 1719 reader->state = XML_TEXTREADER_END; 1720 return(0); 1721 } 1722 1723 reader->node = reader->doc->children; 1724 reader->state = XML_TEXTREADER_START; 1725 goto found_node; 1726 } 1727 1728 if ((reader->state != XML_TEXTREADER_BACKTRACK) && 1729 (reader->node->type != XML_DTD_NODE) && 1730 (reader->node->type != XML_XINCLUDE_START) && 1731 (reader->node->type != XML_ENTITY_REF_NODE)) { 1732 if (reader->node->children != NULL) { 1733 reader->node = reader->node->children; 1734 reader->depth++; 1735 reader->state = XML_TEXTREADER_START; 1736 goto found_node; 1737 } 1738 1739 if (reader->node->type == XML_ATTRIBUTE_NODE) { 1740 reader->state = XML_TEXTREADER_BACKTRACK; 1741 goto found_node; 1742 } 1743 } 1744 1745 if (reader->node->next != NULL) { 1746 reader->node = reader->node->next; 1747 reader->state = XML_TEXTREADER_START; 1748 goto found_node; 1749 } 1750 1751 if (reader->node->parent != NULL) { 1752 if ((reader->node->parent->type == XML_DOCUMENT_NODE) || 1753 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { 1754 reader->state = XML_TEXTREADER_END; 1755 return(0); 1756 } 1757 1758 reader->node = reader->node->parent; 1759 reader->depth--; 1760 reader->state = XML_TEXTREADER_BACKTRACK; 1761 goto found_node; 1762 } 1763 1764 reader->state = XML_TEXTREADER_END; 1765 1766found_node: 1767 if ((reader->node->type == XML_XINCLUDE_START) || 1768 (reader->node->type == XML_XINCLUDE_END)) 1769 goto next_node; 1770 1771 return(1); 1772} 1773 1774/** 1775 * xmlTextReaderNextSibling: 1776 * @reader: the xmlTextReaderPtr used 1777 * 1778 * Skip to the node following the current one in document order while 1779 * avoiding the subtree if any. 1780 * Currently implemented only for Readers built on a document 1781 * 1782 * Returns 1 if the node was read successfully, 0 if there is no more 1783 * nodes to read, or -1 in case of error 1784 */ 1785int 1786xmlTextReaderNextSibling(xmlTextReaderPtr reader) { 1787 if (reader == NULL) 1788 return(-1); 1789 if (reader->doc == NULL) { 1790 TODO 1791 return(-1); 1792 } 1793 1794 if (reader->state == XML_TEXTREADER_END) 1795 return(0); 1796 1797 if (reader->node == NULL) 1798 return(xmlTextReaderNextTree(reader)); 1799 1800 if (reader->node->next != NULL) { 1801 reader->node = reader->node->next; 1802 reader->state = XML_TEXTREADER_START; 1803 return(1); 1804 } 1805 1806 return(0); 1807} 1808 1809/************************************************************************ 1810 * * 1811 * Constructor and destructors * 1812 * * 1813 ************************************************************************/ 1814/** 1815 * xmlNewTextReader: 1816 * @input: the xmlParserInputBufferPtr used to read data 1817 * @URI: the URI information for the source if available 1818 * 1819 * Create an xmlTextReader structure fed with @input 1820 * 1821 * Returns the new xmlTextReaderPtr or NULL in case of error 1822 */ 1823xmlTextReaderPtr 1824xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { 1825 xmlTextReaderPtr ret; 1826 1827 if (input == NULL) 1828 return(NULL); 1829 ret = xmlMalloc(sizeof(xmlTextReader)); 1830 if (ret == NULL) { 1831 xmlGenericError(xmlGenericErrorContext, 1832 "xmlNewTextReader : malloc failed\n"); 1833 return(NULL); 1834 } 1835 memset(ret, 0, sizeof(xmlTextReader)); 1836 ret->doc = NULL; 1837 ret->entTab = NULL; 1838 ret->entMax = 0; 1839 ret->entNr = 0; 1840 ret->input = input; 1841 ret->buffer = xmlBufferCreateSize(100); 1842 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 1843 if (ret->sax == NULL) { 1844 xmlFree(ret); 1845 xmlGenericError(xmlGenericErrorContext, 1846 "xmlNewTextReader : malloc failed\n"); 1847 return(NULL); 1848 } 1849 xmlSAXVersion(ret->sax, 2); 1850 ret->startElement = ret->sax->startElement; 1851 ret->sax->startElement = xmlTextReaderStartElement; 1852 ret->endElement = ret->sax->endElement; 1853 ret->sax->endElement = xmlTextReaderEndElement; 1854#ifdef LIBXML_SAX1_ENABLED 1855 if (ret->sax->initialized == XML_SAX2_MAGIC) { 1856#endif /* LIBXML_SAX1_ENABLED */ 1857 ret->startElementNs = ret->sax->startElementNs; 1858 ret->sax->startElementNs = xmlTextReaderStartElementNs; 1859 ret->endElementNs = ret->sax->endElementNs; 1860 ret->sax->endElementNs = xmlTextReaderEndElementNs; 1861#ifdef LIBXML_SAX1_ENABLED 1862 } else { 1863 ret->startElementNs = NULL; 1864 ret->endElementNs = NULL; 1865 } 1866#endif /* LIBXML_SAX1_ENABLED */ 1867 ret->characters = ret->sax->characters; 1868 ret->sax->characters = xmlTextReaderCharacters; 1869 ret->sax->ignorableWhitespace = xmlTextReaderCharacters; 1870 ret->cdataBlock = ret->sax->cdataBlock; 1871 ret->sax->cdataBlock = xmlTextReaderCDataBlock; 1872 1873 ret->mode = XML_TEXTREADER_MODE_INITIAL; 1874 ret->node = NULL; 1875 ret->curnode = NULL; 1876 if (ret->input->buffer->use < 4) { 1877 xmlParserInputBufferRead(input, 4); 1878 } 1879 if (ret->input->buffer->use >= 4) { 1880 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, 1881 (const char *) ret->input->buffer->content, 4, URI); 1882 ret->base = 0; 1883 ret->cur = 4; 1884 } else { 1885 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); 1886 ret->base = 0; 1887 ret->cur = 0; 1888 } 1889 if (ret->ctxt == NULL) { 1890 xmlGenericError(xmlGenericErrorContext, 1891 "xmlNewTextReader : malloc failed\n"); 1892 xmlFree(ret->sax); 1893 xmlFree(ret); 1894 return(NULL); 1895 } 1896 ret->ctxt->_private = ret; 1897 ret->ctxt->linenumbers = 1; 1898 ret->ctxt->dictNames = 1; 1899 ret->allocs = XML_TEXTREADER_CTXT; 1900 /* 1901 * use the parser dictionnary to allocate all elements and attributes names 1902 */ 1903 ret->ctxt->docdict = 1; 1904 ret->dict = ret->ctxt->dict; 1905#ifdef LIBXML_XINCLUDE_ENABLED 1906 ret->xinclude = 0; 1907#endif 1908#ifdef LIBXML_PATTERN_ENABLED 1909 ret->patternMax = 0; 1910 ret->patternTab = NULL; 1911#endif 1912 return(ret); 1913} 1914 1915/** 1916 * xmlNewTextReaderFilename: 1917 * @URI: the URI of the resource to process 1918 * 1919 * Create an xmlTextReader structure fed with the resource at @URI 1920 * 1921 * Returns the new xmlTextReaderPtr or NULL in case of error 1922 */ 1923xmlTextReaderPtr 1924xmlNewTextReaderFilename(const char *URI) { 1925 xmlParserInputBufferPtr input; 1926 xmlTextReaderPtr ret; 1927 char *directory = NULL; 1928 1929 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); 1930 if (input == NULL) 1931 return(NULL); 1932 ret = xmlNewTextReader(input, URI); 1933 if (ret == NULL) { 1934 xmlFreeParserInputBuffer(input); 1935 return(NULL); 1936 } 1937 ret->allocs |= XML_TEXTREADER_INPUT; 1938 if (ret->ctxt->directory == NULL) 1939 directory = xmlParserGetDirectory(URI); 1940 if ((ret->ctxt->directory == NULL) && (directory != NULL)) 1941 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); 1942 if (directory != NULL) 1943 xmlFree(directory); 1944 return(ret); 1945} 1946 1947/** 1948 * xmlFreeTextReader: 1949 * @reader: the xmlTextReaderPtr 1950 * 1951 * Deallocate all the resources associated to the reader 1952 */ 1953void 1954xmlFreeTextReader(xmlTextReaderPtr reader) { 1955 if (reader == NULL) 1956 return; 1957#ifdef LIBXML_SCHEMAS_ENABLED 1958 if (reader->rngSchemas != NULL) { 1959 xmlRelaxNGFree(reader->rngSchemas); 1960 reader->rngSchemas = NULL; 1961 } 1962 if (reader->rngValidCtxt != NULL) { 1963 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 1964 reader->rngValidCtxt = NULL; 1965 } 1966#endif 1967#ifdef LIBXML_XINCLUDE_ENABLED 1968 if (reader->xincctxt != NULL) 1969 xmlXIncludeFreeContext(reader->xincctxt); 1970#endif 1971#ifdef LIBXML_PATTERN_ENABLED 1972 if (reader->patternTab != NULL) { 1973 int i; 1974 for (i = 0;i < reader->patternNr;i++) { 1975 if (reader->patternTab[i] != NULL) 1976 xmlFreePattern(reader->patternTab[i]); 1977 } 1978 xmlFree(reader->patternTab); 1979 } 1980#endif 1981 if (reader->ctxt != NULL) { 1982 if (reader->dict == reader->ctxt->dict) 1983 reader->dict = NULL; 1984 if (reader->ctxt->myDoc != NULL) { 1985 if (reader->preserve == 0) 1986 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 1987 reader->ctxt->myDoc = NULL; 1988 } 1989 if ((reader->ctxt->vctxt.vstateTab != NULL) && 1990 (reader->ctxt->vctxt.vstateMax > 0)){ 1991 xmlFree(reader->ctxt->vctxt.vstateTab); 1992 reader->ctxt->vctxt.vstateTab = 0; 1993 reader->ctxt->vctxt.vstateMax = 0; 1994 } 1995 if (reader->allocs & XML_TEXTREADER_CTXT) 1996 xmlFreeParserCtxt(reader->ctxt); 1997 } 1998 if (reader->sax != NULL) 1999 xmlFree(reader->sax); 2000 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) 2001 xmlFreeParserInputBuffer(reader->input); 2002 if (reader->faketext != NULL) { 2003 xmlFreeNode(reader->faketext); 2004 } 2005 if (reader->buffer != NULL) 2006 xmlBufferFree(reader->buffer); 2007 if (reader->entTab != NULL) 2008 xmlFree(reader->entTab); 2009 if (reader->dict != NULL) 2010 xmlDictFree(reader->dict); 2011 xmlFree(reader); 2012} 2013 2014/************************************************************************ 2015 * * 2016 * Methods for XmlTextReader * 2017 * * 2018 ************************************************************************/ 2019/** 2020 * xmlTextReaderClose: 2021 * @reader: the xmlTextReaderPtr used 2022 * 2023 * This method releases any resources allocated by the current instance 2024 * changes the state to Closed and close any underlying input. 2025 * 2026 * Returns 0 or -1 in case of error 2027 */ 2028int 2029xmlTextReaderClose(xmlTextReaderPtr reader) { 2030 if (reader == NULL) 2031 return(-1); 2032 reader->node = NULL; 2033 reader->curnode = NULL; 2034 reader->mode = XML_TEXTREADER_MODE_CLOSED; 2035 if (reader->ctxt != NULL) { 2036 if (reader->ctxt->myDoc != NULL) { 2037 if (reader->preserve == 0) 2038 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2039 reader->ctxt->myDoc = NULL; 2040 } 2041 if (reader->allocs & XML_TEXTREADER_CTXT) { 2042 xmlFreeParserCtxt(reader->ctxt); 2043 reader->allocs -= XML_TEXTREADER_CTXT; 2044 } 2045 } 2046 if (reader->sax != NULL) { 2047 xmlFree(reader->sax); 2048 reader->sax = NULL; 2049 } 2050 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { 2051 xmlFreeParserInputBuffer(reader->input); 2052 reader->allocs -= XML_TEXTREADER_INPUT; 2053 } 2054 return(0); 2055} 2056 2057/** 2058 * xmlTextReaderGetAttributeNo: 2059 * @reader: the xmlTextReaderPtr used 2060 * @no: the zero-based index of the attribute relative to the containing element 2061 * 2062 * Provides the value of the attribute with the specified index relative 2063 * to the containing element. 2064 * 2065 * Returns a string containing the value of the specified attribute, or NULL 2066 * in case of error. The string must be deallocated by the caller. 2067 */ 2068xmlChar * 2069xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { 2070 xmlChar *ret; 2071 int i; 2072 xmlAttrPtr cur; 2073 xmlNsPtr ns; 2074 2075 if (reader == NULL) 2076 return(NULL); 2077 if (reader->node == NULL) 2078 return(NULL); 2079 if (reader->curnode != NULL) 2080 return(NULL); 2081 /* TODO: handle the xmlDecl */ 2082 if (reader->node->type != XML_ELEMENT_NODE) 2083 return(NULL); 2084 2085 ns = reader->node->nsDef; 2086 for (i = 0;(i < no) && (ns != NULL);i++) { 2087 ns = ns->next; 2088 } 2089 if (ns != NULL) 2090 return(xmlStrdup(ns->href)); 2091 2092 cur = reader->node->properties; 2093 if (cur == NULL) 2094 return(NULL); 2095 for (;i < no;i++) { 2096 cur = cur->next; 2097 if (cur == NULL) 2098 return(NULL); 2099 } 2100 /* TODO walk the DTD if present */ 2101 2102 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); 2103 if (ret == NULL) return(xmlStrdup((xmlChar *)"")); 2104 return(ret); 2105} 2106 2107/** 2108 * xmlTextReaderGetAttribute: 2109 * @reader: the xmlTextReaderPtr used 2110 * @name: the qualified name of the attribute. 2111 * 2112 * Provides the value of the attribute with the specified qualified name. 2113 * 2114 * Returns a string containing the value of the specified attribute, or NULL 2115 * in case of error. The string must be deallocated by the caller. 2116 */ 2117xmlChar * 2118xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2119 xmlChar *prefix = NULL; 2120 xmlChar *localname; 2121 xmlNsPtr ns; 2122 xmlChar *ret = NULL; 2123 2124 if ((reader == NULL) || (name == NULL)) 2125 return(NULL); 2126 if (reader->node == NULL) 2127 return(NULL); 2128 if (reader->curnode != NULL) 2129 return(NULL); 2130 2131 /* TODO: handle the xmlDecl */ 2132 if (reader->node->type != XML_ELEMENT_NODE) 2133 return(NULL); 2134 2135 localname = xmlSplitQName2(name, &prefix); 2136 if (localname == NULL) 2137 return(xmlGetProp(reader->node, name)); 2138 2139 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2140 if (ns != NULL) 2141 ret = xmlGetNsProp(reader->node, localname, ns->href); 2142 2143 if (localname != NULL) 2144 xmlFree(localname); 2145 if (prefix != NULL) 2146 xmlFree(prefix); 2147 return(ret); 2148} 2149 2150 2151/** 2152 * xmlTextReaderGetAttributeNs: 2153 * @reader: the xmlTextReaderPtr used 2154 * @localName: the local name of the attribute. 2155 * @namespaceURI: the namespace URI of the attribute. 2156 * 2157 * Provides the value of the specified attribute 2158 * 2159 * Returns a string containing the value of the specified attribute, or NULL 2160 * in case of error. The string must be deallocated by the caller. 2161 */ 2162xmlChar * 2163xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, 2164 const xmlChar *namespaceURI) { 2165 if ((reader == NULL) || (localName == NULL)) 2166 return(NULL); 2167 if (reader->node == NULL) 2168 return(NULL); 2169 if (reader->curnode != NULL) 2170 return(NULL); 2171 2172 /* TODO: handle the xmlDecl */ 2173 if (reader->node->type != XML_ELEMENT_NODE) 2174 return(NULL); 2175 2176 return(xmlGetNsProp(reader->node, localName, namespaceURI)); 2177} 2178 2179/** 2180 * xmlTextReaderGetRemainder: 2181 * @reader: the xmlTextReaderPtr used 2182 * 2183 * Method to get the remainder of the buffered XML. this method stops the 2184 * parser, set its state to End Of File and return the input stream with 2185 * what is left that the parser did not use. 2186 * 2187 * Returns the xmlParserInputBufferPtr attached to the XML or NULL 2188 * in case of error. 2189 */ 2190xmlParserInputBufferPtr 2191xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { 2192 xmlParserInputBufferPtr ret = NULL; 2193 2194 if (reader == NULL) 2195 return(NULL); 2196 if (reader->node == NULL) 2197 return(NULL); 2198 2199 reader->node = NULL; 2200 reader->curnode = NULL; 2201 reader->mode = XML_TEXTREADER_MODE_EOF; 2202 if (reader->ctxt != NULL) { 2203 if (reader->ctxt->myDoc != NULL) { 2204 if (reader->preserve == 0) 2205 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 2206 reader->ctxt->myDoc = NULL; 2207 } 2208 if (reader->allocs & XML_TEXTREADER_CTXT) { 2209 xmlFreeParserCtxt(reader->ctxt); 2210 reader->allocs -= XML_TEXTREADER_CTXT; 2211 } 2212 } 2213 if (reader->sax != NULL) { 2214 xmlFree(reader->sax); 2215 reader->sax = NULL; 2216 } 2217 if (reader->allocs & XML_TEXTREADER_INPUT) { 2218 ret = reader->input; 2219 reader->allocs -= XML_TEXTREADER_INPUT; 2220 } else { 2221 /* 2222 * Hum, one may need to duplicate the data structure because 2223 * without reference counting the input may be freed twice: 2224 * - by the layer which allocated it. 2225 * - by the layer to which would have been returned to. 2226 */ 2227 TODO 2228 return(NULL); 2229 } 2230 return(ret); 2231} 2232 2233/** 2234 * xmlTextReaderLookupNamespace: 2235 * @reader: the xmlTextReaderPtr used 2236 * @prefix: the prefix whose namespace URI is to be resolved. To return 2237 * the default namespace, specify NULL 2238 * 2239 * Resolves a namespace prefix in the scope of the current element. 2240 * 2241 * Returns a string containing the namespace URI to which the prefix maps 2242 * or NULL in case of error. The string must be deallocated by the caller. 2243 */ 2244xmlChar * 2245xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { 2246 xmlNsPtr ns; 2247 2248 if (reader == NULL) 2249 return(NULL); 2250 if (reader->node == NULL) 2251 return(NULL); 2252 2253 ns = xmlSearchNs(reader->node->doc, reader->node, prefix); 2254 if (ns == NULL) 2255 return(NULL); 2256 return(xmlStrdup(ns->href)); 2257} 2258 2259/** 2260 * xmlTextReaderMoveToAttributeNo: 2261 * @reader: the xmlTextReaderPtr used 2262 * @no: the zero-based index of the attribute relative to the containing 2263 * element. 2264 * 2265 * Moves the position of the current instance to the attribute with 2266 * the specified index relative to the containing element. 2267 * 2268 * Returns 1 in case of success, -1 in case of error, 0 if not found 2269 */ 2270int 2271xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { 2272 int i; 2273 xmlAttrPtr cur; 2274 xmlNsPtr ns; 2275 2276 if (reader == NULL) 2277 return(-1); 2278 if (reader->node == NULL) 2279 return(-1); 2280 /* TODO: handle the xmlDecl */ 2281 if (reader->node->type != XML_ELEMENT_NODE) 2282 return(-1); 2283 2284 reader->curnode = NULL; 2285 2286 ns = reader->node->nsDef; 2287 for (i = 0;(i < no) && (ns != NULL);i++) { 2288 ns = ns->next; 2289 } 2290 if (ns != NULL) { 2291 reader->curnode = (xmlNodePtr) ns; 2292 return(1); 2293 } 2294 2295 cur = reader->node->properties; 2296 if (cur == NULL) 2297 return(0); 2298 for (;i < no;i++) { 2299 cur = cur->next; 2300 if (cur == NULL) 2301 return(0); 2302 } 2303 /* TODO walk the DTD if present */ 2304 2305 reader->curnode = (xmlNodePtr) cur; 2306 return(1); 2307} 2308 2309/** 2310 * xmlTextReaderMoveToAttribute: 2311 * @reader: the xmlTextReaderPtr used 2312 * @name: the qualified name of the attribute. 2313 * 2314 * Moves the position of the current instance to the attribute with 2315 * the specified qualified name. 2316 * 2317 * Returns 1 in case of success, -1 in case of error, 0 if not found 2318 */ 2319int 2320xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { 2321 xmlChar *prefix = NULL; 2322 xmlChar *localname; 2323 xmlNsPtr ns; 2324 xmlAttrPtr prop; 2325 2326 if ((reader == NULL) || (name == NULL)) 2327 return(-1); 2328 if (reader->node == NULL) 2329 return(-1); 2330 2331 /* TODO: handle the xmlDecl */ 2332 if (reader->node->type != XML_ELEMENT_NODE) 2333 return(0); 2334 2335 localname = xmlSplitQName2(name, &prefix); 2336 if (localname == NULL) { 2337 /* 2338 * Namespace default decl 2339 */ 2340 if (xmlStrEqual(name, BAD_CAST "xmlns")) { 2341 ns = reader->node->nsDef; 2342 while (ns != NULL) { 2343 if (ns->prefix == NULL) { 2344 reader->curnode = (xmlNodePtr) ns; 2345 return(1); 2346 } 2347 ns = ns->next; 2348 } 2349 return(0); 2350 } 2351 2352 prop = reader->node->properties; 2353 while (prop != NULL) { 2354 /* 2355 * One need to have 2356 * - same attribute names 2357 * - and the attribute carrying that namespace 2358 */ 2359 if ((xmlStrEqual(prop->name, name)) && 2360 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { 2361 reader->curnode = (xmlNodePtr) prop; 2362 return(1); 2363 } 2364 prop = prop->next; 2365 } 2366 return(0); 2367 } 2368 2369 /* 2370 * Namespace default decl 2371 */ 2372 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { 2373 ns = reader->node->nsDef; 2374 while (ns != NULL) { 2375 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { 2376 reader->curnode = (xmlNodePtr) ns; 2377 goto found; 2378 } 2379 ns = ns->next; 2380 } 2381 goto not_found; 2382 } 2383 prop = reader->node->properties; 2384 while (prop != NULL) { 2385 /* 2386 * One need to have 2387 * - same attribute names 2388 * - and the attribute carrying that namespace 2389 */ 2390 if ((xmlStrEqual(prop->name, localname)) && 2391 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) { 2392 reader->curnode = (xmlNodePtr) prop; 2393 goto found; 2394 } 2395 prop = prop->next; 2396 } 2397not_found: 2398 if (localname != NULL) 2399 xmlFree(localname); 2400 if (prefix != NULL) 2401 xmlFree(prefix); 2402 return(0); 2403 2404found: 2405 if (localname != NULL) 2406 xmlFree(localname); 2407 if (prefix != NULL) 2408 xmlFree(prefix); 2409 return(1); 2410} 2411 2412/** 2413 * xmlTextReaderMoveToAttributeNs: 2414 * @reader: the xmlTextReaderPtr used 2415 * @localName: the local name of the attribute. 2416 * @namespaceURI: the namespace URI of the attribute. 2417 * 2418 * Moves the position of the current instance to the attribute with the 2419 * specified local name and namespace URI. 2420 * 2421 * Returns 1 in case of success, -1 in case of error, 0 if not found 2422 */ 2423int 2424xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, 2425 const xmlChar *localName, const xmlChar *namespaceURI) { 2426 xmlAttrPtr prop; 2427 xmlNodePtr node; 2428 2429 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL)) 2430 return(-1); 2431 if (reader->node == NULL) 2432 return(-1); 2433 if (reader->node->type != XML_ELEMENT_NODE) 2434 return(0); 2435 node = reader->node; 2436 2437 /* 2438 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no 2439 * namespace name associated to "xmlns" 2440 */ 2441 prop = node->properties; 2442 while (prop != NULL) { 2443 /* 2444 * One need to have 2445 * - same attribute names 2446 * - and the attribute carrying that namespace 2447 */ 2448 if (xmlStrEqual(prop->name, localName) && 2449 ((prop->ns != NULL) && 2450 (xmlStrEqual(prop->ns->href, namespaceURI)))) { 2451 reader->curnode = (xmlNodePtr) prop; 2452 return(1); 2453 } 2454 prop = prop->next; 2455 } 2456 return(0); 2457} 2458 2459/** 2460 * xmlTextReaderMoveToFirstAttribute: 2461 * @reader: the xmlTextReaderPtr used 2462 * 2463 * Moves the position of the current instance to the first attribute 2464 * associated with the current node. 2465 * 2466 * Returns 1 in case of success, -1 in case of error, 0 if not found 2467 */ 2468int 2469xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) { 2470 if (reader == NULL) 2471 return(-1); 2472 if (reader->node == NULL) 2473 return(-1); 2474 if (reader->node->type != XML_ELEMENT_NODE) 2475 return(0); 2476 2477 if (reader->node->nsDef != NULL) { 2478 reader->curnode = (xmlNodePtr) reader->node->nsDef; 2479 return(1); 2480 } 2481 if (reader->node->properties != NULL) { 2482 reader->curnode = (xmlNodePtr) reader->node->properties; 2483 return(1); 2484 } 2485 return(0); 2486} 2487 2488/** 2489 * xmlTextReaderMoveToNextAttribute: 2490 * @reader: the xmlTextReaderPtr used 2491 * 2492 * Moves the position of the current instance to the next attribute 2493 * associated with the current node. 2494 * 2495 * Returns 1 in case of success, -1 in case of error, 0 if not found 2496 */ 2497int 2498xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) { 2499 if (reader == NULL) 2500 return(-1); 2501 if (reader->node == NULL) 2502 return(-1); 2503 if (reader->node->type != XML_ELEMENT_NODE) 2504 return(0); 2505 if (reader->curnode == NULL) 2506 return(xmlTextReaderMoveToFirstAttribute(reader)); 2507 2508 if (reader->curnode->type == XML_NAMESPACE_DECL) { 2509 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2510 if (ns->next != NULL) { 2511 reader->curnode = (xmlNodePtr) ns->next; 2512 return(1); 2513 } 2514 if (reader->node->properties != NULL) { 2515 reader->curnode = (xmlNodePtr) reader->node->properties; 2516 return(1); 2517 } 2518 return(0); 2519 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) && 2520 (reader->curnode->next != NULL)) { 2521 reader->curnode = reader->curnode->next; 2522 return(1); 2523 } 2524 return(0); 2525} 2526 2527/** 2528 * xmlTextReaderMoveToElement: 2529 * @reader: the xmlTextReaderPtr used 2530 * 2531 * Moves the position of the current instance to the node that 2532 * contains the current Attribute node. 2533 * 2534 * Returns 1 in case of success, -1 in case of error, 0 if not moved 2535 */ 2536int 2537xmlTextReaderMoveToElement(xmlTextReaderPtr reader) { 2538 if (reader == NULL) 2539 return(-1); 2540 if (reader->node == NULL) 2541 return(-1); 2542 if (reader->node->type != XML_ELEMENT_NODE) 2543 return(0); 2544 if (reader->curnode != NULL) { 2545 reader->curnode = NULL; 2546 return(1); 2547 } 2548 return(0); 2549} 2550 2551/** 2552 * xmlTextReaderReadAttributeValue: 2553 * @reader: the xmlTextReaderPtr used 2554 * 2555 * Parses an attribute value into one or more Text and EntityReference nodes. 2556 * 2557 * Returns 1 in case of success, 0 if the reader was not positionned on an 2558 * ttribute node or all the attribute values have been read, or -1 2559 * in case of error. 2560 */ 2561int 2562xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { 2563 if (reader == NULL) 2564 return(-1); 2565 if (reader->node == NULL) 2566 return(-1); 2567 if (reader->curnode == NULL) 2568 return(0); 2569 if (reader->curnode->type == XML_ATTRIBUTE_NODE) { 2570 if (reader->curnode->children == NULL) 2571 return(0); 2572 reader->curnode = reader->curnode->children; 2573 } else if (reader->curnode->type == XML_NAMESPACE_DECL) { 2574 xmlNsPtr ns = (xmlNsPtr) reader->curnode; 2575 2576 if (reader->faketext == NULL) { 2577 reader->faketext = xmlNewDocText(reader->node->doc, 2578 ns->href); 2579 } else { 2580 if (reader->faketext->content != NULL) 2581 xmlFree(reader->faketext->content); 2582 reader->faketext->content = xmlStrdup(ns->href); 2583 } 2584 reader->curnode = reader->faketext; 2585 } else { 2586 if (reader->curnode->next == NULL) 2587 return(0); 2588 reader->curnode = reader->curnode->next; 2589 } 2590 return(1); 2591} 2592 2593/************************************************************************ 2594 * * 2595 * Acces API to the current node * 2596 * * 2597 ************************************************************************/ 2598/** 2599 * xmlTextReaderAttributeCount: 2600 * @reader: the xmlTextReaderPtr used 2601 * 2602 * Provides the number of attributes of the current node 2603 * 2604 * Returns 0 i no attributes, -1 in case of error or the attribute count 2605 */ 2606int 2607xmlTextReaderAttributeCount(xmlTextReaderPtr reader) { 2608 int ret; 2609 xmlAttrPtr attr; 2610 xmlNsPtr ns; 2611 xmlNodePtr node; 2612 2613 if (reader == NULL) 2614 return(-1); 2615 if (reader->node == NULL) 2616 return(0); 2617 2618 if (reader->curnode != NULL) 2619 node = reader->curnode; 2620 else 2621 node = reader->node; 2622 2623 if (node->type != XML_ELEMENT_NODE) 2624 return(0); 2625 if ((reader->state == XML_TEXTREADER_END) || 2626 (reader->state == XML_TEXTREADER_BACKTRACK)) 2627 return(0); 2628 ret = 0; 2629 attr = node->properties; 2630 while (attr != NULL) { 2631 ret++; 2632 attr = attr->next; 2633 } 2634 ns = node->nsDef; 2635 while (ns != NULL) { 2636 ret++; 2637 ns = ns->next; 2638 } 2639 return(ret); 2640} 2641 2642/** 2643 * xmlTextReaderNodeType: 2644 * @reader: the xmlTextReaderPtr used 2645 * 2646 * Get the node type of the current node 2647 * Reference: 2648 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html 2649 * 2650 * Returns the xmlNodeType of the current node or -1 in case of error 2651 */ 2652int 2653xmlTextReaderNodeType(xmlTextReaderPtr reader) { 2654 xmlNodePtr node; 2655 2656 if (reader == NULL) 2657 return(-1); 2658 if (reader->node == NULL) 2659 return(XML_READER_TYPE_NONE); 2660 if (reader->curnode != NULL) 2661 node = reader->curnode; 2662 else 2663 node = reader->node; 2664 switch (node->type) { 2665 case XML_ELEMENT_NODE: 2666 if ((reader->state == XML_TEXTREADER_END) || 2667 (reader->state == XML_TEXTREADER_BACKTRACK)) 2668 return(XML_READER_TYPE_END_ELEMENT); 2669 return(XML_READER_TYPE_ELEMENT); 2670 case XML_NAMESPACE_DECL: 2671 case XML_ATTRIBUTE_NODE: 2672 return(XML_READER_TYPE_ATTRIBUTE); 2673 case XML_TEXT_NODE: 2674 if (xmlIsBlankNode(reader->node)) { 2675 if (xmlNodeGetSpacePreserve(reader->node)) 2676 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE); 2677 else 2678 return(XML_READER_TYPE_WHITESPACE); 2679 } else { 2680 return(XML_READER_TYPE_TEXT); 2681 } 2682 case XML_CDATA_SECTION_NODE: 2683 return(XML_READER_TYPE_CDATA); 2684 case XML_ENTITY_REF_NODE: 2685 return(XML_READER_TYPE_ENTITY_REFERENCE); 2686 case XML_ENTITY_NODE: 2687 return(XML_READER_TYPE_ENTITY); 2688 case XML_PI_NODE: 2689 return(XML_READER_TYPE_PROCESSING_INSTRUCTION); 2690 case XML_COMMENT_NODE: 2691 return(XML_READER_TYPE_COMMENT); 2692 case XML_DOCUMENT_NODE: 2693 case XML_HTML_DOCUMENT_NODE: 2694#ifdef LIBXML_DOCB_ENABLED 2695 case XML_DOCB_DOCUMENT_NODE: 2696#endif 2697 return(XML_READER_TYPE_DOCUMENT); 2698 case XML_DOCUMENT_FRAG_NODE: 2699 return(XML_READER_TYPE_DOCUMENT_FRAGMENT); 2700 case XML_NOTATION_NODE: 2701 return(XML_READER_TYPE_NOTATION); 2702 case XML_DOCUMENT_TYPE_NODE: 2703 case XML_DTD_NODE: 2704 return(XML_READER_TYPE_DOCUMENT_TYPE); 2705 2706 case XML_ELEMENT_DECL: 2707 case XML_ATTRIBUTE_DECL: 2708 case XML_ENTITY_DECL: 2709 case XML_XINCLUDE_START: 2710 case XML_XINCLUDE_END: 2711 return(XML_READER_TYPE_NONE); 2712 } 2713 return(-1); 2714} 2715 2716/** 2717 * xmlTextReaderIsEmptyElement: 2718 * @reader: the xmlTextReaderPtr used 2719 * 2720 * Check if the current node is empty 2721 * 2722 * Returns 1 if empty, 0 if not and -1 in case of error 2723 */ 2724int 2725xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) { 2726 if ((reader == NULL) || (reader->node == NULL)) 2727 return(-1); 2728 if (reader->node->type != XML_ELEMENT_NODE) 2729 return(0); 2730 if (reader->curnode != NULL) 2731 return(0); 2732 if (reader->node->children != NULL) 2733 return(0); 2734 if (reader->state == XML_TEXTREADER_END) 2735 return(0); 2736 if (reader->doc != NULL) 2737 return(1); 2738 if (reader->in_xinclude > 0) 2739 return(1); 2740 return((reader->node->extra & NODE_IS_EMPTY) != 0); 2741} 2742 2743/** 2744 * xmlTextReaderLocalName: 2745 * @reader: the xmlTextReaderPtr used 2746 * 2747 * The local name of the node. 2748 * 2749 * Returns the local name or NULL if not available 2750 */ 2751xmlChar * 2752xmlTextReaderLocalName(xmlTextReaderPtr reader) { 2753 xmlNodePtr node; 2754 if ((reader == NULL) || (reader->node == NULL)) 2755 return(NULL); 2756 if (reader->curnode != NULL) 2757 node = reader->curnode; 2758 else 2759 node = reader->node; 2760 if (node->type == XML_NAMESPACE_DECL) { 2761 xmlNsPtr ns = (xmlNsPtr) node; 2762 if (ns->prefix == NULL) 2763 return(xmlStrdup(BAD_CAST "xmlns")); 2764 else 2765 return(xmlStrdup(ns->prefix)); 2766 } 2767 if ((node->type != XML_ELEMENT_NODE) && 2768 (node->type != XML_ATTRIBUTE_NODE)) 2769 return(xmlTextReaderName(reader)); 2770 return(xmlStrdup(node->name)); 2771} 2772 2773/** 2774 * xmlTextReaderConstLocalName: 2775 * @reader: the xmlTextReaderPtr used 2776 * 2777 * The local name of the node. 2778 * 2779 * Returns the local name or NULL if not available, the 2780 * string will be deallocated with the reader. 2781 */ 2782const xmlChar * 2783xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { 2784 xmlNodePtr node; 2785 if ((reader == NULL) || (reader->node == NULL)) 2786 return(NULL); 2787 if (reader->curnode != NULL) 2788 node = reader->curnode; 2789 else 2790 node = reader->node; 2791 if (node->type == XML_NAMESPACE_DECL) { 2792 xmlNsPtr ns = (xmlNsPtr) node; 2793 if (ns->prefix == NULL) 2794 return(CONSTSTR(BAD_CAST "xmlns")); 2795 else 2796 return(ns->prefix); 2797 } 2798 if ((node->type != XML_ELEMENT_NODE) && 2799 (node->type != XML_ATTRIBUTE_NODE)) 2800 return(xmlTextReaderConstName(reader)); 2801 return(node->name); 2802} 2803 2804/** 2805 * xmlTextReaderName: 2806 * @reader: the xmlTextReaderPtr used 2807 * 2808 * The qualified name of the node, equal to Prefix :LocalName. 2809 * 2810 * Returns the local name or NULL if not available 2811 */ 2812xmlChar * 2813xmlTextReaderName(xmlTextReaderPtr reader) { 2814 xmlNodePtr node; 2815 xmlChar *ret; 2816 2817 if ((reader == NULL) || (reader->node == NULL)) 2818 return(NULL); 2819 if (reader->curnode != NULL) 2820 node = reader->curnode; 2821 else 2822 node = reader->node; 2823 switch (node->type) { 2824 case XML_ELEMENT_NODE: 2825 case XML_ATTRIBUTE_NODE: 2826 if ((node->ns == NULL) || 2827 (node->ns->prefix == NULL)) 2828 return(xmlStrdup(node->name)); 2829 2830 ret = xmlStrdup(node->ns->prefix); 2831 ret = xmlStrcat(ret, BAD_CAST ":"); 2832 ret = xmlStrcat(ret, node->name); 2833 return(ret); 2834 case XML_TEXT_NODE: 2835 return(xmlStrdup(BAD_CAST "#text")); 2836 case XML_CDATA_SECTION_NODE: 2837 return(xmlStrdup(BAD_CAST "#cdata-section")); 2838 case XML_ENTITY_NODE: 2839 case XML_ENTITY_REF_NODE: 2840 return(xmlStrdup(node->name)); 2841 case XML_PI_NODE: 2842 return(xmlStrdup(node->name)); 2843 case XML_COMMENT_NODE: 2844 return(xmlStrdup(BAD_CAST "#comment")); 2845 case XML_DOCUMENT_NODE: 2846 case XML_HTML_DOCUMENT_NODE: 2847#ifdef LIBXML_DOCB_ENABLED 2848 case XML_DOCB_DOCUMENT_NODE: 2849#endif 2850 return(xmlStrdup(BAD_CAST "#document")); 2851 case XML_DOCUMENT_FRAG_NODE: 2852 return(xmlStrdup(BAD_CAST "#document-fragment")); 2853 case XML_NOTATION_NODE: 2854 return(xmlStrdup(node->name)); 2855 case XML_DOCUMENT_TYPE_NODE: 2856 case XML_DTD_NODE: 2857 return(xmlStrdup(node->name)); 2858 case XML_NAMESPACE_DECL: { 2859 xmlNsPtr ns = (xmlNsPtr) node; 2860 2861 ret = xmlStrdup(BAD_CAST "xmlns"); 2862 if (ns->prefix == NULL) 2863 return(ret); 2864 ret = xmlStrcat(ret, BAD_CAST ":"); 2865 ret = xmlStrcat(ret, ns->prefix); 2866 return(ret); 2867 } 2868 2869 case XML_ELEMENT_DECL: 2870 case XML_ATTRIBUTE_DECL: 2871 case XML_ENTITY_DECL: 2872 case XML_XINCLUDE_START: 2873 case XML_XINCLUDE_END: 2874 return(NULL); 2875 } 2876 return(NULL); 2877} 2878 2879/** 2880 * xmlTextReaderConstName: 2881 * @reader: the xmlTextReaderPtr used 2882 * 2883 * The qualified name of the node, equal to Prefix :LocalName. 2884 * 2885 * Returns the local name or NULL if not available, the string is 2886 * deallocated with the reader. 2887 */ 2888const xmlChar * 2889xmlTextReaderConstName(xmlTextReaderPtr reader) { 2890 xmlNodePtr node; 2891 2892 if ((reader == NULL) || (reader->node == NULL)) 2893 return(NULL); 2894 if (reader->curnode != NULL) 2895 node = reader->curnode; 2896 else 2897 node = reader->node; 2898 switch (node->type) { 2899 case XML_ELEMENT_NODE: 2900 case XML_ATTRIBUTE_NODE: 2901 if ((node->ns == NULL) || 2902 (node->ns->prefix == NULL)) 2903 return(node->name); 2904 return(CONSTQSTR(node->ns->prefix, node->name)); 2905 case XML_TEXT_NODE: 2906 return(CONSTSTR(BAD_CAST "#text")); 2907 case XML_CDATA_SECTION_NODE: 2908 return(CONSTSTR(BAD_CAST "#cdata-section")); 2909 case XML_ENTITY_NODE: 2910 case XML_ENTITY_REF_NODE: 2911 return(CONSTSTR(node->name)); 2912 case XML_PI_NODE: 2913 return(CONSTSTR(node->name)); 2914 case XML_COMMENT_NODE: 2915 return(CONSTSTR(BAD_CAST "#comment")); 2916 case XML_DOCUMENT_NODE: 2917 case XML_HTML_DOCUMENT_NODE: 2918#ifdef LIBXML_DOCB_ENABLED 2919 case XML_DOCB_DOCUMENT_NODE: 2920#endif 2921 return(CONSTSTR(BAD_CAST "#document")); 2922 case XML_DOCUMENT_FRAG_NODE: 2923 return(CONSTSTR(BAD_CAST "#document-fragment")); 2924 case XML_NOTATION_NODE: 2925 return(CONSTSTR(node->name)); 2926 case XML_DOCUMENT_TYPE_NODE: 2927 case XML_DTD_NODE: 2928 return(CONSTSTR(node->name)); 2929 case XML_NAMESPACE_DECL: { 2930 xmlNsPtr ns = (xmlNsPtr) node; 2931 2932 if (ns->prefix == NULL) 2933 return(CONSTSTR(BAD_CAST "xmlns")); 2934 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); 2935 } 2936 2937 case XML_ELEMENT_DECL: 2938 case XML_ATTRIBUTE_DECL: 2939 case XML_ENTITY_DECL: 2940 case XML_XINCLUDE_START: 2941 case XML_XINCLUDE_END: 2942 return(NULL); 2943 } 2944 return(NULL); 2945} 2946 2947/** 2948 * xmlTextReaderPrefix: 2949 * @reader: the xmlTextReaderPtr used 2950 * 2951 * A shorthand reference to the namespace associated with the node. 2952 * 2953 * Returns the prefix or NULL if not available 2954 */ 2955xmlChar * 2956xmlTextReaderPrefix(xmlTextReaderPtr reader) { 2957 xmlNodePtr node; 2958 if ((reader == NULL) || (reader->node == NULL)) 2959 return(NULL); 2960 if (reader->curnode != NULL) 2961 node = reader->curnode; 2962 else 2963 node = reader->node; 2964 if (node->type == XML_NAMESPACE_DECL) { 2965 xmlNsPtr ns = (xmlNsPtr) node; 2966 if (ns->prefix == NULL) 2967 return(NULL); 2968 return(xmlStrdup(BAD_CAST "xmlns")); 2969 } 2970 if ((node->type != XML_ELEMENT_NODE) && 2971 (node->type != XML_ATTRIBUTE_NODE)) 2972 return(NULL); 2973 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 2974 return(xmlStrdup(node->ns->prefix)); 2975 return(NULL); 2976} 2977 2978/** 2979 * xmlTextReaderConstPrefix: 2980 * @reader: the xmlTextReaderPtr used 2981 * 2982 * A shorthand reference to the namespace associated with the node. 2983 * 2984 * Returns the prefix or NULL if not available, the string is deallocated 2985 * with the reader. 2986 */ 2987const xmlChar * 2988xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { 2989 xmlNodePtr node; 2990 if ((reader == NULL) || (reader->node == NULL)) 2991 return(NULL); 2992 if (reader->curnode != NULL) 2993 node = reader->curnode; 2994 else 2995 node = reader->node; 2996 if (node->type == XML_NAMESPACE_DECL) { 2997 xmlNsPtr ns = (xmlNsPtr) node; 2998 if (ns->prefix == NULL) 2999 return(NULL); 3000 return(CONSTSTR(BAD_CAST "xmlns")); 3001 } 3002 if ((node->type != XML_ELEMENT_NODE) && 3003 (node->type != XML_ATTRIBUTE_NODE)) 3004 return(NULL); 3005 if ((node->ns != NULL) && (node->ns->prefix != NULL)) 3006 return(CONSTSTR(node->ns->prefix)); 3007 return(NULL); 3008} 3009 3010/** 3011 * xmlTextReaderNamespaceUri: 3012 * @reader: the xmlTextReaderPtr used 3013 * 3014 * The URI defining the namespace associated with the node. 3015 * 3016 * Returns the namespace URI or NULL if not available 3017 */ 3018xmlChar * 3019xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { 3020 xmlNodePtr node; 3021 if ((reader == NULL) || (reader->node == NULL)) 3022 return(NULL); 3023 if (reader->curnode != NULL) 3024 node = reader->curnode; 3025 else 3026 node = reader->node; 3027 if (node->type == XML_NAMESPACE_DECL) 3028 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3029 if ((node->type != XML_ELEMENT_NODE) && 3030 (node->type != XML_ATTRIBUTE_NODE)) 3031 return(NULL); 3032 if (node->ns != NULL) 3033 return(xmlStrdup(node->ns->href)); 3034 return(NULL); 3035} 3036 3037/** 3038 * xmlTextReaderConstNamespaceUri: 3039 * @reader: the xmlTextReaderPtr used 3040 * 3041 * The URI defining the namespace associated with the node. 3042 * 3043 * Returns the namespace URI or NULL if not available, the string 3044 * will be deallocated with the reader 3045 */ 3046const xmlChar * 3047xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { 3048 xmlNodePtr node; 3049 if ((reader == NULL) || (reader->node == NULL)) 3050 return(NULL); 3051 if (reader->curnode != NULL) 3052 node = reader->curnode; 3053 else 3054 node = reader->node; 3055 if (node->type == XML_NAMESPACE_DECL) 3056 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); 3057 if ((node->type != XML_ELEMENT_NODE) && 3058 (node->type != XML_ATTRIBUTE_NODE)) 3059 return(NULL); 3060 if (node->ns != NULL) 3061 return(CONSTSTR(node->ns->href)); 3062 return(NULL); 3063} 3064 3065/** 3066 * xmlTextReaderBaseUri: 3067 * @reader: the xmlTextReaderPtr used 3068 * 3069 * The base URI of the node. 3070 * 3071 * Returns the base URI or NULL if not available 3072 */ 3073xmlChar * 3074xmlTextReaderBaseUri(xmlTextReaderPtr reader) { 3075 if ((reader == NULL) || (reader->node == NULL)) 3076 return(NULL); 3077 return(xmlNodeGetBase(NULL, reader->node)); 3078} 3079 3080/** 3081 * xmlTextReaderConstBaseUri: 3082 * @reader: the xmlTextReaderPtr used 3083 * 3084 * The base URI of the node. 3085 * 3086 * Returns the base URI or NULL if not available, the string 3087 * will be deallocated with the reader 3088 */ 3089const xmlChar * 3090xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { 3091 xmlChar *tmp; 3092 const xmlChar *ret; 3093 3094 if ((reader == NULL) || (reader->node == NULL)) 3095 return(NULL); 3096 tmp = xmlNodeGetBase(NULL, reader->node); 3097 if (tmp == NULL) 3098 return(NULL); 3099 ret = CONSTSTR(tmp); 3100 xmlFree(tmp); 3101 return(ret); 3102} 3103 3104/** 3105 * xmlTextReaderDepth: 3106 * @reader: the xmlTextReaderPtr used 3107 * 3108 * The depth of the node in the tree. 3109 * 3110 * Returns the depth or -1 in case of error 3111 */ 3112int 3113xmlTextReaderDepth(xmlTextReaderPtr reader) { 3114 if (reader == NULL) 3115 return(-1); 3116 if (reader->node == NULL) 3117 return(0); 3118 3119 if (reader->curnode != NULL) { 3120 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) || 3121 (reader->curnode->type == XML_NAMESPACE_DECL)) 3122 return(reader->depth + 1); 3123 return(reader->depth + 2); 3124 } 3125 return(reader->depth); 3126} 3127 3128/** 3129 * xmlTextReaderHasAttributes: 3130 * @reader: the xmlTextReaderPtr used 3131 * 3132 * Whether the node has attributes. 3133 * 3134 * Returns 1 if true, 0 if false, and -1 in case or error 3135 */ 3136int 3137xmlTextReaderHasAttributes(xmlTextReaderPtr reader) { 3138 xmlNodePtr node; 3139 if (reader == NULL) 3140 return(-1); 3141 if (reader->node == NULL) 3142 return(0); 3143 if (reader->curnode != NULL) 3144 node = reader->curnode; 3145 else 3146 node = reader->node; 3147 3148 if ((node->type == XML_ELEMENT_NODE) && 3149 (node->properties != NULL)) 3150 return(1); 3151 /* TODO: handle the xmlDecl */ 3152 return(0); 3153} 3154 3155/** 3156 * xmlTextReaderHasValue: 3157 * @reader: the xmlTextReaderPtr used 3158 * 3159 * Whether the node can have a text value. 3160 * 3161 * Returns 1 if true, 0 if false, and -1 in case or error 3162 */ 3163int 3164xmlTextReaderHasValue(xmlTextReaderPtr reader) { 3165 xmlNodePtr node; 3166 if (reader == NULL) 3167 return(-1); 3168 if (reader->node == NULL) 3169 return(0); 3170 if (reader->curnode != NULL) 3171 node = reader->curnode; 3172 else 3173 node = reader->node; 3174 3175 switch (node->type) { 3176 case XML_ATTRIBUTE_NODE: 3177 case XML_TEXT_NODE: 3178 case XML_CDATA_SECTION_NODE: 3179 case XML_PI_NODE: 3180 case XML_COMMENT_NODE: 3181 case XML_NAMESPACE_DECL: 3182 return(1); 3183 default: 3184 break; 3185 } 3186 return(0); 3187} 3188 3189/** 3190 * xmlTextReaderValue: 3191 * @reader: the xmlTextReaderPtr used 3192 * 3193 * Provides the text value of the node if present 3194 * 3195 * Returns the string or NULL if not available. The result must be deallocated 3196 * with xmlFree() 3197 */ 3198xmlChar * 3199xmlTextReaderValue(xmlTextReaderPtr reader) { 3200 xmlNodePtr node; 3201 if (reader == NULL) 3202 return(NULL); 3203 if (reader->node == NULL) 3204 return(NULL); 3205 if (reader->curnode != NULL) 3206 node = reader->curnode; 3207 else 3208 node = reader->node; 3209 3210 switch (node->type) { 3211 case XML_NAMESPACE_DECL: 3212 return(xmlStrdup(((xmlNsPtr) node)->href)); 3213 case XML_ATTRIBUTE_NODE:{ 3214 xmlAttrPtr attr = (xmlAttrPtr) node; 3215 3216 if (attr->parent != NULL) 3217 return (xmlNodeListGetString 3218 (attr->parent->doc, attr->children, 1)); 3219 else 3220 return (xmlNodeListGetString(NULL, attr->children, 1)); 3221 break; 3222 } 3223 case XML_TEXT_NODE: 3224 case XML_CDATA_SECTION_NODE: 3225 case XML_PI_NODE: 3226 case XML_COMMENT_NODE: 3227 if (node->content != NULL) 3228 return (xmlStrdup(node->content)); 3229 default: 3230 break; 3231 } 3232 return(NULL); 3233} 3234 3235/** 3236 * xmlTextReaderConstValue: 3237 * @reader: the xmlTextReaderPtr used 3238 * 3239 * Provides the text value of the node if present 3240 * 3241 * Returns the string or NULL if not available. The result will be 3242 * deallocated on the next Read() operation. 3243 */ 3244const xmlChar * 3245xmlTextReaderConstValue(xmlTextReaderPtr reader) { 3246 xmlNodePtr node; 3247 if (reader == NULL) 3248 return(NULL); 3249 if (reader->node == NULL) 3250 return(NULL); 3251 if (reader->curnode != NULL) 3252 node = reader->curnode; 3253 else 3254 node = reader->node; 3255 3256 switch (node->type) { 3257 case XML_NAMESPACE_DECL: 3258 return(((xmlNsPtr) node)->href); 3259 case XML_ATTRIBUTE_NODE:{ 3260 xmlAttrPtr attr = (xmlAttrPtr) node; 3261 3262 if ((attr->children != NULL) && 3263 (attr->children->type == XML_TEXT_NODE) && 3264 (attr->children->next == NULL)) 3265 return(attr->children->content); 3266 else { 3267 reader->buffer->use = 0; 3268 xmlNodeBufGetContent(reader->buffer, node); 3269 return(reader->buffer->content); 3270 } 3271 break; 3272 } 3273 case XML_TEXT_NODE: 3274 case XML_CDATA_SECTION_NODE: 3275 case XML_PI_NODE: 3276 case XML_COMMENT_NODE: 3277 return(node->content); 3278 default: 3279 break; 3280 } 3281 return(NULL); 3282} 3283 3284/** 3285 * xmlTextReaderIsDefault: 3286 * @reader: the xmlTextReaderPtr used 3287 * 3288 * Whether an Attribute node was generated from the default value 3289 * defined in the DTD or schema. 3290 * 3291 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error 3292 */ 3293int 3294xmlTextReaderIsDefault(xmlTextReaderPtr reader) { 3295 if (reader == NULL) 3296 return(-1); 3297 return(0); 3298} 3299 3300/** 3301 * xmlTextReaderQuoteChar: 3302 * @reader: the xmlTextReaderPtr used 3303 * 3304 * The quotation mark character used to enclose the value of an attribute. 3305 * 3306 * Returns " or ' and -1 in case of error 3307 */ 3308int 3309xmlTextReaderQuoteChar(xmlTextReaderPtr reader) { 3310 if (reader == NULL) 3311 return(-1); 3312 /* TODO maybe lookup the attribute value for " first */ 3313 return((int) '"'); 3314} 3315 3316/** 3317 * xmlTextReaderXmlLang: 3318 * @reader: the xmlTextReaderPtr used 3319 * 3320 * The xml:lang scope within which the node resides. 3321 * 3322 * Returns the xml:lang value or NULL if none exists. 3323 */ 3324xmlChar * 3325xmlTextReaderXmlLang(xmlTextReaderPtr reader) { 3326 if (reader == NULL) 3327 return(NULL); 3328 if (reader->node == NULL) 3329 return(NULL); 3330 return(xmlNodeGetLang(reader->node)); 3331} 3332 3333/** 3334 * xmlTextReaderConstXmlLang: 3335 * @reader: the xmlTextReaderPtr used 3336 * 3337 * The xml:lang scope within which the node resides. 3338 * 3339 * Returns the xml:lang value or NULL if none exists. 3340 */ 3341const xmlChar * 3342xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { 3343 xmlChar *tmp; 3344 const xmlChar *ret; 3345 3346 if (reader == NULL) 3347 return(NULL); 3348 if (reader->node == NULL) 3349 return(NULL); 3350 tmp = xmlNodeGetLang(reader->node); 3351 if (tmp == NULL) 3352 return(NULL); 3353 ret = CONSTSTR(tmp); 3354 xmlFree(tmp); 3355 return(ret); 3356} 3357 3358/** 3359 * xmlTextReaderConstString: 3360 * @reader: the xmlTextReaderPtr used 3361 * @str: the string to intern. 3362 * 3363 * Get an interned string from the reader, allows for example to 3364 * speedup string name comparisons 3365 * 3366 * Returns an interned copy of the string or NULL in case of error. The 3367 * string will be deallocated with the reader. 3368 */ 3369const xmlChar * 3370xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { 3371 if (reader == NULL) 3372 return(NULL); 3373 return(CONSTSTR(str)); 3374} 3375 3376/** 3377 * xmlTextReaderNormalization: 3378 * @reader: the xmlTextReaderPtr used 3379 * 3380 * The value indicating whether to normalize white space and attribute values. 3381 * Since attribute value and end of line normalizations are a MUST in the XML 3382 * specification only the value true is accepted. The broken bahaviour of 3383 * accepting out of range character entities like � is of course not 3384 * supported either. 3385 * 3386 * Returns 1 or -1 in case of error. 3387 */ 3388int 3389xmlTextReaderNormalization(xmlTextReaderPtr reader) { 3390 if (reader == NULL) 3391 return(-1); 3392 return(1); 3393} 3394 3395/************************************************************************ 3396 * * 3397 * Extensions to the base APIs * 3398 * * 3399 ************************************************************************/ 3400 3401/** 3402 * xmlTextReaderSetParserProp: 3403 * @reader: the xmlTextReaderPtr used 3404 * @prop: the xmlParserProperties to set 3405 * @value: usually 0 or 1 to (de)activate it 3406 * 3407 * Change the parser processing behaviour by changing some of its internal 3408 * properties. Note that some properties can only be changed before any 3409 * read has been done. 3410 * 3411 * Returns 0 if the call was successful, or -1 in case of error 3412 */ 3413int 3414xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { 3415 xmlParserProperties p = (xmlParserProperties) prop; 3416 xmlParserCtxtPtr ctxt; 3417 3418 if ((reader == NULL) || (reader->ctxt == NULL)) 3419 return(-1); 3420 ctxt = reader->ctxt; 3421 3422 switch (p) { 3423 case XML_PARSER_LOADDTD: 3424 if (value != 0) { 3425 if (ctxt->loadsubset == 0) { 3426 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 3427 return(-1); 3428 ctxt->loadsubset = XML_DETECT_IDS; 3429 } 3430 } else { 3431 ctxt->loadsubset = 0; 3432 } 3433 return(0); 3434 case XML_PARSER_DEFAULTATTRS: 3435 if (value != 0) { 3436 ctxt->loadsubset |= XML_COMPLETE_ATTRS; 3437 } else { 3438 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3439 ctxt->loadsubset -= XML_COMPLETE_ATTRS; 3440 } 3441 return(0); 3442 case XML_PARSER_VALIDATE: 3443 if (value != 0) { 3444 ctxt->validate = 1; 3445 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 3446 } else { 3447 ctxt->validate = 0; 3448 } 3449 return(0); 3450 case XML_PARSER_SUBST_ENTITIES: 3451 if (value != 0) { 3452 ctxt->replaceEntities = 1; 3453 } else { 3454 ctxt->replaceEntities = 0; 3455 } 3456 return(0); 3457 } 3458 return(-1); 3459} 3460 3461/** 3462 * xmlTextReaderGetParserProp: 3463 * @reader: the xmlTextReaderPtr used 3464 * @prop: the xmlParserProperties to get 3465 * 3466 * Read the parser internal property. 3467 * 3468 * Returns the value, usually 0 or 1, or -1 in case of error. 3469 */ 3470int 3471xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) { 3472 xmlParserProperties p = (xmlParserProperties) prop; 3473 xmlParserCtxtPtr ctxt; 3474 3475 if ((reader == NULL) || (reader->ctxt == NULL)) 3476 return(-1); 3477 ctxt = reader->ctxt; 3478 3479 switch (p) { 3480 case XML_PARSER_LOADDTD: 3481 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0)) 3482 return(1); 3483 return(0); 3484 case XML_PARSER_DEFAULTATTRS: 3485 if (ctxt->loadsubset & XML_COMPLETE_ATTRS) 3486 return(1); 3487 return(0); 3488 case XML_PARSER_VALIDATE: 3489 return(reader->validate); 3490 case XML_PARSER_SUBST_ENTITIES: 3491 return(ctxt->replaceEntities); 3492 } 3493 return(-1); 3494} 3495 3496/** 3497 * xmlTextReaderCurrentNode: 3498 * @reader: the xmlTextReaderPtr used 3499 * 3500 * Hacking interface allowing to get the xmlNodePtr correponding to the 3501 * current node being accessed by the xmlTextReader. This is dangerous 3502 * because the underlying node may be destroyed on the next Reads. 3503 * 3504 * Returns the xmlNodePtr or NULL in case of error. 3505 */ 3506xmlNodePtr 3507xmlTextReaderCurrentNode(xmlTextReaderPtr reader) { 3508 if (reader == NULL) 3509 return(NULL); 3510 3511 if (reader->curnode != NULL) 3512 return(reader->curnode); 3513 return(reader->node); 3514} 3515 3516/** 3517 * xmlTextReaderPreserve: 3518 * @reader: the xmlTextReaderPtr used 3519 * 3520 * 3521 * current node being accessed by the xmlTextReader. This is dangerous 3522 * because the underlying node may be destroyed on the next Reads. 3523 * 3524 * Returns the xmlNodePtr or NULL in case of error. 3525 */ 3526xmlNodePtr 3527xmlTextReaderPreserve(xmlTextReaderPtr reader) { 3528 xmlNodePtr cur, parent; 3529 3530 if (reader == NULL) 3531 return(NULL); 3532 3533 if (reader->curnode != NULL) 3534 cur = reader->curnode; 3535 else 3536 cur = reader->node; 3537 if (cur == NULL) 3538 return(NULL); 3539 3540 if (cur->type != XML_DOCUMENT_NODE) { 3541 cur->extra |= NODE_IS_PRESERVED; 3542 cur->extra |= NODE_IS_SPRESERVED; 3543 } 3544 reader->preserves++; 3545 3546 parent = cur->parent;; 3547 while (parent != NULL) { 3548 if (parent->type == XML_ELEMENT_NODE) 3549 parent->extra |= NODE_IS_PRESERVED; 3550 parent = parent->parent; 3551 } 3552 return(cur); 3553} 3554 3555#ifdef LIBXML_PATTERN_ENABLED 3556/** 3557 * xmlTextReaderPreservePattern: 3558 * @reader: the xmlTextReaderPtr used 3559 * @pattern: an XPath subset pattern 3560 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL 3561 * 3562 * This tells the XML Reader to preserve all nodes matched by the 3563 * pattern. The caller must also use xmlTextReaderCurrentDoc() to 3564 * keep an handle on the resulting document once parsing has finished 3565 * 3566 * Returns a positive number in case of success and -1 in case of error 3567 */ 3568int 3569xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, 3570 const xmlChar **namespaces) 3571{ 3572 xmlPatternPtr comp; 3573 3574 if ((reader == NULL) || (pattern == NULL)) 3575 return(-1); 3576 3577 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces); 3578 if (comp == NULL) 3579 return(-1); 3580 3581 if (reader->patternMax <= 0) { 3582 reader->patternMax = 4; 3583 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * 3584 sizeof(reader->patternTab[0])); 3585 if (reader->patternTab == NULL) { 3586 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 3587 return (-1); 3588 } 3589 } 3590 if (reader->patternNr >= reader->patternMax) { 3591 xmlPatternPtr *tmp; 3592 reader->patternMax *= 2; 3593 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab, 3594 reader->patternMax * 3595 sizeof(reader->patternTab[0])); 3596 if (tmp == NULL) { 3597 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 3598 reader->patternMax /= 2; 3599 return (-1); 3600 } 3601 reader->patternTab = tmp; 3602 } 3603 reader->patternTab[reader->patternNr] = comp; 3604 return(reader->patternNr++); 3605} 3606#endif 3607 3608/** 3609 * xmlTextReaderCurrentDoc: 3610 * @reader: the xmlTextReaderPtr used 3611 * 3612 * Hacking interface allowing to get the xmlDocPtr correponding to the 3613 * current document being accessed by the xmlTextReader. 3614 * NOTE: as a result of this call, the reader will not destroy the 3615 * associated XML document and calling xmlFreeDoc() on the result 3616 * is needed once the reader parsing has finished. 3617 * 3618 * Returns the xmlDocPtr or NULL in case of error. 3619 */ 3620xmlDocPtr 3621xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { 3622 if (reader == NULL) 3623 return(NULL); 3624 if (reader->doc != NULL) 3625 return(reader->doc); 3626 if ((reader == NULL) || (reader->ctxt == NULL) || 3627 (reader->ctxt->myDoc == NULL)) 3628 return(NULL); 3629 3630 reader->preserve = 1; 3631 if ((reader->ctxt->myDoc->dict != NULL) && 3632 (reader->ctxt->myDoc->dict == reader->ctxt->dict)) 3633 xmlDictReference(reader->ctxt->dict); 3634 return(reader->ctxt->myDoc); 3635} 3636 3637#ifdef LIBXML_SCHEMAS_ENABLED 3638/** 3639 * xmlTextReaderRelaxNGSetSchema: 3640 * @reader: the xmlTextReaderPtr used 3641 * @schema: a precompiled RelaxNG schema 3642 * 3643 * Use RelaxNG to validate the document as it is processed. 3644 * Activation is only possible before the first Read(). 3645 * if @schema is NULL, then RelaxNG validation is desactivated. 3646 @ The @schema should not be freed until the reader is deallocated 3647 * or its use has been deactivated. 3648 * 3649 * Returns 0 in case the RelaxNG validation could be (des)activated and 3650 * -1 in case of error. 3651 */ 3652int 3653xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { 3654 if (schema == NULL) { 3655 if (reader->rngSchemas != NULL) { 3656 xmlRelaxNGFree(reader->rngSchemas); 3657 reader->rngSchemas = NULL; 3658 } 3659 if (reader->rngValidCtxt != NULL) { 3660 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 3661 reader->rngValidCtxt = NULL; 3662 } 3663 return(0); 3664 } 3665 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 3666 return(-1); 3667 if (reader->rngSchemas != NULL) { 3668 xmlRelaxNGFree(reader->rngSchemas); 3669 reader->rngSchemas = NULL; 3670 } 3671 if (reader->rngValidCtxt != NULL) { 3672 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 3673 reader->rngValidCtxt = NULL; 3674 } 3675 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); 3676 if (reader->rngValidCtxt == NULL) 3677 return(-1); 3678 if (reader->errorFunc != NULL) { 3679 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 3680 (xmlRelaxNGValidityErrorFunc)reader->errorFunc, 3681 (xmlRelaxNGValidityWarningFunc) reader->errorFunc, 3682 reader->errorFuncArg); 3683 } 3684 reader->rngValidErrors = 0; 3685 reader->rngFullNode = NULL; 3686 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 3687 return(0); 3688} 3689 3690/** 3691 * xmlTextReaderRelaxNGValidate: 3692 * @reader: the xmlTextReaderPtr used 3693 * @rng: the path to a RelaxNG schema or NULL 3694 * 3695 * Use RelaxNG to validate the document as it is processed. 3696 * Activation is only possible before the first Read(). 3697 * if @rng is NULL, then RelaxNG validation is desactivated. 3698 * 3699 * Returns 0 in case the RelaxNG validation could be (des)activated and 3700 * -1 in case of error. 3701 */ 3702int 3703xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) { 3704 xmlRelaxNGParserCtxtPtr ctxt; 3705 3706 if (reader == NULL) 3707 return(-1); 3708 3709 if (rng == NULL) { 3710 if (reader->rngSchemas != NULL) { 3711 xmlRelaxNGFree(reader->rngSchemas); 3712 reader->rngSchemas = NULL; 3713 } 3714 if (reader->rngValidCtxt != NULL) { 3715 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 3716 reader->rngValidCtxt = NULL; 3717 } 3718 return(0); 3719 } 3720 if (reader->mode != XML_TEXTREADER_MODE_INITIAL) 3721 return(-1); 3722 if (reader->rngSchemas != NULL) { 3723 xmlRelaxNGFree(reader->rngSchemas); 3724 reader->rngSchemas = NULL; 3725 } 3726 if (reader->rngValidCtxt != NULL) { 3727 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); 3728 reader->rngValidCtxt = NULL; 3729 } 3730 ctxt = xmlRelaxNGNewParserCtxt(rng); 3731 if (reader->errorFunc != NULL) { 3732 xmlRelaxNGSetParserErrors(ctxt, 3733 (xmlRelaxNGValidityErrorFunc) reader->errorFunc, 3734 (xmlRelaxNGValidityWarningFunc) reader->errorFunc, 3735 reader->errorFuncArg); 3736 } 3737 reader->rngSchemas = xmlRelaxNGParse(ctxt); 3738 xmlRelaxNGFreeParserCtxt(ctxt); 3739 if (reader->rngSchemas == NULL) 3740 return(-1); 3741 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); 3742 if (reader->rngValidCtxt == NULL) 3743 return(-1); 3744 if (reader->errorFunc != NULL) { 3745 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, 3746 (xmlRelaxNGValidityErrorFunc)reader->errorFunc, 3747 (xmlRelaxNGValidityWarningFunc) reader->errorFunc, 3748 reader->errorFuncArg); 3749 } 3750 reader->rngValidErrors = 0; 3751 reader->rngFullNode = NULL; 3752 reader->validate = XML_TEXTREADER_VALIDATE_RNG; 3753 return(0); 3754} 3755#endif 3756 3757/************************************************************************ 3758 * * 3759 * Error Handling Extensions * 3760 * * 3761 ************************************************************************/ 3762 3763/* helper to build a xmlMalloc'ed string from a format and va_list */ 3764static char * 3765xmlTextReaderBuildMessage(const char *msg, va_list ap) { 3766 int size; 3767 int chars; 3768 char *larger; 3769 char *str; 3770 3771 str = (char *) xmlMallocAtomic(150); 3772 if (str == NULL) { 3773 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); 3774 return NULL; 3775 } 3776 3777 size = 150; 3778 3779 while (1) { 3780 chars = vsnprintf(str, size, msg, ap); 3781 if ((chars > -1) && (chars < size)) 3782 break; 3783 if (chars > -1) 3784 size += chars + 1; 3785 else 3786 size += 100; 3787 if ((larger = (char *) xmlRealloc(str, size)) == NULL) { 3788 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); 3789 xmlFree(str); 3790 return NULL; 3791 } 3792 str = larger; 3793 } 3794 3795 return str; 3796} 3797 3798/** 3799 * xmlTextReaderLocatorLineNumber: 3800 * @locator: the xmlTextReaderLocatorPtr used 3801 * 3802 * Obtain the line number for the given locator. 3803 * 3804 * Returns the line number or -1 in case of error. 3805 */ 3806int 3807xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) { 3808 /* we know that locator is a xmlParserCtxtPtr */ 3809 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 3810 int ret = -1; 3811 3812 if (ctx->node != NULL) { 3813 ret = xmlGetLineNo(ctx->node); 3814 } 3815 else { 3816 /* inspired from error.c */ 3817 xmlParserInputPtr input; 3818 input = ctx->input; 3819 if ((input->filename == NULL) && (ctx->inputNr > 1)) 3820 input = ctx->inputTab[ctx->inputNr - 2]; 3821 if (input != NULL) { 3822 ret = input->line; 3823 } 3824 else { 3825 ret = -1; 3826 } 3827 } 3828 3829 return ret; 3830} 3831 3832/** 3833 * xmlTextReaderLocatorBaseURI: 3834 * @locator: the xmlTextReaderLocatorPtr used 3835 * 3836 * Obtain the base URI for the given locator. 3837 * 3838 * Returns the base URI or NULL in case of error. 3839 */ 3840xmlChar * 3841xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { 3842 /* we know that locator is a xmlParserCtxtPtr */ 3843 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; 3844 xmlChar *ret = NULL; 3845 3846 if (ctx->node != NULL) { 3847 ret = xmlNodeGetBase(NULL,ctx->node); 3848 } 3849 else { 3850 /* inspired from error.c */ 3851 xmlParserInputPtr input; 3852 input = ctx->input; 3853 if ((input->filename == NULL) && (ctx->inputNr > 1)) 3854 input = ctx->inputTab[ctx->inputNr - 2]; 3855 if (input != NULL) { 3856 ret = xmlStrdup(BAD_CAST input->filename); 3857 } 3858 else { 3859 ret = NULL; 3860 } 3861 } 3862 3863 return ret; 3864} 3865 3866static void 3867xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) { 3868 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt; 3869 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private; 3870 3871 if (str != NULL) { 3872 reader->errorFunc(reader->errorFuncArg, 3873 str, 3874 severity, 3875 (xmlTextReaderLocatorPtr)ctx); 3876 xmlFree(str); 3877 } 3878} 3879 3880static void 3881xmlTextReaderError(void *ctxt, const char *msg, ...) { 3882 va_list ap; 3883 3884 va_start(ap,msg); 3885 xmlTextReaderGenericError(ctxt, 3886 XML_PARSER_SEVERITY_ERROR, 3887 xmlTextReaderBuildMessage(msg,ap)); 3888 va_end(ap); 3889 3890} 3891 3892static void 3893xmlTextReaderWarning(void *ctxt, const char *msg, ...) { 3894 va_list ap; 3895 3896 va_start(ap,msg); 3897 xmlTextReaderGenericError(ctxt, 3898 XML_PARSER_SEVERITY_WARNING, 3899 xmlTextReaderBuildMessage(msg,ap)); 3900 va_end(ap); 3901} 3902 3903static void 3904xmlTextReaderValidityError(void *ctxt, const char *msg, ...) { 3905 va_list ap; 3906 int len = xmlStrlen((const xmlChar *) msg); 3907 3908 if ((len > 1) && (msg[len - 2] != ':')) { 3909 /* 3910 * some callbacks only report locator information: 3911 * skip them (mimicking behaviour in error.c) 3912 */ 3913 va_start(ap,msg); 3914 xmlTextReaderGenericError(ctxt, 3915 XML_PARSER_SEVERITY_VALIDITY_ERROR, 3916 xmlTextReaderBuildMessage(msg,ap)); 3917 va_end(ap); 3918 } 3919} 3920 3921static void 3922xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) { 3923 va_list ap; 3924 int len = xmlStrlen((const xmlChar *) msg); 3925 3926 if ((len != 0) && (msg[len - 1] != ':')) { 3927 /* 3928 * some callbacks only report locator information: 3929 * skip them (mimicking behaviour in error.c) 3930 */ 3931 va_start(ap,msg); 3932 xmlTextReaderGenericError(ctxt, 3933 XML_PARSER_SEVERITY_VALIDITY_WARNING, 3934 xmlTextReaderBuildMessage(msg,ap)); 3935 va_end(ap); 3936 } 3937} 3938 3939/** 3940 * xmlTextReaderSetErrorHandler: 3941 * @reader: the xmlTextReaderPtr used 3942 * @f: the callback function to call on error and warnings 3943 * @arg: a user argument to pass to the callback function 3944 * 3945 * Register a callback function that will be called on error and warnings. 3946 * 3947 * If @f is NULL, the default error and warning handlers are restored. 3948 */ 3949void 3950xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, 3951 xmlTextReaderErrorFunc f, 3952 void *arg) { 3953 if (f != NULL) { 3954 reader->ctxt->sax->error = xmlTextReaderError; 3955 reader->ctxt->vctxt.error = xmlTextReaderValidityError; 3956 reader->ctxt->sax->warning = xmlTextReaderWarning; 3957 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; 3958 reader->errorFunc = f; 3959 reader->errorFuncArg = arg; 3960 } 3961 else { 3962 /* restore defaults */ 3963 reader->ctxt->sax->error = xmlParserError; 3964 reader->ctxt->vctxt.error = xmlParserValidityError; 3965 reader->ctxt->sax->warning = xmlParserWarning; 3966 reader->ctxt->vctxt.warning = xmlParserValidityWarning; 3967 reader->errorFunc = NULL; 3968 reader->errorFuncArg = NULL; 3969 } 3970} 3971 3972/** 3973 * xmlTextReaderIsValid: 3974 * @reader: the xmlTextReaderPtr used 3975 * 3976 * Retrieve the validity status from the parser context 3977 * 3978 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error 3979 */ 3980int 3981xmlTextReaderIsValid(xmlTextReaderPtr reader) { 3982 if (reader == NULL) return(-1); 3983#ifdef LIBXML_SCHEMAS_ENABLED 3984 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG) 3985 return(reader->rngValidErrors == 0); 3986#endif 3987 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1)) 3988 return(reader->ctxt->valid); 3989 return(0); 3990} 3991 3992/** 3993 * xmlTextReaderGetErrorHandler: 3994 * @reader: the xmlTextReaderPtr used 3995 * @f: the callback function or NULL is no callback has been registered 3996 * @arg: a user argument 3997 * 3998 * Retrieve the error callback function and user argument. 3999 */ 4000void 4001xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, 4002 xmlTextReaderErrorFunc *f, 4003 void **arg) { 4004 *f = reader->errorFunc; 4005 *arg = reader->errorFuncArg; 4006} 4007 4008 4009/************************************************************************ 4010 * * 4011 * New set (2.6.0) of simpler and more flexible APIs * 4012 * * 4013 ************************************************************************/ 4014 4015/** 4016 * xmlTextReaderSetup: 4017 * @reader: an XML reader 4018 * @URL: the base URL to use for the document 4019 * @encoding: the document encoding, or NULL 4020 * @options: a combination of xmlParserOption(s) 4021 * @reuse: keep the context for reuse 4022 * 4023 * Setup an XML reader with new options 4024 * 4025 * Returns 0 in case of success and -1 in case of error. 4026 */ 4027static int 4028xmlTextReaderSetup(xmlTextReaderPtr reader, 4029 xmlParserInputBufferPtr input, const char *URL, 4030 const char *encoding, int options) 4031{ 4032 if (reader == NULL) 4033 return (-1); 4034 4035 reader->doc = NULL; 4036 reader->entNr = 0; 4037 reader->parserFlags = options; 4038 reader->validate = XML_TEXTREADER_NOT_VALIDATE; 4039 if ((input != NULL) && (reader->input != NULL) && 4040 (reader->allocs & XML_TEXTREADER_INPUT)) { 4041 xmlFreeParserInputBuffer(reader->input); 4042 reader->input = NULL; 4043 reader->allocs -= XML_TEXTREADER_INPUT; 4044 } 4045 if (input != NULL) { 4046 reader->input = input; 4047 reader->allocs |= XML_TEXTREADER_INPUT; 4048 } 4049 if (reader->buffer == NULL) 4050 reader->buffer = xmlBufferCreateSize(100); 4051 if (reader->buffer == NULL) { 4052 xmlGenericError(xmlGenericErrorContext, 4053 "xmlTextReaderSetup : malloc failed\n"); 4054 return (-1); 4055 } 4056 if (reader->sax == NULL) 4057 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); 4058 if (reader->sax == NULL) { 4059 xmlGenericError(xmlGenericErrorContext, 4060 "xmlTextReaderSetup : malloc failed\n"); 4061 return (-1); 4062 } 4063 xmlSAXVersion(reader->sax, 2); 4064 reader->startElement = reader->sax->startElement; 4065 reader->sax->startElement = xmlTextReaderStartElement; 4066 reader->endElement = reader->sax->endElement; 4067 reader->sax->endElement = xmlTextReaderEndElement; 4068#ifdef LIBXML_SAX1_ENABLED 4069 if (reader->sax->initialized == XML_SAX2_MAGIC) { 4070#endif /* LIBXML_SAX1_ENABLED */ 4071 reader->startElementNs = reader->sax->startElementNs; 4072 reader->sax->startElementNs = xmlTextReaderStartElementNs; 4073 reader->endElementNs = reader->sax->endElementNs; 4074 reader->sax->endElementNs = xmlTextReaderEndElementNs; 4075#ifdef LIBXML_SAX1_ENABLED 4076 } else { 4077 reader->startElementNs = NULL; 4078 reader->endElementNs = NULL; 4079 } 4080#endif /* LIBXML_SAX1_ENABLED */ 4081 reader->characters = reader->sax->characters; 4082 reader->sax->characters = xmlTextReaderCharacters; 4083 reader->sax->ignorableWhitespace = xmlTextReaderCharacters; 4084 reader->cdataBlock = reader->sax->cdataBlock; 4085 reader->sax->cdataBlock = xmlTextReaderCDataBlock; 4086 4087 reader->mode = XML_TEXTREADER_MODE_INITIAL; 4088 reader->node = NULL; 4089 reader->curnode = NULL; 4090 if (input != NULL) { 4091 if (reader->input->buffer->use < 4) { 4092 xmlParserInputBufferRead(input, 4); 4093 } 4094 if (reader->ctxt == NULL) { 4095 if (reader->input->buffer->use >= 4) { 4096 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, 4097 (const char *) reader->input->buffer->content, 4, URL); 4098 reader->base = 0; 4099 reader->cur = 4; 4100 } else { 4101 reader->ctxt = 4102 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); 4103 reader->base = 0; 4104 reader->cur = 0; 4105 } 4106 } else { 4107 xmlParserInputPtr inputStream; 4108 xmlParserInputBufferPtr buf; 4109 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; 4110 4111 if (reader->ctxt->myDoc != NULL) 4112 xmlDictReference(reader->ctxt->myDoc->dict); 4113 xmlCtxtReset(reader->ctxt); 4114 buf = xmlAllocParserInputBuffer(enc); 4115 if (buf == NULL) return(-1); 4116 inputStream = xmlNewInputStream(reader->ctxt); 4117 if (inputStream == NULL) { 4118 xmlFreeParserInputBuffer(buf); 4119 return(-1); 4120 } 4121 4122 if (URL == NULL) 4123 inputStream->filename = NULL; 4124 else 4125 inputStream->filename = (char *) 4126 xmlCanonicPath((const xmlChar *) URL); 4127 inputStream->buf = buf; 4128 inputStream->base = inputStream->buf->buffer->content; 4129 inputStream->cur = inputStream->buf->buffer->content; 4130 inputStream->end = 4131 &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; 4132 4133 inputPush(reader->ctxt, inputStream); 4134 reader->cur = 0; 4135 } 4136 if (reader->ctxt == NULL) { 4137 xmlGenericError(xmlGenericErrorContext, 4138 "xmlTextReaderSetup : malloc failed\n"); 4139 return (-1); 4140 } 4141 } 4142 if (reader->dict != NULL) { 4143 if (reader->ctxt->dict != NULL) { 4144 if (reader->dict != reader->ctxt->dict) { 4145 xmlDictFree(reader->dict); 4146 reader->dict = reader->ctxt->dict; 4147 } 4148 } else { 4149 reader->ctxt->dict = reader->dict; 4150 } 4151 } else { 4152 if (reader->ctxt->dict == NULL) 4153 reader->ctxt->dict = xmlDictCreate(); 4154 reader->dict = reader->ctxt->dict; 4155 } 4156 reader->ctxt->_private = reader; 4157 reader->ctxt->linenumbers = 1; 4158 reader->ctxt->dictNames = 1; 4159 /* 4160 * use the parser dictionnary to allocate all elements and attributes names 4161 */ 4162 reader->ctxt->docdict = 1; 4163 4164#ifdef LIBXML_XINCLUDE_ENABLED 4165 if (reader->xincctxt != NULL) { 4166 xmlXIncludeFreeContext(reader->xincctxt); 4167 reader->xincctxt = NULL; 4168 } 4169 if (options & XML_PARSE_XINCLUDE) { 4170 reader->xinclude = 1; 4171 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); 4172 options -= XML_PARSE_XINCLUDE; 4173 } else 4174 reader->xinclude = 0; 4175 reader->in_xinclude = 0; 4176#endif 4177#ifdef LIBXML_PATTERN_ENABLED 4178 if (reader->patternTab == NULL) { 4179 reader->patternNr = 0; 4180 reader->patternMax = 0; 4181 } 4182 while (reader->patternNr > 0) { 4183 reader->patternNr--; 4184 if (reader->patternTab[reader->patternNr] != NULL) { 4185 xmlFreePattern(reader->patternTab[reader->patternNr]); 4186 reader->patternTab[reader->patternNr] = NULL; 4187 } 4188 } 4189#endif 4190 4191 if (options & XML_PARSE_DTDVALID) 4192 reader->validate = XML_TEXTREADER_VALIDATE_DTD; 4193 4194 xmlCtxtUseOptions(reader->ctxt, options); 4195 if (encoding != NULL) { 4196 xmlCharEncodingHandlerPtr hdlr; 4197 4198 hdlr = xmlFindCharEncodingHandler(encoding); 4199 if (hdlr != NULL) 4200 xmlSwitchToEncoding(reader->ctxt, hdlr); 4201 } 4202 if ((URL != NULL) && (reader->ctxt->input != NULL) && 4203 (reader->ctxt->input->filename == NULL)) 4204 reader->ctxt->input->filename = (char *) 4205 xmlStrdup((const xmlChar *) URL); 4206 4207 reader->doc = NULL; 4208 4209 return (0); 4210} 4211 4212/** 4213 * xmlReaderWalker: 4214 * @doc: a preparsed document 4215 * 4216 * Create an xmltextReader for a preparsed document. 4217 * 4218 * Returns the new reader or NULL in case of error. 4219 */ 4220xmlTextReaderPtr 4221xmlReaderWalker(xmlDocPtr doc) 4222{ 4223 xmlTextReaderPtr ret; 4224 4225 if (doc == NULL) 4226 return(NULL); 4227 4228 ret = xmlMalloc(sizeof(xmlTextReader)); 4229 if (ret == NULL) { 4230 xmlGenericError(xmlGenericErrorContext, 4231 "xmlNewTextReader : malloc failed\n"); 4232 return(NULL); 4233 } 4234 memset(ret, 0, sizeof(xmlTextReader)); 4235 ret->entNr = 0; 4236 ret->input = NULL; 4237 ret->mode = XML_TEXTREADER_MODE_INITIAL; 4238 ret->node = NULL; 4239 ret->curnode = NULL; 4240 ret->base = 0; 4241 ret->cur = 0; 4242 ret->allocs = XML_TEXTREADER_CTXT; 4243 ret->doc = doc; 4244 ret->state = XML_TEXTREADER_START; 4245 ret->dict = xmlDictCreate(); 4246 return(ret); 4247} 4248 4249/** 4250 * xmlReaderForDoc: 4251 * @cur: a pointer to a zero terminated string 4252 * @URL: the base URL to use for the document 4253 * @encoding: the document encoding, or NULL 4254 * @options: a combination of xmlParserOption(s) 4255 * 4256 * Create an xmltextReader for an XML in-memory document. 4257 * The parsing flags @options are a combination of xmlParserOption(s). 4258 * 4259 * Returns the new reader or NULL in case of error. 4260 */ 4261xmlTextReaderPtr 4262xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, 4263 int options) 4264{ 4265 int len; 4266 4267 if (cur == NULL) 4268 return (NULL); 4269 len = xmlStrlen(cur); 4270 4271 return (xmlReaderForMemory 4272 ((const char *) cur, len, URL, encoding, options)); 4273} 4274 4275/** 4276 * xmlReaderForFile: 4277 * @filename: a file or URL 4278 * @encoding: the document encoding, or NULL 4279 * @options: a combination of xmlParserOption(s) 4280 * 4281 * parse an XML file from the filesystem or the network. 4282 * The parsing flags @options are a combination of xmlParserOption(s). 4283 * 4284 * Returns the new reader or NULL in case of error. 4285 */ 4286xmlTextReaderPtr 4287xmlReaderForFile(const char *filename, const char *encoding, int options) 4288{ 4289 xmlTextReaderPtr reader; 4290 4291 reader = xmlNewTextReaderFilename(filename); 4292 if (reader == NULL) 4293 return (NULL); 4294 xmlTextReaderSetup(reader, NULL, NULL, encoding, options); 4295 return (reader); 4296} 4297 4298/** 4299 * xmlReaderForMemory: 4300 * @buffer: a pointer to a char array 4301 * @size: the size of the array 4302 * @URL: the base URL to use for the document 4303 * @encoding: the document encoding, or NULL 4304 * @options: a combination of xmlParserOption(s) 4305 * 4306 * Create an xmltextReader for an XML in-memory document. 4307 * The parsing flags @options are a combination of xmlParserOption(s). 4308 * 4309 * Returns the new reader or NULL in case of error. 4310 */ 4311xmlTextReaderPtr 4312xmlReaderForMemory(const char *buffer, int size, const char *URL, 4313 const char *encoding, int options) 4314{ 4315 xmlTextReaderPtr reader; 4316 xmlParserInputBufferPtr buf; 4317 4318 buf = 4319 xmlParserInputBufferCreateMem(buffer, size, 4320 XML_CHAR_ENCODING_NONE); 4321 if (buf == NULL) { 4322 return (NULL); 4323 } 4324 reader = xmlNewTextReader(buf, URL); 4325 if (reader == NULL) { 4326 xmlFreeParserInputBuffer(buf); 4327 return (NULL); 4328 } 4329 reader->allocs |= XML_TEXTREADER_INPUT; 4330 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 4331 return (reader); 4332} 4333 4334/** 4335 * xmlReaderForFd: 4336 * @fd: an open file descriptor 4337 * @URL: the base URL to use for the document 4338 * @encoding: the document encoding, or NULL 4339 * @options: a combination of xmlParserOption(s) 4340 * 4341 * Create an xmltextReader for an XML from a file descriptor. 4342 * The parsing flags @options are a combination of xmlParserOption(s). 4343 * 4344 * Returns the new reader or NULL in case of error. 4345 */ 4346xmlTextReaderPtr 4347xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) 4348{ 4349 xmlTextReaderPtr reader; 4350 xmlParserInputBufferPtr input; 4351 4352 if (fd < 0) 4353 return (NULL); 4354 4355 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 4356 if (input == NULL) 4357 return (NULL); 4358 reader = xmlNewTextReader(input, URL); 4359 if (reader == NULL) { 4360 xmlFreeParserInputBuffer(input); 4361 return (NULL); 4362 } 4363 reader->allocs |= XML_TEXTREADER_INPUT; 4364 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 4365 return (reader); 4366} 4367 4368/** 4369 * xmlReaderForIO: 4370 * @ioread: an I/O read function 4371 * @ioclose: an I/O close function 4372 * @ioctx: an I/O handler 4373 * @URL: the base URL to use for the document 4374 * @encoding: the document encoding, or NULL 4375 * @options: a combination of xmlParserOption(s) 4376 * 4377 * Create an xmltextReader for an XML document from I/O functions and source. 4378 * The parsing flags @options are a combination of xmlParserOption(s). 4379 * 4380 * Returns the new reader or NULL in case of error. 4381 */ 4382xmlTextReaderPtr 4383xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, 4384 void *ioctx, const char *URL, const char *encoding, 4385 int options) 4386{ 4387 xmlTextReaderPtr reader; 4388 xmlParserInputBufferPtr input; 4389 4390 if (ioread == NULL) 4391 return (NULL); 4392 4393 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 4394 XML_CHAR_ENCODING_NONE); 4395 if (input == NULL) 4396 return (NULL); 4397 reader = xmlNewTextReader(input, URL); 4398 if (reader == NULL) { 4399 xmlFreeParserInputBuffer(input); 4400 return (NULL); 4401 } 4402 reader->allocs |= XML_TEXTREADER_INPUT; 4403 xmlTextReaderSetup(reader, NULL, URL, encoding, options); 4404 return (reader); 4405} 4406 4407/** 4408 * xmlReaderNewWalker: 4409 * @reader: an XML reader 4410 * @doc: a preparsed document 4411 * 4412 * Setup an xmltextReader to parse a preparsed XML document. 4413 * This reuses the existing @reader xmlTextReader. 4414 * 4415 * Returns 0 in case of success and -1 in case of error 4416 */ 4417int 4418xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc) 4419{ 4420 if (doc == NULL) 4421 return (-1); 4422 if (reader == NULL) 4423 return (-1); 4424 4425 if (reader->ctxt != NULL) { 4426 xmlCtxtReset(reader->ctxt); 4427 } 4428 4429 reader->entNr = 0; 4430 reader->input = NULL; 4431 reader->mode = XML_TEXTREADER_MODE_INITIAL; 4432 reader->node = NULL; 4433 reader->curnode = NULL; 4434 reader->base = 0; 4435 reader->cur = 0; 4436 reader->allocs = XML_TEXTREADER_CTXT; 4437 reader->doc = doc; 4438 reader->state = XML_TEXTREADER_START; 4439 if (reader->dict == NULL) { 4440 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) 4441 reader->dict = reader->ctxt->dict; 4442 else 4443 reader->dict = xmlDictCreate(); 4444 } 4445 return(0); 4446} 4447 4448/** 4449 * xmlReaderNewDoc: 4450 * @reader: an XML reader 4451 * @cur: a pointer to a zero terminated string 4452 * @URL: the base URL to use for the document 4453 * @encoding: the document encoding, or NULL 4454 * @options: a combination of xmlParserOption(s) 4455 * 4456 * Setup an xmltextReader to parse an XML in-memory document. 4457 * The parsing flags @options are a combination of xmlParserOption(s). 4458 * This reuses the existing @reader xmlTextReader. 4459 * 4460 * Returns 0 in case of success and -1 in case of error 4461 */ 4462int 4463xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, 4464 const char *URL, const char *encoding, int options) 4465{ 4466 4467 int len; 4468 4469 if (cur == NULL) 4470 return (-1); 4471 if (reader == NULL) 4472 return (-1); 4473 4474 len = xmlStrlen(cur); 4475 return (xmlReaderNewMemory(reader, (const char *)cur, len, 4476 URL, encoding, options)); 4477} 4478 4479/** 4480 * xmlReaderNewFile: 4481 * @reader: an XML reader 4482 * @filename: a file or URL 4483 * @encoding: the document encoding, or NULL 4484 * @options: a combination of xmlParserOption(s) 4485 * 4486 * parse an XML file from the filesystem or the network. 4487 * The parsing flags @options are a combination of xmlParserOption(s). 4488 * This reuses the existing @reader xmlTextReader. 4489 * 4490 * Returns 0 in case of success and -1 in case of error 4491 */ 4492int 4493xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, 4494 const char *encoding, int options) 4495{ 4496 xmlParserInputBufferPtr input; 4497 4498 if (filename == NULL) 4499 return (-1); 4500 if (reader == NULL) 4501 return (-1); 4502 4503 input = 4504 xmlParserInputBufferCreateFilename(filename, 4505 XML_CHAR_ENCODING_NONE); 4506 if (input == NULL) 4507 return (-1); 4508 return (xmlTextReaderSetup(reader, input, filename, encoding, options)); 4509} 4510 4511/** 4512 * xmlReaderNewMemory: 4513 * @reader: an XML reader 4514 * @buffer: a pointer to a char array 4515 * @size: the size of the array 4516 * @URL: the base URL to use for the document 4517 * @encoding: the document encoding, or NULL 4518 * @options: a combination of xmlParserOption(s) 4519 * 4520 * Setup an xmltextReader to parse an XML in-memory document. 4521 * The parsing flags @options are a combination of xmlParserOption(s). 4522 * This reuses the existing @reader xmlTextReader. 4523 * 4524 * Returns 0 in case of success and -1 in case of error 4525 */ 4526int 4527xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, 4528 const char *URL, const char *encoding, int options) 4529{ 4530 xmlParserInputBufferPtr input; 4531 4532 if (reader == NULL) 4533 return (-1); 4534 if (buffer == NULL) 4535 return (-1); 4536 4537 input = xmlParserInputBufferCreateMem(buffer, size, 4538 XML_CHAR_ENCODING_NONE); 4539 if (input == NULL) { 4540 return (-1); 4541 } 4542 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 4543} 4544 4545/** 4546 * xmlReaderNewFd: 4547 * @reader: an XML reader 4548 * @fd: an open file descriptor 4549 * @URL: the base URL to use for the document 4550 * @encoding: the document encoding, or NULL 4551 * @options: a combination of xmlParserOption(s) 4552 * 4553 * Setup an xmltextReader to parse an XML from a file descriptor. 4554 * The parsing flags @options are a combination of xmlParserOption(s). 4555 * This reuses the existing @reader xmlTextReader. 4556 * 4557 * Returns 0 in case of success and -1 in case of error 4558 */ 4559int 4560xmlReaderNewFd(xmlTextReaderPtr reader, int fd, 4561 const char *URL, const char *encoding, int options) 4562{ 4563 xmlParserInputBufferPtr input; 4564 4565 if (fd < 0) 4566 return (-1); 4567 if (reader == NULL) 4568 return (-1); 4569 4570 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 4571 if (input == NULL) 4572 return (-1); 4573 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 4574} 4575 4576/** 4577 * xmlReaderNewIO: 4578 * @reader: an XML reader 4579 * @ioread: an I/O read function 4580 * @ioclose: an I/O close function 4581 * @ioctx: an I/O handler 4582 * @URL: the base URL to use for the document 4583 * @encoding: the document encoding, or NULL 4584 * @options: a combination of xmlParserOption(s) 4585 * 4586 * Setup an xmltextReader to parse an XML document from I/O functions 4587 * and source. 4588 * The parsing flags @options are a combination of xmlParserOption(s). 4589 * This reuses the existing @reader xmlTextReader. 4590 * 4591 * Returns 0 in case of success and -1 in case of error 4592 */ 4593int 4594xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, 4595 xmlInputCloseCallback ioclose, void *ioctx, 4596 const char *URL, const char *encoding, int options) 4597{ 4598 xmlParserInputBufferPtr input; 4599 4600 if (ioread == NULL) 4601 return (-1); 4602 if (reader == NULL) 4603 return (-1); 4604 4605 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 4606 XML_CHAR_ENCODING_NONE); 4607 if (input == NULL) 4608 return (-1); 4609 return (xmlTextReaderSetup(reader, input, URL, encoding, options)); 4610} 4611/************************************************************************ 4612 * * 4613 * Utilities * 4614 * * 4615 ************************************************************************/ 4616#ifdef NOT_USED_YET 4617/** 4618 * xmlBase64Decode: 4619 * @in: the input buffer 4620 * @inlen: the size of the input (in), the size read from it (out) 4621 * @to: the output buffer 4622 * @tolen: the size of the output (in), the size written to (out) 4623 * 4624 * Base64 decoder, reads from @in and save in @to 4625 * TODO: tell jody when this is actually exported 4626 * 4627 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, 4628 * 2 if there wasn't enough space on the output or -1 in case of error. 4629 */ 4630static int 4631xmlBase64Decode(const unsigned char *in, unsigned long *inlen, 4632 unsigned char *to, unsigned long *tolen) { 4633 unsigned long incur; /* current index in in[] */ 4634 unsigned long inblk; /* last block index in in[] */ 4635 unsigned long outcur; /* current index in out[] */ 4636 unsigned long inmax; /* size of in[] */ 4637 unsigned long outmax; /* size of out[] */ 4638 unsigned char cur; /* the current value read from in[] */ 4639 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */ 4640 int nbintmp; /* number of byte in intmp[] */ 4641 int is_ignore; /* cur should be ignored */ 4642 int is_end = 0; /* the end of the base64 was found */ 4643 int retval = 1; 4644 int i; 4645 4646 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) 4647 return(-1); 4648 4649 incur = 0; 4650 inblk = 0; 4651 outcur = 0; 4652 inmax = *inlen; 4653 outmax = *tolen; 4654 nbintmp = 0; 4655 4656 while (1) { 4657 if (incur >= inmax) 4658 break; 4659 cur = in[incur++]; 4660 is_ignore = 0; 4661 if ((cur >= 'A') && (cur <= 'Z')) 4662 cur = cur - 'A'; 4663 else if ((cur >= 'a') && (cur <= 'z')) 4664 cur = cur - 'a' + 26; 4665 else if ((cur >= '0') && (cur <= '9')) 4666 cur = cur - '0' + 52; 4667 else if (cur == '+') 4668 cur = 62; 4669 else if (cur == '/') 4670 cur = 63; 4671 else if (cur == '.') 4672 cur = 0; 4673 else if (cur == '=') /*no op , end of the base64 stream */ 4674 is_end = 1; 4675 else { 4676 is_ignore = 1; 4677 if (nbintmp == 0) 4678 inblk = incur; 4679 } 4680 4681 if (!is_ignore) { 4682 int nbouttmp = 3; 4683 int is_break = 0; 4684 4685 if (is_end) { 4686 if (nbintmp == 0) 4687 break; 4688 if ((nbintmp == 1) || (nbintmp == 2)) 4689 nbouttmp = 1; 4690 else 4691 nbouttmp = 2; 4692 nbintmp = 3; 4693 is_break = 1; 4694 } 4695 intmp[nbintmp++] = cur; 4696 /* 4697 * if intmp is full, push the 4byte sequence as a 3 byte 4698 * sequence out 4699 */ 4700 if (nbintmp == 4) { 4701 nbintmp = 0; 4702 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); 4703 outtmp[1] = 4704 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); 4705 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); 4706 if (outcur + 3 >= outmax) { 4707 retval = 2; 4708 break; 4709 } 4710 4711 for (i = 0; i < nbouttmp; i++) 4712 to[outcur++] = outtmp[i]; 4713 inblk = incur; 4714 } 4715 4716 if (is_break) { 4717 retval = 0; 4718 break; 4719 } 4720 } 4721 } 4722 4723 *tolen = outcur; 4724 *inlen = inblk; 4725 return (retval); 4726} 4727 4728/* 4729 * Test routine for the xmlBase64Decode function 4730 */ 4731#if 0 4732int main(int argc, char **argv) { 4733 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== "; 4734 char output[100]; 4735 char output2[100]; 4736 char output3[100]; 4737 unsigned long inlen = strlen(input); 4738 unsigned long outlen = 100; 4739 int ret; 4740 unsigned long cons, tmp, tmp2, prod; 4741 4742 /* 4743 * Direct 4744 */ 4745 ret = xmlBase64Decode(input, &inlen, output, &outlen); 4746 4747 output[outlen] = 0; 4748 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output); 4749 4750 /* 4751 * output chunking 4752 */ 4753 cons = 0; 4754 prod = 0; 4755 while (cons < inlen) { 4756 tmp = 5; 4757 tmp2 = inlen - cons; 4758 4759 printf("%ld %ld\n", cons, prod); 4760 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); 4761 cons += tmp2; 4762 prod += tmp; 4763 printf("%ld %ld\n", cons, prod); 4764 } 4765 output2[outlen] = 0; 4766 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2); 4767 4768 /* 4769 * input chunking 4770 */ 4771 cons = 0; 4772 prod = 0; 4773 while (cons < inlen) { 4774 tmp = 100 - prod; 4775 tmp2 = inlen - cons; 4776 if (tmp2 > 5) 4777 tmp2 = 5; 4778 4779 printf("%ld %ld\n", cons, prod); 4780 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); 4781 cons += tmp2; 4782 prod += tmp; 4783 printf("%ld %ld\n", cons, prod); 4784 } 4785 output3[outlen] = 0; 4786 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3); 4787 return(0); 4788 4789} 4790#endif 4791#endif /* NOT_USED_YET */ 4792#endif /* LIBXML_READER_ENABLED */ 4793