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