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