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