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