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