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