ReactOS 0.4.15-dev-7712-gbbbcd8e
xmlreader.c
Go to the documentation of this file.
1/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
4 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
8 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
13/*
14 * TODOs:
15 * - XML Schemas validation
16 */
17#define IN_LIBXML
18#include "libxml.h"
19
20#ifdef LIBXML_READER_ENABLED
21#include <string.h> /* for memset() only ! */
22#include <stdarg.h>
23#include <ctype.h>
24#include <stdlib.h>
25
26#include <libxml/xmlmemory.h>
27#include <libxml/xmlIO.h>
28#include <libxml/xmlreader.h>
30#ifdef LIBXML_SCHEMAS_ENABLED
31#include <libxml/relaxng.h>
32#include <libxml/xmlschemas.h>
33#endif
34#include <libxml/uri.h>
35#ifdef LIBXML_XINCLUDE_ENABLED
36#include <libxml/xinclude.h>
37#endif
38#ifdef LIBXML_PATTERN_ENABLED
39#include <libxml/pattern.h>
40#endif
41
42#include "buf.h"
43
44#define MAX_ERR_MSG_SIZE 64000
45
46#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
47/* Keeping free objects can hide memory errors. */
48#define MAX_FREE_NODES 1
49#else
50#define MAX_FREE_NODES 100
51#endif
52
53/*
54 * The following VA_COPY was coded following an example in
55 * the Samba project. It may not be sufficient for some
56 * esoteric implementations of va_list but (hopefully) will
57 * be sufficient for libxml2.
58 */
59#ifndef VA_COPY
60 #ifdef HAVE_VA_COPY
61 #define VA_COPY(dest, src) va_copy(dest, src)
62 #else
63 #ifdef HAVE___VA_COPY
64 #define VA_COPY(dest,src) __va_copy(dest, src)
65 #else
66 #ifndef VA_LIST_IS_ARRAY
67 #define VA_COPY(dest,src) (dest) = (src)
68 #else
69 #include <string.h>
70 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
71 #endif
72 #endif
73 #endif
74#endif
75
76/* #define DEBUG_CALLBACKS */
77/* #define DEBUG_READER */
78
84#define TODO \
85 xmlGenericError(xmlGenericErrorContext, \
86 "Unimplemented block at %s:%d\n", \
87 __FILE__, __LINE__);
88
89#ifdef DEBUG_READER
90#define DUMP_READER xmlTextReaderDebug(reader);
91#else
92#define DUMP_READER
93#endif
94
95#define CHUNK_SIZE 512
96/************************************************************************
97 * *
98 * The parser: maps the Text Reader API on top of the existing *
99 * parsing routines building a tree *
100 * *
101 ************************************************************************/
102
103#define XML_TEXTREADER_INPUT 1
104#define XML_TEXTREADER_CTXT 2
105
106typedef enum {
107 XML_TEXTREADER_NONE = -1,
108 XML_TEXTREADER_START= 0,
109 XML_TEXTREADER_ELEMENT= 1,
110 XML_TEXTREADER_END= 2,
111 XML_TEXTREADER_EMPTY= 3,
112 XML_TEXTREADER_BACKTRACK= 4,
113 XML_TEXTREADER_DONE= 5,
114 XML_TEXTREADER_ERROR= 6
115} xmlTextReaderState;
116
117typedef enum {
118 XML_TEXTREADER_NOT_VALIDATE = 0,
119 XML_TEXTREADER_VALIDATE_DTD = 1,
120 XML_TEXTREADER_VALIDATE_RNG = 2,
121 XML_TEXTREADER_VALIDATE_XSD = 4
122} xmlTextReaderValidate;
123
124struct _xmlTextReader {
125 int mode; /* the parsing mode */
126 xmlDocPtr doc; /* when walking an existing doc */
127 xmlTextReaderValidate validate;/* is there any validation */
128 int allocs; /* what structure were deallocated */
129 xmlTextReaderState state;
130 xmlParserCtxtPtr ctxt; /* the parser context */
131 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
132 xmlParserInputBufferPtr input; /* the input */
133 startElementSAXFunc startElement;/* initial SAX callbacks */
134 endElementSAXFunc endElement; /* idem */
135 startElementNsSAX2Func startElementNs;/* idem */
136 endElementNsSAX2Func endElementNs; /* idem */
137 charactersSAXFunc characters;
138 cdataBlockSAXFunc cdataBlock;
139 unsigned int base; /* base of the segment in the input */
140 unsigned int cur; /* current position in the input */
141 xmlNodePtr node; /* current node */
142 xmlNodePtr curnode;/* current attribute node */
143 int depth; /* depth of the current node */
144 xmlNodePtr faketext;/* fake xmlNs chld */
145 int preserve;/* preserve the resulting document */
146 xmlBufPtr buffer; /* used to return const xmlChar * */
147 xmlDictPtr dict; /* the context dictionary */
148
149 /* entity stack when traversing entities content */
150 xmlNodePtr ent; /* Current Entity Ref Node */
151 int entNr; /* Depth of the entities stack */
152 int entMax; /* Max depth of the entities stack */
153 xmlNodePtr *entTab; /* array of entities */
154
155 /* error handling */
156 xmlTextReaderErrorFunc errorFunc; /* callback function */
157 void *errorFuncArg; /* callback function user argument */
158
159#ifdef LIBXML_SCHEMAS_ENABLED
160 /* Handling of RelaxNG validation */
161 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
162 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
163 int rngPreserveCtxt; /* 1 if the context was provided by the user */
164 int rngValidErrors;/* The number of errors detected */
165 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
166 /* Handling of Schemas validation */
167 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
168 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
169 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
170 int xsdValidErrors;/* The number of errors detected */
171 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
172#endif
173#ifdef LIBXML_XINCLUDE_ENABLED
174 /* Handling of XInclude processing */
175 int xinclude; /* is xinclude asked for */
176 const xmlChar * xinclude_name; /* the xinclude name from dict */
177 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
178 int in_xinclude; /* counts for xinclude */
179#endif
180#ifdef LIBXML_PATTERN_ENABLED
181 int patternNr; /* number of preserve patterns */
182 int patternMax; /* max preserve patterns */
183 xmlPatternPtr *patternTab; /* array of preserve patterns */
184#endif
185 int preserves; /* level of preserves */
186 int parserFlags; /* the set of options set */
187 /* Structured error handling */
188 xmlStructuredErrorFunc sErrorFunc; /* callback function */
189};
190
191#define NODE_IS_EMPTY 0x1
192#define NODE_IS_PRESERVED 0x2
193#define NODE_IS_SPRESERVED 0x4
194
200#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
201#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
202
203static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
204static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
205
206/************************************************************************
207 * *
208 * Our own version of the freeing routines as we recycle nodes *
209 * *
210 ************************************************************************/
218#define DICT_FREE(str) \
219 if ((str) && ((!dict) || \
220 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
221 xmlFree((char *)(str));
222
223static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
224static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
225
233static void
234xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
235 xmlDictPtr dict;
236
237 if ((reader != NULL) && (reader->ctxt != NULL))
238 dict = reader->ctxt->dict;
239 else
240 dict = NULL;
241 if (cur == NULL) return;
242
245
246 if (cur->children != NULL)
247 xmlTextReaderFreeNodeList(reader, cur->children);
248
249 DICT_FREE(cur->name);
250 if ((reader != NULL) && (reader->ctxt != NULL) &&
251 (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
252 cur->next = reader->ctxt->freeAttrs;
253 reader->ctxt->freeAttrs = cur;
254 reader->ctxt->freeAttrsNr++;
255 } else {
256 xmlFree(cur);
257 }
258}
259
267static void
268xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
270
271 while (cur != NULL) {
272 next = cur->next;
273 xmlTextReaderFreeProp(reader, cur);
274 cur = next;
275 }
276}
277
286static void
287xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
290 xmlDictPtr dict;
291 size_t depth = 0;
292
293 if ((reader != NULL) && (reader->ctxt != NULL))
294 dict = reader->ctxt->dict;
295 else
296 dict = NULL;
297 if (cur == NULL) return;
298 if (cur->type == XML_NAMESPACE_DECL) {
300 return;
301 }
302 if ((cur->type == XML_DOCUMENT_NODE) ||
303 (cur->type == XML_HTML_DOCUMENT_NODE)) {
305 return;
306 }
307 while (1) {
308 while ((cur->type != XML_DTD_NODE) &&
309 (cur->type != XML_ENTITY_REF_NODE) &&
310 (cur->children != NULL) &&
311 (cur->children->parent == cur)) {
312 cur = cur->children;
313 depth += 1;
314 }
315
316 next = cur->next;
317 parent = cur->parent;
318
319 /* unroll to speed up freeing the document */
320 if (cur->type != XML_DTD_NODE) {
321
324
325 if (((cur->type == XML_ELEMENT_NODE) ||
326 (cur->type == XML_XINCLUDE_START) ||
327 (cur->type == XML_XINCLUDE_END)) &&
328 (cur->properties != NULL))
329 xmlTextReaderFreePropList(reader, cur->properties);
330 if ((cur->content != (xmlChar *) &(cur->properties)) &&
331 (cur->type != XML_ELEMENT_NODE) &&
332 (cur->type != XML_XINCLUDE_START) &&
333 (cur->type != XML_XINCLUDE_END) &&
334 (cur->type != XML_ENTITY_REF_NODE)) {
335 DICT_FREE(cur->content);
336 }
337 if (((cur->type == XML_ELEMENT_NODE) ||
338 (cur->type == XML_XINCLUDE_START) ||
339 (cur->type == XML_XINCLUDE_END)) &&
340 (cur->nsDef != NULL))
341 xmlFreeNsList(cur->nsDef);
342
343 /*
344 * we don't free element names here they are interned now
345 */
346 if ((cur->type != XML_TEXT_NODE) &&
347 (cur->type != XML_COMMENT_NODE))
348 DICT_FREE(cur->name);
349 if (((cur->type == XML_ELEMENT_NODE) ||
350 (cur->type == XML_TEXT_NODE)) &&
351 (reader != NULL) && (reader->ctxt != NULL) &&
352 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
353 cur->next = reader->ctxt->freeElems;
354 reader->ctxt->freeElems = cur;
355 reader->ctxt->freeElemsNr++;
356 } else {
357 xmlFree(cur);
358 }
359 }
360
361 if (next != NULL) {
362 cur = next;
363 } else {
364 if ((depth == 0) || (parent == NULL))
365 break;
366 depth -= 1;
367 cur = parent;
368 cur->children = NULL;
369 }
370 }
371}
372
381static void
382xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
383 xmlDictPtr dict;
384
385 if ((reader != NULL) && (reader->ctxt != NULL))
386 dict = reader->ctxt->dict;
387 else
388 dict = NULL;
389 if (cur->type == XML_DTD_NODE) {
391 return;
392 }
393 if (cur->type == XML_NAMESPACE_DECL) {
395 return;
396 }
397 if (cur->type == XML_ATTRIBUTE_NODE) {
398 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
399 return;
400 }
401
402 if ((cur->children != NULL) &&
403 (cur->type != XML_ENTITY_REF_NODE)) {
404 if (cur->children->parent == cur)
405 xmlTextReaderFreeNodeList(reader, cur->children);
406 cur->children = NULL;
407 }
408
411
412 if (((cur->type == XML_ELEMENT_NODE) ||
413 (cur->type == XML_XINCLUDE_START) ||
414 (cur->type == XML_XINCLUDE_END)) &&
415 (cur->properties != NULL))
416 xmlTextReaderFreePropList(reader, cur->properties);
417 if ((cur->content != (xmlChar *) &(cur->properties)) &&
418 (cur->type != XML_ELEMENT_NODE) &&
419 (cur->type != XML_XINCLUDE_START) &&
420 (cur->type != XML_XINCLUDE_END) &&
421 (cur->type != XML_ENTITY_REF_NODE)) {
422 DICT_FREE(cur->content);
423 }
424 if (((cur->type == XML_ELEMENT_NODE) ||
425 (cur->type == XML_XINCLUDE_START) ||
426 (cur->type == XML_XINCLUDE_END)) &&
427 (cur->nsDef != NULL))
428 xmlFreeNsList(cur->nsDef);
429
430 /*
431 * we don't free names here they are interned now
432 */
433 if ((cur->type != XML_TEXT_NODE) &&
434 (cur->type != XML_COMMENT_NODE))
435 DICT_FREE(cur->name);
436
437 if (((cur->type == XML_ELEMENT_NODE) ||
438 (cur->type == XML_TEXT_NODE)) &&
439 (reader != NULL) && (reader->ctxt != NULL) &&
440 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
441 cur->next = reader->ctxt->freeElems;
442 reader->ctxt->freeElems = cur;
443 reader->ctxt->freeElemsNr++;
444 } else {
445 xmlFree(cur);
446 }
447}
448
456static void
457xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
458 xmlDtdPtr extSubset, intSubset;
459
460 if (cur == NULL) return;
461
464
465 /*
466 * Do this before freeing the children list to avoid ID lookups
467 */
468 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
469 cur->ids = NULL;
470 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
471 cur->refs = NULL;
472 extSubset = cur->extSubset;
473 intSubset = cur->intSubset;
474 if (intSubset == extSubset)
475 extSubset = NULL;
476 if (extSubset != NULL) {
477 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
478 cur->extSubset = NULL;
479 xmlFreeDtd(extSubset);
480 }
481 if (intSubset != NULL) {
482 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
483 cur->intSubset = NULL;
484 xmlFreeDtd(intSubset);
485 }
486
487 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
488
489 if (cur->version != NULL) xmlFree((char *) cur->version);
490 if (cur->name != NULL) xmlFree((char *) cur->name);
491 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
492 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
493 if (cur->URL != NULL) xmlFree((char *) cur->URL);
494 if (cur->dict != NULL) xmlDictFree(cur->dict);
495
496 xmlFree(cur);
497}
498
499/************************************************************************
500 * *
501 * The reader core parser *
502 * *
503 ************************************************************************/
504#ifdef DEBUG_READER
505static void
506xmlTextReaderDebug(xmlTextReaderPtr reader) {
507 if ((reader == NULL) || (reader->ctxt == NULL)) {
508 fprintf(stderr, "xmlTextReader NULL\n");
509 return;
510 }
511 fprintf(stderr, "xmlTextReader: state %d depth %d ",
512 reader->state, reader->depth);
513 if (reader->node == NULL) {
514 fprintf(stderr, "node = NULL\n");
515 } else {
516 fprintf(stderr, "node %s\n", reader->node->name);
517 }
518 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
519 reader->base, reader->cur, reader->ctxt->nodeNr);
520 if (reader->input->buffer == NULL) {
521 fprintf(stderr, "buffer is NULL\n");
522 } else {
523#ifdef LIBXML_DEBUG_ENABLED
524 xmlDebugDumpString(stderr,
525 &reader->input->buffer->content[reader->cur]);
526#endif
527 fprintf(stderr, "\n");
528 }
529}
530#endif
531
541static int
542xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
543{
544 if (reader->entMax <= 0) {
545 reader->entMax = 10;
546 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
547 sizeof(reader->entTab[0]));
548 if (reader->entTab == NULL) {
549 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
550 return (0);
551 }
552 }
553 if (reader->entNr >= reader->entMax) {
554 reader->entMax *= 2;
555 reader->entTab =
556 (xmlNodePtr *) xmlRealloc(reader->entTab,
557 reader->entMax *
558 sizeof(reader->entTab[0]));
559 if (reader->entTab == NULL) {
560 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
561 return (0);
562 }
563 }
564 reader->entTab[reader->entNr] = value;
565 reader->ent = value;
566 return (reader->entNr++);
567}
568
577static xmlNodePtr
578xmlTextReaderEntPop(xmlTextReaderPtr reader)
579{
581
582 if (reader->entNr <= 0)
583 return (NULL);
584 reader->entNr--;
585 if (reader->entNr > 0)
586 reader->ent = reader->entTab[reader->entNr - 1];
587 else
588 reader->ent = NULL;
589 ret = reader->entTab[reader->entNr];
590 reader->entTab[reader->entNr] = NULL;
591 return (ret);
592}
593
602static void
603xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
604 const xmlChar **atts) {
606 xmlTextReaderPtr reader = ctxt->_private;
607
608#ifdef DEBUG_CALLBACKS
609 printf("xmlTextReaderStartElement(%s)\n", fullname);
610#endif
611 if ((reader != NULL) && (reader->startElement != NULL)) {
612 reader->startElement(ctx, fullname, atts);
613 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
614 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
615 (ctxt->input->cur[1] == '>'))
616 ctxt->node->extra = NODE_IS_EMPTY;
617 }
618 if (reader != NULL)
619 reader->state = XML_TEXTREADER_ELEMENT;
620}
621
629static void
630xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
632 xmlTextReaderPtr reader = ctxt->_private;
633
634#ifdef DEBUG_CALLBACKS
635 printf("xmlTextReaderEndElement(%s)\n", fullname);
636#endif
637 if ((reader != NULL) && (reader->endElement != NULL)) {
638 reader->endElement(ctx, fullname);
639 }
640}
641
657static void
658xmlTextReaderStartElementNs(void *ctx,
659 const xmlChar *localname,
660 const xmlChar *prefix,
661 const xmlChar *URI,
662 int nb_namespaces,
663 const xmlChar **namespaces,
664 int nb_attributes,
665 int nb_defaulted,
666 const xmlChar **attributes)
667{
669 xmlTextReaderPtr reader = ctxt->_private;
670
671#ifdef DEBUG_CALLBACKS
672 printf("xmlTextReaderStartElementNs(%s)\n", localname);
673#endif
674 if ((reader != NULL) && (reader->startElementNs != NULL)) {
675 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
676 namespaces, nb_attributes, nb_defaulted,
677 attributes);
678 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
679 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
680 (ctxt->input->cur[1] == '>'))
681 ctxt->node->extra = NODE_IS_EMPTY;
682 }
683 if (reader != NULL)
684 reader->state = XML_TEXTREADER_ELEMENT;
685}
686
696static void
697xmlTextReaderEndElementNs(void *ctx,
698 const xmlChar * localname,
699 const xmlChar * prefix,
700 const xmlChar * URI)
701{
703 xmlTextReaderPtr reader = ctxt->_private;
704
705#ifdef DEBUG_CALLBACKS
706 printf("xmlTextReaderEndElementNs(%s)\n", localname);
707#endif
708 if ((reader != NULL) && (reader->endElementNs != NULL)) {
709 reader->endElementNs(ctx, localname, prefix, URI);
710 }
711}
712
713
722static void
723xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
724{
726 xmlTextReaderPtr reader = ctxt->_private;
727
728#ifdef DEBUG_CALLBACKS
729 printf("xmlTextReaderCharacters()\n");
730#endif
731 if ((reader != NULL) && (reader->characters != NULL)) {
732 reader->characters(ctx, ch, len);
733 }
734}
735
744static void
745xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
746{
748 xmlTextReaderPtr reader = ctxt->_private;
749
750#ifdef DEBUG_CALLBACKS
751 printf("xmlTextReaderCDataBlock()\n");
752#endif
753 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
754 reader->cdataBlock(ctx, ch, len);
755 }
756}
757
767static int
768xmlTextReaderPushData(xmlTextReaderPtr reader) {
770 int val, s;
771 xmlTextReaderState oldstate;
772 int alloc;
773
774 if ((reader->input == NULL) || (reader->input->buffer == NULL))
775 return(-1);
776
777 oldstate = reader->state;
778 reader->state = XML_TEXTREADER_NONE;
779 inbuf = reader->input->buffer;
781
782 while (reader->state == XML_TEXTREADER_NONE) {
783 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
784 /*
785 * Refill the buffer unless we are at the end of the stream
786 */
787 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
788 val = xmlParserInputBufferRead(reader->input, 4096);
789 if ((val == 0) &&
791 if (xmlBufUse(inbuf) == reader->cur) {
792 reader->mode = XML_TEXTREADER_MODE_EOF;
793 reader->state = oldstate;
794 }
795 } else if (val < 0) {
796 reader->mode = XML_TEXTREADER_MODE_EOF;
797 reader->state = oldstate;
798 if ((oldstate != XML_TEXTREADER_START) ||
799 (reader->ctxt->myDoc != NULL))
800 return(val);
801 } else if (val == 0) {
802 /* mark the end of the stream and process the remains */
803 reader->mode = XML_TEXTREADER_MODE_EOF;
804 break;
805 }
806
807 } else
808 break;
809 }
810 /*
811 * parse by block of CHUNK_SIZE bytes, various tests show that
812 * it's the best tradeoff at least on a 1.2GH Duron
813 */
814 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
815 val = xmlParseChunk(reader->ctxt,
816 (const char *) xmlBufContent(inbuf) + reader->cur,
817 CHUNK_SIZE, 0);
818 reader->cur += CHUNK_SIZE;
819 if (val != 0)
820 reader->ctxt->wellFormed = 0;
821 if (reader->ctxt->wellFormed == 0)
822 break;
823 } else {
824 s = xmlBufUse(inbuf) - reader->cur;
825 val = xmlParseChunk(reader->ctxt,
826 (const char *) xmlBufContent(inbuf) + reader->cur,
827 s, 0);
828 reader->cur += s;
829 if (val != 0)
830 reader->ctxt->wellFormed = 0;
831 break;
832 }
833 }
834
835 /*
836 * Discard the consumed input when needed and possible
837 */
838 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
840 if ((reader->cur >= 4096) &&
841 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
842 val = xmlBufShrink(inbuf, reader->cur);
843 if (val >= 0) {
844 reader->cur -= val;
845 }
846 }
847 }
848 }
849
850 /*
851 * At the end of the stream signal that the work is done to the Push
852 * parser.
853 */
854 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
855 if (reader->state != XML_TEXTREADER_DONE) {
856 s = xmlBufUse(inbuf) - reader->cur;
857 val = xmlParseChunk(reader->ctxt,
858 (const char *) xmlBufContent(inbuf) + reader->cur,
859 s, 1);
860 reader->cur = xmlBufUse(inbuf);
861 reader->state = XML_TEXTREADER_DONE;
862 if (val != 0) {
863 if (reader->ctxt->wellFormed)
864 reader->ctxt->wellFormed = 0;
865 else
866 return(-1);
867 }
868 }
869 }
870 reader->state = oldstate;
871 if (reader->ctxt->wellFormed == 0) {
872 reader->mode = XML_TEXTREADER_MODE_EOF;
873 return(-1);
874 }
875
876 return(0);
877}
878
879#ifdef LIBXML_REGEXP_ENABLED
886static void
887xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
888 xmlNodePtr node = reader->node;
889
890#ifdef LIBXML_VALID_ENABLED
891 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
892 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
893 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
894 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
895 reader->ctxt->myDoc, node, node->name);
896 } else {
897 /* TODO use the BuildQName interface */
898 xmlChar *qname;
899
900 qname = xmlStrdup(node->ns->prefix);
901 qname = xmlStrcat(qname, BAD_CAST ":");
902 qname = xmlStrcat(qname, node->name);
903 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
904 reader->ctxt->myDoc, node, qname);
905 if (qname != NULL)
906 xmlFree(qname);
907 }
908 }
909#endif /* LIBXML_VALID_ENABLED */
910#ifdef LIBXML_SCHEMAS_ENABLED
911 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
912 (reader->rngValidCtxt != NULL)) {
913 int ret;
914
915 if (reader->rngFullNode != NULL) return;
916 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
917 reader->ctxt->myDoc,
918 node);
919 if (ret == 0) {
920 /*
921 * this element requires a full tree
922 */
923 node = xmlTextReaderExpand(reader);
924 if (node == NULL) {
925 ret = -1;
926 } else {
927 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
928 reader->ctxt->myDoc,
929 node);
930 reader->rngFullNode = node;
931 }
932 }
933 if (ret != 1)
934 reader->rngValidErrors++;
935 }
936#endif
937}
938
947static void
948xmlTextReaderValidateCData(xmlTextReaderPtr reader,
949 const xmlChar *data, int len) {
950#ifdef LIBXML_VALID_ENABLED
951 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
952 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
953 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
954 data, len);
955 }
956#endif /* LIBXML_VALID_ENABLED */
957#ifdef LIBXML_SCHEMAS_ENABLED
958 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
959 (reader->rngValidCtxt != NULL)) {
960 int ret;
961
962 if (reader->rngFullNode != NULL) return;
963 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
964 if (ret != 1)
965 reader->rngValidErrors++;
966 }
967#endif
968}
969
976static void
977xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
978 xmlNodePtr node = reader->node;
979
980#ifdef LIBXML_VALID_ENABLED
981 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
982 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
983 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
984 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
985 reader->ctxt->myDoc, node, node->name);
986 } else {
987 /* TODO use the BuildQName interface */
988 xmlChar *qname;
989
990 qname = xmlStrdup(node->ns->prefix);
991 qname = xmlStrcat(qname, BAD_CAST ":");
992 qname = xmlStrcat(qname, node->name);
993 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
994 reader->ctxt->myDoc, node, qname);
995 if (qname != NULL)
996 xmlFree(qname);
997 }
998 }
999#endif /* LIBXML_VALID_ENABLED */
1000#ifdef LIBXML_SCHEMAS_ENABLED
1001 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1002 (reader->rngValidCtxt != NULL)) {
1003 int ret;
1004
1005 if (reader->rngFullNode != NULL) {
1006 if (node == reader->rngFullNode)
1007 reader->rngFullNode = NULL;
1008 return;
1009 }
1010 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1011 reader->ctxt->myDoc,
1012 node);
1013 if (ret != 1)
1014 reader->rngValidErrors++;
1015 }
1016#endif
1017}
1018
1027static void
1028xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1029 xmlNodePtr oldnode = reader->node;
1030 xmlNodePtr node = reader->node;
1031
1032 do {
1033 if (node->type == XML_ENTITY_REF_NODE) {
1034 if ((node->children != NULL) &&
1035 (node->children->type == XML_ENTITY_DECL) &&
1036 (node->children->children != NULL)) {
1037 xmlTextReaderEntPush(reader, node);
1038 node = node->children->children;
1039 continue;
1040 } else {
1041 /*
1042 * The error has probably been raised already.
1043 */
1044 if (node == oldnode)
1045 break;
1046 goto skip_children;
1047 }
1048#ifdef LIBXML_REGEXP_ENABLED
1049 } else if (node->type == XML_ELEMENT_NODE) {
1050 reader->node = node;
1051 xmlTextReaderValidatePush(reader);
1052 } else if ((node->type == XML_TEXT_NODE) ||
1053 (node->type == XML_CDATA_SECTION_NODE)) {
1054 xmlTextReaderValidateCData(reader, node->content,
1055 xmlStrlen(node->content));
1056#endif
1057 }
1058
1059 /*
1060 * go to next node
1061 */
1062 if (node->children != NULL) {
1063 node = node->children;
1064 continue;
1065 } else if (node->type == XML_ELEMENT_NODE) {
1066 xmlTextReaderValidatePop(reader);
1067 }
1068skip_children:
1069 if (node->next != NULL) {
1070 node = node->next;
1071 continue;
1072 }
1073 do {
1074 node = node->parent;
1075 if (node->type == XML_ELEMENT_NODE) {
1076 xmlNodePtr tmp;
1077 if (reader->entNr == 0) {
1078 while ((tmp = node->last) != NULL) {
1079 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1080 xmlUnlinkNode(tmp);
1081 xmlTextReaderFreeNode(reader, tmp);
1082 } else
1083 break;
1084 }
1085 }
1086 reader->node = node;
1087 xmlTextReaderValidatePop(reader);
1088 }
1089 if ((node->type == XML_ENTITY_DECL) &&
1090 (reader->ent != NULL) && (reader->ent->children == node)) {
1091 node = xmlTextReaderEntPop(reader);
1092 }
1093 if (node == oldnode)
1094 break;
1095 if (node->next != NULL) {
1096 node = node->next;
1097 break;
1098 }
1099 } while ((node != NULL) && (node != oldnode));
1100 } while ((node != NULL) && (node != oldnode));
1101 reader->node = oldnode;
1102}
1103#endif /* LIBXML_REGEXP_ENABLED */
1104
1105
1114static xmlNodePtr
1115xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1116 if (cur == NULL) return(NULL) ; /* ERROR */
1117 if (cur->next != NULL) return(cur->next) ;
1118 do {
1119 cur = cur->parent;
1120 if (cur == NULL) break;
1121 if (cur->next != NULL) return(cur->next);
1122 } while (cur != NULL);
1123 return(cur);
1124}
1125
1137static int
1138xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1139 int val;
1140
1141 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1142 return(-1);
1143 do {
1144 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1145
1146 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1147 return(1);
1148 if (reader->ctxt->nodeNr < reader->depth)
1149 return(1);
1150 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1151 return(1);
1152 val = xmlTextReaderPushData(reader);
1153 if (val < 0){
1154 reader->mode = XML_TEXTREADER_MODE_ERROR;
1155 return(-1);
1156 }
1157 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1158 return(1);
1159}
1160
1171static xmlChar *
1172xmlTextReaderCollectSiblings(xmlNodePtr node)
1173{
1175 xmlChar *ret;
1176
1177 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1178 return(NULL);
1179
1181 if (buffer == NULL)
1182 return NULL;
1184
1185 for ( ; node != NULL; node = node->next) {
1186 switch (node->type) {
1187 case XML_TEXT_NODE:
1189 xmlBufferCat(buffer, node->content);
1190 break;
1191 case XML_ELEMENT_NODE: {
1192 xmlChar *tmp;
1193
1194 tmp = xmlTextReaderCollectSiblings(node->children);
1195 xmlBufferCat(buffer, tmp);
1196 xmlFree(tmp);
1197 break;
1198 }
1199 default:
1200 break;
1201 }
1202 }
1203 ret = buffer->content;
1204 buffer->content = NULL;
1206 return(ret);
1207}
1208
1219int
1220xmlTextReaderRead(xmlTextReaderPtr reader) {
1221 int val, olddepth = 0;
1222 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1223 xmlNodePtr oldnode = NULL;
1224
1225
1226 if (reader == NULL)
1227 return(-1);
1228 reader->curnode = NULL;
1229 if (reader->doc != NULL)
1230 return(xmlTextReaderReadTree(reader));
1231 if (reader->ctxt == NULL)
1232 return(-1);
1233
1234#ifdef DEBUG_READER
1235 fprintf(stderr, "\nREAD ");
1236 DUMP_READER
1237#endif
1238 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1239 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1240 /*
1241 * Initial state
1242 */
1243 do {
1244 val = xmlTextReaderPushData(reader);
1245 if (val < 0){
1246 reader->mode = XML_TEXTREADER_MODE_ERROR;
1247 reader->state = XML_TEXTREADER_ERROR;
1248 return(-1);
1249 }
1250 } while ((reader->ctxt->node == NULL) &&
1251 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1252 (reader->state != XML_TEXTREADER_DONE)));
1253 if (reader->ctxt->node == NULL) {
1254 if (reader->ctxt->myDoc != NULL) {
1255 reader->node = reader->ctxt->myDoc->children;
1256 }
1257 if (reader->node == NULL){
1258 reader->mode = XML_TEXTREADER_MODE_ERROR;
1259 reader->state = XML_TEXTREADER_ERROR;
1260 return(-1);
1261 }
1262 reader->state = XML_TEXTREADER_ELEMENT;
1263 } else {
1264 if (reader->ctxt->myDoc != NULL) {
1265 reader->node = reader->ctxt->myDoc->children;
1266 }
1267 if (reader->node == NULL)
1268 reader->node = reader->ctxt->nodeTab[0];
1269 reader->state = XML_TEXTREADER_ELEMENT;
1270 }
1271 reader->depth = 0;
1272 reader->ctxt->parseMode = XML_PARSE_READER;
1273 goto node_found;
1274 }
1275 oldstate = reader->state;
1276 olddepth = reader->ctxt->nodeNr;
1277 oldnode = reader->node;
1278
1279get_next_node:
1280 if (reader->node == NULL) {
1281 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1282 return(0);
1283 else
1284 return(-1);
1285 }
1286
1287 /*
1288 * If we are not backtracking on ancestors or examined nodes,
1289 * that the parser didn't finished or that we aren't at the end
1290 * of stream, continue processing.
1291 */
1292 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1293 (reader->ctxt->nodeNr == olddepth) &&
1294 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1295 (reader->node->children == NULL) ||
1296 (reader->node->type == XML_ENTITY_REF_NODE) ||
1297 ((reader->node->children != NULL) &&
1298 (reader->node->children->type == XML_TEXT_NODE) &&
1299 (reader->node->children->next == NULL)) ||
1300 (reader->node->type == XML_DTD_NODE) ||
1301 (reader->node->type == XML_DOCUMENT_NODE) ||
1302 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1303 ((reader->ctxt->node == NULL) ||
1304 (reader->ctxt->node == reader->node) ||
1305 (reader->ctxt->node == reader->node->parent)) &&
1306 (reader->ctxt->instate != XML_PARSER_EOF)) {
1307 val = xmlTextReaderPushData(reader);
1308 if (val < 0){
1309 reader->mode = XML_TEXTREADER_MODE_ERROR;
1310 reader->state = XML_TEXTREADER_ERROR;
1311 return(-1);
1312 }
1313 if (reader->node == NULL)
1314 goto node_end;
1315 }
1316 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1317 if ((reader->node->children != NULL) &&
1318 (reader->node->type != XML_ENTITY_REF_NODE) &&
1319 (reader->node->type != XML_XINCLUDE_START) &&
1320 (reader->node->type != XML_DTD_NODE)) {
1321 reader->node = reader->node->children;
1322 reader->depth++;
1323 reader->state = XML_TEXTREADER_ELEMENT;
1324 goto node_found;
1325 }
1326 }
1327 if (reader->node->next != NULL) {
1328 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1329 (reader->node->type == XML_ELEMENT_NODE) &&
1330 (reader->node->children == NULL) &&
1331 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1333 && (reader->in_xinclude <= 0)
1334#endif
1335 ) {
1336 reader->state = XML_TEXTREADER_END;
1337 goto node_found;
1338 }
1339#ifdef LIBXML_REGEXP_ENABLED
1340 if ((reader->validate) &&
1341 (reader->node->type == XML_ELEMENT_NODE))
1342 xmlTextReaderValidatePop(reader);
1343#endif /* LIBXML_REGEXP_ENABLED */
1344 if ((reader->preserves > 0) &&
1345 (reader->node->extra & NODE_IS_SPRESERVED))
1346 reader->preserves--;
1347 reader->node = reader->node->next;
1348 reader->state = XML_TEXTREADER_ELEMENT;
1349
1350 /*
1351 * Cleanup of the old node
1352 */
1353 if ((reader->preserves == 0) &&
1355 (reader->in_xinclude == 0) &&
1356#endif
1357 (reader->entNr == 0) &&
1358 (reader->node->prev != NULL) &&
1359 (reader->node->prev->type != XML_DTD_NODE)) {
1360 xmlNodePtr tmp = reader->node->prev;
1361 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1362 if (oldnode == tmp)
1363 oldnode = NULL;
1364 xmlUnlinkNode(tmp);
1365 xmlTextReaderFreeNode(reader, tmp);
1366 }
1367 }
1368
1369 goto node_found;
1370 }
1371 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1372 (reader->node->type == XML_ELEMENT_NODE) &&
1373 (reader->node->children == NULL) &&
1374 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1375 reader->state = XML_TEXTREADER_END;
1376 goto node_found;
1377 }
1378#ifdef LIBXML_REGEXP_ENABLED
1379 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1380 xmlTextReaderValidatePop(reader);
1381#endif /* LIBXML_REGEXP_ENABLED */
1382 if ((reader->preserves > 0) &&
1383 (reader->node->extra & NODE_IS_SPRESERVED))
1384 reader->preserves--;
1385 reader->node = reader->node->parent;
1386 if ((reader->node == NULL) ||
1387 (reader->node->type == XML_DOCUMENT_NODE) ||
1388 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1389 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1390 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1391 reader->state = XML_TEXTREADER_DONE;
1392 if (val != 0)
1393 return(-1);
1394 }
1395 reader->node = NULL;
1396 reader->depth = -1;
1397
1398 /*
1399 * Cleanup of the old node
1400 */
1401 if ((oldnode != NULL) && (reader->preserves == 0) &&
1403 (reader->in_xinclude == 0) &&
1404#endif
1405 (reader->entNr == 0) &&
1406 (oldnode->type != XML_DTD_NODE) &&
1407 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1408 xmlUnlinkNode(oldnode);
1409 xmlTextReaderFreeNode(reader, oldnode);
1410 }
1411
1412 goto node_end;
1413 }
1414 if ((reader->preserves == 0) &&
1416 (reader->in_xinclude == 0) &&
1417#endif
1418 (reader->entNr == 0) &&
1419 (reader->node->last != NULL) &&
1420 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1421 xmlNodePtr tmp = reader->node->last;
1422 xmlUnlinkNode(tmp);
1423 xmlTextReaderFreeNode(reader, tmp);
1424 }
1425 reader->depth--;
1426 reader->state = XML_TEXTREADER_BACKTRACK;
1427
1428node_found:
1429 DUMP_READER
1430
1431 /*
1432 * If we are in the middle of a piece of CDATA make sure it's finished
1433 */
1434 if ((reader->node != NULL) &&
1435 (reader->node->next == NULL) &&
1436 ((reader->node->type == XML_TEXT_NODE) ||
1437 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1438 if (xmlTextReaderExpand(reader) == NULL)
1439 return -1;
1440 }
1441
1442#ifdef LIBXML_XINCLUDE_ENABLED
1443 /*
1444 * Handle XInclude if asked for
1445 */
1446 if ((reader->xinclude) && (reader->in_xinclude == 0) &&
1447 (reader->node != NULL) &&
1448 (reader->node->type == XML_ELEMENT_NODE) &&
1449 (reader->node->ns != NULL) &&
1450 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1451 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1452 if (reader->xincctxt == NULL) {
1453 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1454 xmlXIncludeSetFlags(reader->xincctxt,
1455 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1456 }
1457 /*
1458 * expand that node and process it
1459 */
1460 if (xmlTextReaderExpand(reader) == NULL)
1461 return -1;
1462 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1463 }
1464 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1465 reader->in_xinclude++;
1466 goto get_next_node;
1467 }
1468 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1469 reader->in_xinclude--;
1470 goto get_next_node;
1471 }
1472#endif
1473 /*
1474 * Handle entities enter and exit when in entity replacement mode
1475 */
1476 if ((reader->node != NULL) &&
1477 (reader->node->type == XML_ENTITY_REF_NODE) &&
1478 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1479 if ((reader->node->children != NULL) &&
1480 (reader->node->children->type == XML_ENTITY_DECL) &&
1481 (reader->node->children->children != NULL)) {
1482 xmlTextReaderEntPush(reader, reader->node);
1483 reader->node = reader->node->children->children;
1484 }
1485#ifdef LIBXML_REGEXP_ENABLED
1486 } else if ((reader->node != NULL) &&
1487 (reader->node->type == XML_ENTITY_REF_NODE) &&
1488 (reader->ctxt != NULL) && (reader->validate)) {
1489 xmlTextReaderValidateEntity(reader);
1490#endif /* LIBXML_REGEXP_ENABLED */
1491 }
1492 if ((reader->node != NULL) &&
1493 (reader->node->type == XML_ENTITY_DECL) &&
1494 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1495 reader->node = xmlTextReaderEntPop(reader);
1496 reader->depth++;
1497 goto get_next_node;
1498 }
1499#ifdef LIBXML_REGEXP_ENABLED
1500 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1501 xmlNodePtr node = reader->node;
1502
1503 if ((node->type == XML_ELEMENT_NODE) &&
1504 ((reader->state != XML_TEXTREADER_END) &&
1505 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1506 xmlTextReaderValidatePush(reader);
1507 } else if ((node->type == XML_TEXT_NODE) ||
1508 (node->type == XML_CDATA_SECTION_NODE)) {
1509 xmlTextReaderValidateCData(reader, node->content,
1510 xmlStrlen(node->content));
1511 }
1512 }
1513#endif /* LIBXML_REGEXP_ENABLED */
1514#ifdef LIBXML_PATTERN_ENABLED
1515 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1516 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1517 int i;
1518 for (i = 0;i < reader->patternNr;i++) {
1519 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1520 xmlTextReaderPreserve(reader);
1521 break;
1522 }
1523 }
1524 }
1525#endif /* LIBXML_PATTERN_ENABLED */
1526#ifdef LIBXML_SCHEMAS_ENABLED
1527 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1528 (reader->xsdValidErrors == 0) &&
1529 (reader->xsdValidCtxt != NULL)) {
1530 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1531 }
1532#endif /* LIBXML_PATTERN_ENABLED */
1533 return(1);
1534node_end:
1535 reader->state = XML_TEXTREADER_DONE;
1536 return(0);
1537}
1538
1547int
1548xmlTextReaderReadState(xmlTextReaderPtr reader) {
1549 if (reader == NULL)
1550 return(-1);
1551 return(reader->mode);
1552}
1553
1565xmlTextReaderExpand(xmlTextReaderPtr reader) {
1566 if ((reader == NULL) || (reader->node == NULL))
1567 return(NULL);
1568 if (reader->doc != NULL)
1569 return(reader->node);
1570 if (reader->ctxt == NULL)
1571 return(NULL);
1572 if (xmlTextReaderDoExpand(reader) < 0)
1573 return(NULL);
1574 return(reader->node);
1575}
1576
1587int
1588xmlTextReaderNext(xmlTextReaderPtr reader) {
1589 int ret;
1591
1592 if (reader == NULL)
1593 return(-1);
1594 if (reader->doc != NULL)
1595 return(xmlTextReaderNextTree(reader));
1596 cur = reader->node;
1597 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1598 return(xmlTextReaderRead(reader));
1599 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1600 return(xmlTextReaderRead(reader));
1601 if (cur->extra & NODE_IS_EMPTY)
1602 return(xmlTextReaderRead(reader));
1603 do {
1604 ret = xmlTextReaderRead(reader);
1605 if (ret != 1)
1606 return(ret);
1607 } while (reader->node != cur);
1608 return(xmlTextReaderRead(reader));
1609}
1610
1611#ifdef LIBXML_WRITER_ENABLED
1622xmlChar *
1623xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1624{
1625 xmlChar *resbuf;
1626 xmlNodePtr node, cur_node;
1627 xmlBufferPtr buff, buff2;
1628 xmlDocPtr doc;
1629
1630 if (xmlTextReaderExpand(reader) == NULL) {
1631 return NULL;
1632 }
1633 doc = reader->node->doc;
1635 if (buff == NULL)
1636 return NULL;
1638 for (cur_node = reader->node->children; cur_node != NULL;
1639 cur_node = cur_node->next) {
1640 /* XXX: Why is the node copied? */
1641 node = xmlDocCopyNode(cur_node, doc, 1);
1642 /* XXX: Why do we need a second buffer? */
1643 buff2 = xmlBufferCreate();
1645 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1647 xmlBufferFree(buff2);
1649 return NULL;
1650 }
1651 xmlBufferCat(buff, buff2->content);
1653 xmlBufferFree(buff2);
1654 }
1655 resbuf = buff->content;
1656 buff->content = NULL;
1657
1659 return resbuf;
1660}
1661#endif
1662
1663#ifdef LIBXML_WRITER_ENABLED
1674xmlChar *
1675xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1676{
1677 xmlChar *resbuf;
1680 xmlDocPtr doc;
1681
1682 if (xmlTextReaderExpand(reader) == NULL) {
1683 return NULL;
1684 }
1685 node = reader->node;
1686 doc = node->doc;
1687 /* XXX: Why is the node copied? */
1688 if (node->type == XML_DTD_NODE) {
1689 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1690 } else {
1691 node = xmlDocCopyNode(node, doc, 1);
1692 }
1695 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1698 return NULL;
1699 }
1700
1701 resbuf = buff->content;
1702 buff->content = NULL;
1703
1706 return resbuf;
1707}
1708#endif
1709
1720xmlChar *
1721xmlTextReaderReadString(xmlTextReaderPtr reader)
1722{
1724
1725 if ((reader == NULL) || (reader->node == NULL))
1726 return(NULL);
1727
1728 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1729 switch (node->type) {
1730 case XML_TEXT_NODE:
1731 if (node->content != NULL)
1732 return(xmlStrdup(node->content));
1733 break;
1734 case XML_ELEMENT_NODE:
1735 if (xmlTextReaderDoExpand(reader) != -1) {
1736 return xmlTextReaderCollectSiblings(node->children);
1737 }
1738 break;
1739 case XML_ATTRIBUTE_NODE:
1740 TODO
1741 break;
1742 default:
1743 break;
1744 }
1745 return(NULL);
1746}
1747
1748#if 0
1763int
1764xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1765 unsigned char *array ATTRIBUTE_UNUSED,
1767 int len ATTRIBUTE_UNUSED) {
1768 if ((reader == NULL) || (reader->ctxt == NULL))
1769 return(-1);
1770 if (reader->ctxt->wellFormed != 1)
1771 return(-1);
1772
1773 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1774 return(0);
1775 TODO
1776 return(0);
1777}
1778
1793int
1794xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1795 unsigned char *array ATTRIBUTE_UNUSED,
1797 int len ATTRIBUTE_UNUSED) {
1798 if ((reader == NULL) || (reader->ctxt == NULL))
1799 return(-1);
1800 if (reader->ctxt->wellFormed != 1)
1801 return(-1);
1802
1803 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1804 return(0);
1805 TODO
1806 return(0);
1807}
1808#endif
1809
1810/************************************************************************
1811 * *
1812 * Operating on a preparsed tree *
1813 * *
1814 ************************************************************************/
1815static int
1816xmlTextReaderNextTree(xmlTextReaderPtr reader)
1817{
1818 if (reader == NULL)
1819 return(-1);
1820
1821 if (reader->state == XML_TEXTREADER_END)
1822 return(0);
1823
1824 if (reader->node == NULL) {
1825 if (reader->doc->children == NULL) {
1826 reader->state = XML_TEXTREADER_END;
1827 return(0);
1828 }
1829
1830 reader->node = reader->doc->children;
1831 reader->state = XML_TEXTREADER_START;
1832 return(1);
1833 }
1834
1835 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1836 /* Here removed traversal to child, because we want to skip the subtree,
1837 replace with traversal to sibling to skip subtree */
1838 if (reader->node->next != 0) {
1839 /* Move to sibling if present,skipping sub-tree */
1840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1843 }
1844
1845 /* if reader->node->next is NULL mean no subtree for current node,
1846 so need to move to sibling of parent node if present */
1847 reader->state = XML_TEXTREADER_BACKTRACK;
1848 /* This will move to parent if present */
1849 xmlTextReaderRead(reader);
1850 }
1851
1852 if (reader->node->next != 0) {
1853 reader->node = reader->node->next;
1854 reader->state = XML_TEXTREADER_START;
1855 return(1);
1856 }
1857
1858 if (reader->node->parent != 0) {
1859 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1860 reader->state = XML_TEXTREADER_END;
1861 return(0);
1862 }
1863
1864 reader->node = reader->node->parent;
1865 reader->depth--;
1866 reader->state = XML_TEXTREADER_BACKTRACK;
1867 /* Repeat process to move to sibling of parent node if present */
1868 xmlTextReaderNextTree(reader);
1869 }
1870
1871 reader->state = XML_TEXTREADER_END;
1872
1873 return(1);
1874}
1875
1886static int
1887xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1888 if (reader->state == XML_TEXTREADER_END)
1889 return(0);
1890
1891next_node:
1892 if (reader->node == NULL) {
1893 if (reader->doc->children == NULL) {
1894 reader->state = XML_TEXTREADER_END;
1895 return(0);
1896 }
1897
1898 reader->node = reader->doc->children;
1899 reader->state = XML_TEXTREADER_START;
1900 goto found_node;
1901 }
1902
1903 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1904 (reader->node->type != XML_DTD_NODE) &&
1905 (reader->node->type != XML_XINCLUDE_START) &&
1906 (reader->node->type != XML_ENTITY_REF_NODE)) {
1907 if (reader->node->children != NULL) {
1908 reader->node = reader->node->children;
1909 reader->depth++;
1910 reader->state = XML_TEXTREADER_START;
1911 goto found_node;
1912 }
1913
1914 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1915 reader->state = XML_TEXTREADER_BACKTRACK;
1916 goto found_node;
1917 }
1918 }
1919
1920 if (reader->node->next != NULL) {
1921 reader->node = reader->node->next;
1922 reader->state = XML_TEXTREADER_START;
1923 goto found_node;
1924 }
1925
1926 if (reader->node->parent != NULL) {
1927 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1928 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1929 reader->state = XML_TEXTREADER_END;
1930 return(0);
1931 }
1932
1933 reader->node = reader->node->parent;
1934 reader->depth--;
1935 reader->state = XML_TEXTREADER_BACKTRACK;
1936 goto found_node;
1937 }
1938
1939 reader->state = XML_TEXTREADER_END;
1940
1941found_node:
1942 if ((reader->node->type == XML_XINCLUDE_START) ||
1943 (reader->node->type == XML_XINCLUDE_END))
1944 goto next_node;
1945
1946 return(1);
1947}
1948
1960int
1961xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1962 if (reader == NULL)
1963 return(-1);
1964 if (reader->doc == NULL) {
1965 /* TODO */
1966 return(-1);
1967 }
1968
1969 if (reader->state == XML_TEXTREADER_END)
1970 return(0);
1971
1972 if (reader->node == NULL)
1973 return(xmlTextReaderNextTree(reader));
1974
1975 if (reader->node->next != NULL) {
1976 reader->node = reader->node->next;
1977 reader->state = XML_TEXTREADER_START;
1978 return(1);
1979 }
1980
1981 return(0);
1982}
1983
1984/************************************************************************
1985 * *
1986 * Constructor and destructors *
1987 * *
1988 ************************************************************************/
1998xmlTextReaderPtr
1999xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2000 xmlTextReaderPtr ret;
2001
2002 if (input == NULL)
2003 return(NULL);
2004 ret = xmlMalloc(sizeof(xmlTextReader));
2005 if (ret == NULL) {
2007 "xmlNewTextReader : malloc failed\n");
2008 return(NULL);
2009 }
2010 memset(ret, 0, sizeof(xmlTextReader));
2011 ret->doc = NULL;
2012 ret->entTab = NULL;
2013 ret->entMax = 0;
2014 ret->entNr = 0;
2015 ret->input = input;
2016 ret->buffer = xmlBufCreateSize(100);
2017 if (ret->buffer == NULL) {
2018 xmlFree(ret);
2020 "xmlNewTextReader : malloc failed\n");
2021 return(NULL);
2022 }
2023 /* no operation on a reader should require a huge buffer */
2026 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2027 if (ret->sax == NULL) {
2028 xmlBufFree(ret->buffer);
2029 xmlFree(ret);
2031 "xmlNewTextReader : malloc failed\n");
2032 return(NULL);
2033 }
2034 xmlSAXVersion(ret->sax, 2);
2035 ret->startElement = ret->sax->startElement;
2036 ret->sax->startElement = xmlTextReaderStartElement;
2037 ret->endElement = ret->sax->endElement;
2038 ret->sax->endElement = xmlTextReaderEndElement;
2039#ifdef LIBXML_SAX1_ENABLED
2040 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2041#endif /* LIBXML_SAX1_ENABLED */
2042 ret->startElementNs = ret->sax->startElementNs;
2043 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2044 ret->endElementNs = ret->sax->endElementNs;
2045 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2046#ifdef LIBXML_SAX1_ENABLED
2047 } else {
2048 ret->startElementNs = NULL;
2049 ret->endElementNs = NULL;
2050 }
2051#endif /* LIBXML_SAX1_ENABLED */
2052 ret->characters = ret->sax->characters;
2053 ret->sax->characters = xmlTextReaderCharacters;
2054 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2055 ret->cdataBlock = ret->sax->cdataBlock;
2056 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2057
2058 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2059 ret->node = NULL;
2060 ret->curnode = NULL;
2061 if (xmlBufUse(ret->input->buffer) < 4) {
2063 }
2064 if (xmlBufUse(ret->input->buffer) >= 4) {
2065 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2066 (const char *) xmlBufContent(ret->input->buffer),
2067 4, URI);
2068 ret->base = 0;
2069 ret->cur = 4;
2070 } else {
2071 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2072 ret->base = 0;
2073 ret->cur = 0;
2074 }
2075
2076 if (ret->ctxt == NULL) {
2078 "xmlNewTextReader : malloc failed\n");
2079 xmlBufFree(ret->buffer);
2080 xmlFree(ret->sax);
2081 xmlFree(ret);
2082 return(NULL);
2083 }
2084 ret->ctxt->parseMode = XML_PARSE_READER;
2085 ret->ctxt->_private = ret;
2086 ret->ctxt->linenumbers = 1;
2087 ret->ctxt->dictNames = 1;
2088 ret->allocs = XML_TEXTREADER_CTXT;
2089 /*
2090 * use the parser dictionary to allocate all elements and attributes names
2091 */
2092 ret->ctxt->docdict = 1;
2093 ret->dict = ret->ctxt->dict;
2094#ifdef LIBXML_XINCLUDE_ENABLED
2095 ret->xinclude = 0;
2096#endif
2097#ifdef LIBXML_PATTERN_ENABLED
2098 ret->patternMax = 0;
2099 ret->patternTab = NULL;
2100#endif
2101 return(ret);
2102}
2103
2112xmlTextReaderPtr
2113xmlNewTextReaderFilename(const char *URI) {
2115 xmlTextReaderPtr ret;
2116 char *directory = NULL;
2117
2119 if (input == NULL)
2120 return(NULL);
2121 ret = xmlNewTextReader(input, URI);
2122 if (ret == NULL) {
2124 return(NULL);
2125 }
2126 ret->allocs |= XML_TEXTREADER_INPUT;
2127 if (ret->ctxt->directory == NULL)
2129 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2130 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2131 if (directory != NULL)
2133 return(ret);
2134}
2135
2142void
2143xmlFreeTextReader(xmlTextReaderPtr reader) {
2144 if (reader == NULL)
2145 return;
2146#ifdef LIBXML_SCHEMAS_ENABLED
2147 if (reader->rngSchemas != NULL) {
2148 xmlRelaxNGFree(reader->rngSchemas);
2149 reader->rngSchemas = NULL;
2150 }
2151 if (reader->rngValidCtxt != NULL) {
2152 if (! reader->rngPreserveCtxt)
2153 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2154 reader->rngValidCtxt = NULL;
2155 }
2156 if (reader->xsdPlug != NULL) {
2157 xmlSchemaSAXUnplug(reader->xsdPlug);
2158 reader->xsdPlug = NULL;
2159 }
2160 if (reader->xsdValidCtxt != NULL) {
2161 if (! reader->xsdPreserveCtxt)
2162 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2163 reader->xsdValidCtxt = NULL;
2164 }
2165 if (reader->xsdSchemas != NULL) {
2166 xmlSchemaFree(reader->xsdSchemas);
2167 reader->xsdSchemas = NULL;
2168 }
2169#endif
2170#ifdef LIBXML_XINCLUDE_ENABLED
2171 if (reader->xincctxt != NULL)
2172 xmlXIncludeFreeContext(reader->xincctxt);
2173#endif
2174#ifdef LIBXML_PATTERN_ENABLED
2175 if (reader->patternTab != NULL) {
2176 int i;
2177 for (i = 0;i < reader->patternNr;i++) {
2178 if (reader->patternTab[i] != NULL)
2179 xmlFreePattern(reader->patternTab[i]);
2180 }
2181 xmlFree(reader->patternTab);
2182 }
2183#endif
2184 if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
2185 xmlTextReaderClose(reader);
2186 if (reader->ctxt != NULL) {
2187 if (reader->dict == reader->ctxt->dict)
2188 reader->dict = NULL;
2189 if (reader->allocs & XML_TEXTREADER_CTXT)
2191 }
2192 if (reader->sax != NULL)
2193 xmlFree(reader->sax);
2194 if (reader->buffer != NULL)
2195 xmlBufFree(reader->buffer);
2196 if (reader->entTab != NULL)
2197 xmlFree(reader->entTab);
2198 if (reader->dict != NULL)
2199 xmlDictFree(reader->dict);
2200 xmlFree(reader);
2201}
2202
2203/************************************************************************
2204 * *
2205 * Methods for XmlTextReader *
2206 * *
2207 ************************************************************************/
2217int
2218xmlTextReaderClose(xmlTextReaderPtr reader) {
2219 if (reader == NULL)
2220 return(-1);
2221 reader->node = NULL;
2222 reader->curnode = NULL;
2223 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2224 if (reader->faketext != NULL) {
2225 xmlFreeNode(reader->faketext);
2226 reader->faketext = NULL;
2227 }
2228 if (reader->ctxt != NULL) {
2229#ifdef LIBXML_VALID_ENABLED
2230 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2231 (reader->ctxt->vctxt.vstateMax > 0)){
2232#ifdef LIBXML_REGEXP_ENABLED
2233 while (reader->ctxt->vctxt.vstateNr > 0)
2234 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2235#endif /* LIBXML_REGEXP_ENABLED */
2236 xmlFree(reader->ctxt->vctxt.vstateTab);
2237 reader->ctxt->vctxt.vstateTab = NULL;
2238 reader->ctxt->vctxt.vstateMax = 0;
2239 }
2240#endif /* LIBXML_VALID_ENABLED */
2241 xmlStopParser(reader->ctxt);
2242 if (reader->ctxt->myDoc != NULL) {
2243 if (reader->preserve == 0)
2244 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2245 reader->ctxt->myDoc = NULL;
2246 }
2247 }
2248 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2250 reader->allocs -= XML_TEXTREADER_INPUT;
2251 }
2252 return(0);
2253}
2254
2266xmlChar *
2267xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2268 xmlChar *ret;
2269 int i;
2271 xmlNsPtr ns;
2272
2273 if (reader == NULL)
2274 return(NULL);
2275 if (reader->node == NULL)
2276 return(NULL);
2277 if (reader->curnode != NULL)
2278 return(NULL);
2279 /* TODO: handle the xmlDecl */
2280 if (reader->node->type != XML_ELEMENT_NODE)
2281 return(NULL);
2282
2283 ns = reader->node->nsDef;
2284 for (i = 0;(i < no) && (ns != NULL);i++) {
2285 ns = ns->next;
2286 }
2287 if (ns != NULL)
2288 return(xmlStrdup(ns->href));
2289
2290 cur = reader->node->properties;
2291 if (cur == NULL)
2292 return(NULL);
2293 for (;i < no;i++) {
2294 cur = cur->next;
2295 if (cur == NULL)
2296 return(NULL);
2297 }
2298 /* TODO walk the DTD if present */
2299
2300 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2301 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2302 return(ret);
2303}
2304
2315xmlChar *
2316xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2317 xmlChar *prefix = NULL;
2318 xmlChar *localname;
2319 xmlNsPtr ns;
2320 xmlChar *ret = NULL;
2321
2322 if ((reader == NULL) || (name == NULL))
2323 return(NULL);
2324 if (reader->node == NULL)
2325 return(NULL);
2326 if (reader->curnode != NULL)
2327 return(NULL);
2328
2329 /* TODO: handle the xmlDecl */
2330 if (reader->node->type != XML_ELEMENT_NODE)
2331 return(NULL);
2332
2333 localname = xmlSplitQName2(name, &prefix);
2334 if (localname == NULL) {
2335 /*
2336 * Namespace default decl
2337 */
2338 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2339 ns = reader->node->nsDef;
2340 while (ns != NULL) {
2341 if (ns->prefix == NULL) {
2342 return(xmlStrdup(ns->href));
2343 }
2344 ns = ns->next;
2345 }
2346 return NULL;
2347 }
2348 return(xmlGetNoNsProp(reader->node, name));
2349 }
2350
2351 /*
2352 * Namespace default decl
2353 */
2354 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2355 ns = reader->node->nsDef;
2356 while (ns != NULL) {
2357 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2358 ret = xmlStrdup(ns->href);
2359 break;
2360 }
2361 ns = ns->next;
2362 }
2363 } else {
2364 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2365 if (ns != NULL)
2366 ret = xmlGetNsProp(reader->node, localname, ns->href);
2367 }
2368
2369 xmlFree(localname);
2370 if (prefix != NULL)
2371 xmlFree(prefix);
2372 return(ret);
2373}
2374
2375
2387xmlChar *
2388xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2389 const xmlChar *namespaceURI) {
2390 xmlChar *prefix = NULL;
2391 xmlNsPtr ns;
2392
2393 if ((reader == NULL) || (localName == NULL))
2394 return(NULL);
2395 if (reader->node == NULL)
2396 return(NULL);
2397 if (reader->curnode != NULL)
2398 return(NULL);
2399
2400 /* TODO: handle the xmlDecl */
2401 if (reader->node->type != XML_ELEMENT_NODE)
2402 return(NULL);
2403
2404 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2405 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2406 prefix = BAD_CAST localName;
2407 }
2408 ns = reader->node->nsDef;
2409 while (ns != NULL) {
2410 if ((prefix == NULL && ns->prefix == NULL) ||
2411 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2412 return xmlStrdup(ns->href);
2413 }
2414 ns = ns->next;
2415 }
2416 return NULL;
2417 }
2418
2419 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2420}
2421
2438xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2440
2441 if (reader == NULL)
2442 return(NULL);
2443 if (reader->node == NULL)
2444 return(NULL);
2445
2446 reader->node = NULL;
2447 reader->curnode = NULL;
2448 reader->mode = XML_TEXTREADER_MODE_EOF;
2449 if (reader->ctxt != NULL) {
2450 xmlStopParser(reader->ctxt);
2451 if (reader->ctxt->myDoc != NULL) {
2452 if (reader->preserve == 0)
2453 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2454 reader->ctxt->myDoc = NULL;
2455 }
2456 }
2457 if (reader->allocs & XML_TEXTREADER_INPUT) {
2458 ret = reader->input;
2459 reader->input = NULL;
2460 reader->allocs -= XML_TEXTREADER_INPUT;
2461 } else {
2462 /*
2463 * Hum, one may need to duplicate the data structure because
2464 * without reference counting the input may be freed twice:
2465 * - by the layer which allocated it.
2466 * - by the layer to which would have been returned to.
2467 */
2468 TODO
2469 return(NULL);
2470 }
2471 return(ret);
2472}
2473
2485xmlChar *
2486xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2487 xmlNsPtr ns;
2488
2489 if (reader == NULL)
2490 return(NULL);
2491 if (reader->node == NULL)
2492 return(NULL);
2493
2494 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2495 if (ns == NULL)
2496 return(NULL);
2497 return(xmlStrdup(ns->href));
2498}
2499
2511int
2512xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2513 int i;
2515 xmlNsPtr ns;
2516
2517 if (reader == NULL)
2518 return(-1);
2519 if (reader->node == NULL)
2520 return(-1);
2521 /* TODO: handle the xmlDecl */
2522 if (reader->node->type != XML_ELEMENT_NODE)
2523 return(-1);
2524
2525 reader->curnode = NULL;
2526
2527 ns = reader->node->nsDef;
2528 for (i = 0;(i < no) && (ns != NULL);i++) {
2529 ns = ns->next;
2530 }
2531 if (ns != NULL) {
2532 reader->curnode = (xmlNodePtr) ns;
2533 return(1);
2534 }
2535
2536 cur = reader->node->properties;
2537 if (cur == NULL)
2538 return(0);
2539 for (;i < no;i++) {
2540 cur = cur->next;
2541 if (cur == NULL)
2542 return(0);
2543 }
2544 /* TODO walk the DTD if present */
2545
2546 reader->curnode = (xmlNodePtr) cur;
2547 return(1);
2548}
2549
2560int
2561xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2562 xmlChar *prefix = NULL;
2563 xmlChar *localname;
2564 xmlNsPtr ns;
2565 xmlAttrPtr prop;
2566
2567 if ((reader == NULL) || (name == NULL))
2568 return(-1);
2569 if (reader->node == NULL)
2570 return(-1);
2571
2572 /* TODO: handle the xmlDecl */
2573 if (reader->node->type != XML_ELEMENT_NODE)
2574 return(0);
2575
2576 localname = xmlSplitQName2(name, &prefix);
2577 if (localname == NULL) {
2578 /*
2579 * Namespace default decl
2580 */
2581 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2582 ns = reader->node->nsDef;
2583 while (ns != NULL) {
2584 if (ns->prefix == NULL) {
2585 reader->curnode = (xmlNodePtr) ns;
2586 return(1);
2587 }
2588 ns = ns->next;
2589 }
2590 return(0);
2591 }
2592
2593 prop = reader->node->properties;
2594 while (prop != NULL) {
2595 /*
2596 * One need to have
2597 * - same attribute names
2598 * - and the attribute carrying that namespace
2599 */
2600 if ((xmlStrEqual(prop->name, name)) &&
2601 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2602 reader->curnode = (xmlNodePtr) prop;
2603 return(1);
2604 }
2605 prop = prop->next;
2606 }
2607 return(0);
2608 }
2609
2610 /*
2611 * Namespace default decl
2612 */
2613 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2614 ns = reader->node->nsDef;
2615 while (ns != NULL) {
2616 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2617 reader->curnode = (xmlNodePtr) ns;
2618 goto found;
2619 }
2620 ns = ns->next;
2621 }
2622 goto not_found;
2623 }
2624 prop = reader->node->properties;
2625 while (prop != NULL) {
2626 /*
2627 * One need to have
2628 * - same attribute names
2629 * - and the attribute carrying that namespace
2630 */
2631 if ((xmlStrEqual(prop->name, localname)) &&
2632 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2633 reader->curnode = (xmlNodePtr) prop;
2634 goto found;
2635 }
2636 prop = prop->next;
2637 }
2638not_found:
2639 if (localname != NULL)
2640 xmlFree(localname);
2641 if (prefix != NULL)
2642 xmlFree(prefix);
2643 return(0);
2644
2645found:
2646 if (localname != NULL)
2647 xmlFree(localname);
2648 if (prefix != NULL)
2649 xmlFree(prefix);
2650 return(1);
2651}
2652
2664int
2665xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2666 const xmlChar *localName, const xmlChar *namespaceURI) {
2667 xmlAttrPtr prop;
2669 xmlNsPtr ns;
2670 xmlChar *prefix = NULL;
2671
2672 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2673 return(-1);
2674 if (reader->node == NULL)
2675 return(-1);
2676 if (reader->node->type != XML_ELEMENT_NODE)
2677 return(0);
2678 node = reader->node;
2679
2680 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2681 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2682 prefix = BAD_CAST localName;
2683 }
2684 ns = reader->node->nsDef;
2685 while (ns != NULL) {
2686 if ((prefix == NULL && ns->prefix == NULL) ||
2687 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2688 reader->curnode = (xmlNodePtr) ns;
2689 return(1);
2690 }
2691 ns = ns->next;
2692 }
2693 return(0);
2694 }
2695
2696 prop = node->properties;
2697 while (prop != NULL) {
2698 /*
2699 * One need to have
2700 * - same attribute names
2701 * - and the attribute carrying that namespace
2702 */
2703 if (xmlStrEqual(prop->name, localName) &&
2704 ((prop->ns != NULL) &&
2705 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2706 reader->curnode = (xmlNodePtr) prop;
2707 return(1);
2708 }
2709 prop = prop->next;
2710 }
2711 return(0);
2712}
2713
2723int
2724xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2725 if (reader == NULL)
2726 return(-1);
2727 if (reader->node == NULL)
2728 return(-1);
2729 if (reader->node->type != XML_ELEMENT_NODE)
2730 return(0);
2731
2732 if (reader->node->nsDef != NULL) {
2733 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2734 return(1);
2735 }
2736 if (reader->node->properties != NULL) {
2737 reader->curnode = (xmlNodePtr) reader->node->properties;
2738 return(1);
2739 }
2740 return(0);
2741}
2742
2752int
2753xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2754 if (reader == NULL)
2755 return(-1);
2756 if (reader->node == NULL)
2757 return(-1);
2758 if (reader->node->type != XML_ELEMENT_NODE)
2759 return(0);
2760 if (reader->curnode == NULL)
2761 return(xmlTextReaderMoveToFirstAttribute(reader));
2762
2763 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2764 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2765 if (ns->next != NULL) {
2766 reader->curnode = (xmlNodePtr) ns->next;
2767 return(1);
2768 }
2769 if (reader->node->properties != NULL) {
2770 reader->curnode = (xmlNodePtr) reader->node->properties;
2771 return(1);
2772 }
2773 return(0);
2774 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2775 (reader->curnode->next != NULL)) {
2776 reader->curnode = reader->curnode->next;
2777 return(1);
2778 }
2779 return(0);
2780}
2781
2791int
2792xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2793 if (reader == NULL)
2794 return(-1);
2795 if (reader->node == NULL)
2796 return(-1);
2797 if (reader->node->type != XML_ELEMENT_NODE)
2798 return(0);
2799 if (reader->curnode != NULL) {
2800 reader->curnode = NULL;
2801 return(1);
2802 }
2803 return(0);
2804}
2805
2816int
2817xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2818 if (reader == NULL)
2819 return(-1);
2820 if (reader->node == NULL)
2821 return(-1);
2822 if (reader->curnode == NULL)
2823 return(0);
2824 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2825 if (reader->curnode->children == NULL)
2826 return(0);
2827 reader->curnode = reader->curnode->children;
2828 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2829 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2830
2831 if (reader->faketext == NULL) {
2832 reader->faketext = xmlNewDocText(reader->node->doc,
2833 ns->href);
2834 } else {
2835 if ((reader->faketext->content != NULL) &&
2836 (reader->faketext->content !=
2837 (xmlChar *) &(reader->faketext->properties)))
2838 xmlFree(reader->faketext->content);
2839 reader->faketext->content = xmlStrdup(ns->href);
2840 }
2841 reader->curnode = reader->faketext;
2842 } else {
2843 if (reader->curnode->next == NULL)
2844 return(0);
2845 reader->curnode = reader->curnode->next;
2846 }
2847 return(1);
2848}
2849
2859const xmlChar *
2860xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2861 xmlDocPtr doc = NULL;
2862 if (reader == NULL)
2863 return(NULL);
2864 if (reader->doc != NULL)
2865 doc = reader->doc;
2866 else if (reader->ctxt != NULL)
2867 doc = reader->ctxt->myDoc;
2868 if (doc == NULL)
2869 return(NULL);
2870
2871 if (doc->encoding == NULL)
2872 return(NULL);
2873 else
2874 return(CONSTSTR(doc->encoding));
2875}
2876
2877
2878/************************************************************************
2879 * *
2880 * Access API to the current node *
2881 * *
2882 ************************************************************************/
2891int
2892xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2893 int ret;
2895 xmlNsPtr ns;
2897
2898 if (reader == NULL)
2899 return(-1);
2900 if (reader->node == NULL)
2901 return(0);
2902
2903 if (reader->curnode != NULL)
2904 node = reader->curnode;
2905 else
2906 node = reader->node;
2907
2908 if (node->type != XML_ELEMENT_NODE)
2909 return(0);
2910 if ((reader->state == XML_TEXTREADER_END) ||
2911 (reader->state == XML_TEXTREADER_BACKTRACK))
2912 return(0);
2913 ret = 0;
2914 attr = node->properties;
2915 while (attr != NULL) {
2916 ret++;
2917 attr = attr->next;
2918 }
2919 ns = node->nsDef;
2920 while (ns != NULL) {
2921 ret++;
2922 ns = ns->next;
2923 }
2924 return(ret);
2925}
2926
2937int
2938xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2940
2941 if (reader == NULL)
2942 return(-1);
2943 if (reader->node == NULL)
2944 return(XML_READER_TYPE_NONE);
2945 if (reader->curnode != NULL)
2946 node = reader->curnode;
2947 else
2948 node = reader->node;
2949 switch (node->type) {
2950 case XML_ELEMENT_NODE:
2951 if ((reader->state == XML_TEXTREADER_END) ||
2952 (reader->state == XML_TEXTREADER_BACKTRACK))
2953 return(XML_READER_TYPE_END_ELEMENT);
2954 return(XML_READER_TYPE_ELEMENT);
2955 case XML_NAMESPACE_DECL:
2956 case XML_ATTRIBUTE_NODE:
2957 return(XML_READER_TYPE_ATTRIBUTE);
2958 case XML_TEXT_NODE:
2959 if (xmlIsBlankNode(reader->node)) {
2961 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2962 else
2963 return(XML_READER_TYPE_WHITESPACE);
2964 } else {
2965 return(XML_READER_TYPE_TEXT);
2966 }
2968 return(XML_READER_TYPE_CDATA);
2970 return(XML_READER_TYPE_ENTITY_REFERENCE);
2971 case XML_ENTITY_NODE:
2972 return(XML_READER_TYPE_ENTITY);
2973 case XML_PI_NODE:
2974 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
2975 case XML_COMMENT_NODE:
2976 return(XML_READER_TYPE_COMMENT);
2977 case XML_DOCUMENT_NODE:
2979 return(XML_READER_TYPE_DOCUMENT);
2981 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
2982 case XML_NOTATION_NODE:
2983 return(XML_READER_TYPE_NOTATION);
2985 case XML_DTD_NODE:
2986 return(XML_READER_TYPE_DOCUMENT_TYPE);
2987
2988 case XML_ELEMENT_DECL:
2989 case XML_ATTRIBUTE_DECL:
2990 case XML_ENTITY_DECL:
2991 case XML_XINCLUDE_START:
2992 case XML_XINCLUDE_END:
2993 return(XML_READER_TYPE_NONE);
2994 }
2995 return(-1);
2996}
2997
3006int
3007xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3008 if ((reader == NULL) || (reader->node == NULL))
3009 return(-1);
3010 if (reader->node->type != XML_ELEMENT_NODE)
3011 return(0);
3012 if (reader->curnode != NULL)
3013 return(0);
3014 if (reader->node->children != NULL)
3015 return(0);
3016 if (reader->state == XML_TEXTREADER_END)
3017 return(0);
3018 if (reader->doc != NULL)
3019 return(1);
3020#ifdef LIBXML_XINCLUDE_ENABLED
3021 if (reader->in_xinclude > 0)
3022 return(1);
3023#endif
3024 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3025}
3026
3036xmlChar *
3037xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3039 if ((reader == NULL) || (reader->node == NULL))
3040 return(NULL);
3041 if (reader->curnode != NULL)
3042 node = reader->curnode;
3043 else
3044 node = reader->node;
3045 if (node->type == XML_NAMESPACE_DECL) {
3047 if (ns->prefix == NULL)
3048 return(xmlStrdup(BAD_CAST "xmlns"));
3049 else
3050 return(xmlStrdup(ns->prefix));
3051 }
3052 if ((node->type != XML_ELEMENT_NODE) &&
3053 (node->type != XML_ATTRIBUTE_NODE))
3054 return(xmlTextReaderName(reader));
3055 return(xmlStrdup(node->name));
3056}
3057
3067const xmlChar *
3068xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3070 if ((reader == NULL) || (reader->node == NULL))
3071 return(NULL);
3072 if (reader->curnode != NULL)
3073 node = reader->curnode;
3074 else
3075 node = reader->node;
3076 if (node->type == XML_NAMESPACE_DECL) {
3078 if (ns->prefix == NULL)
3079 return(CONSTSTR(BAD_CAST "xmlns"));
3080 else
3081 return(ns->prefix);
3082 }
3083 if ((node->type != XML_ELEMENT_NODE) &&
3084 (node->type != XML_ATTRIBUTE_NODE))
3085 return(xmlTextReaderConstName(reader));
3086 return(node->name);
3087}
3088
3098xmlChar *
3099xmlTextReaderName(xmlTextReaderPtr reader) {
3101 xmlChar *ret;
3102
3103 if ((reader == NULL) || (reader->node == NULL))
3104 return(NULL);
3105 if (reader->curnode != NULL)
3106 node = reader->curnode;
3107 else
3108 node = reader->node;
3109 switch (node->type) {
3110 case XML_ELEMENT_NODE:
3111 case XML_ATTRIBUTE_NODE:
3112 if ((node->ns == NULL) ||
3113 (node->ns->prefix == NULL))
3114 return(xmlStrdup(node->name));
3115
3116 ret = xmlStrdup(node->ns->prefix);
3117 ret = xmlStrcat(ret, BAD_CAST ":");
3118 ret = xmlStrcat(ret, node->name);
3119 return(ret);
3120 case XML_TEXT_NODE:
3121 return(xmlStrdup(BAD_CAST "#text"));
3123 return(xmlStrdup(BAD_CAST "#cdata-section"));
3124 case XML_ENTITY_NODE:
3126 return(xmlStrdup(node->name));
3127 case XML_PI_NODE:
3128 return(xmlStrdup(node->name));
3129 case XML_COMMENT_NODE:
3130 return(xmlStrdup(BAD_CAST "#comment"));
3131 case XML_DOCUMENT_NODE:
3133 return(xmlStrdup(BAD_CAST "#document"));
3135 return(xmlStrdup(BAD_CAST "#document-fragment"));
3136 case XML_NOTATION_NODE:
3137 return(xmlStrdup(node->name));
3139 case XML_DTD_NODE:
3140 return(xmlStrdup(node->name));
3141 case XML_NAMESPACE_DECL: {
3143
3144 ret = xmlStrdup(BAD_CAST "xmlns");
3145 if (ns->prefix == NULL)
3146 return(ret);
3147 ret = xmlStrcat(ret, BAD_CAST ":");
3148 ret = xmlStrcat(ret, ns->prefix);
3149 return(ret);
3150 }
3151
3152 case XML_ELEMENT_DECL:
3153 case XML_ATTRIBUTE_DECL:
3154 case XML_ENTITY_DECL:
3155 case XML_XINCLUDE_START:
3156 case XML_XINCLUDE_END:
3157 return(NULL);
3158 }
3159 return(NULL);
3160}
3161
3171const xmlChar *
3172xmlTextReaderConstName(xmlTextReaderPtr reader) {
3174
3175 if ((reader == NULL) || (reader->node == NULL))
3176 return(NULL);
3177 if (reader->curnode != NULL)
3178 node = reader->curnode;
3179 else
3180 node = reader->node;
3181 switch (node->type) {
3182 case XML_ELEMENT_NODE:
3183 case XML_ATTRIBUTE_NODE:
3184 if ((node->ns == NULL) ||
3185 (node->ns->prefix == NULL))
3186 return(node->name);
3187 return(CONSTQSTR(node->ns->prefix, node->name));
3188 case XML_TEXT_NODE:
3189 return(CONSTSTR(BAD_CAST "#text"));
3191 return(CONSTSTR(BAD_CAST "#cdata-section"));
3192 case XML_ENTITY_NODE:
3194 return(CONSTSTR(node->name));
3195 case XML_PI_NODE:
3196 return(CONSTSTR(node->name));
3197 case XML_COMMENT_NODE:
3198 return(CONSTSTR(BAD_CAST "#comment"));
3199 case XML_DOCUMENT_NODE:
3201 return(CONSTSTR(BAD_CAST "#document"));
3203 return(CONSTSTR(BAD_CAST "#document-fragment"));
3204 case XML_NOTATION_NODE:
3205 return(CONSTSTR(node->name));
3207 case XML_DTD_NODE:
3208 return(CONSTSTR(node->name));
3209 case XML_NAMESPACE_DECL: {
3211
3212 if (ns->prefix == NULL)
3213 return(CONSTSTR(BAD_CAST "xmlns"));
3214 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3215 }
3216
3217 case XML_ELEMENT_DECL:
3218 case XML_ATTRIBUTE_DECL:
3219 case XML_ENTITY_DECL:
3220 case XML_XINCLUDE_START:
3221 case XML_XINCLUDE_END:
3222 return(NULL);
3223 }
3224 return(NULL);
3225}
3226
3236xmlChar *
3237xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3239 if ((reader == NULL) || (reader->node == NULL))
3240 return(NULL);
3241 if (reader->curnode != NULL)
3242 node = reader->curnode;
3243 else
3244 node = reader->node;
3245 if (node->type == XML_NAMESPACE_DECL) {
3247 if (ns->prefix == NULL)
3248 return(NULL);
3249 return(xmlStrdup(BAD_CAST "xmlns"));
3250 }
3251 if ((node->type != XML_ELEMENT_NODE) &&
3252 (node->type != XML_ATTRIBUTE_NODE))
3253 return(NULL);
3254 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3255 return(xmlStrdup(node->ns->prefix));
3256 return(NULL);
3257}
3258
3268const xmlChar *
3269xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3271 if ((reader == NULL) || (reader->node == NULL))
3272 return(NULL);
3273 if (reader->curnode != NULL)
3274 node = reader->curnode;
3275 else
3276 node = reader->node;
3277 if (node->type == XML_NAMESPACE_DECL) {
3279 if (ns->prefix == NULL)
3280 return(NULL);
3281 return(CONSTSTR(BAD_CAST "xmlns"));
3282 }
3283 if ((node->type != XML_ELEMENT_NODE) &&
3284 (node->type != XML_ATTRIBUTE_NODE))
3285 return(NULL);
3286 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3287 return(CONSTSTR(node->ns->prefix));
3288 return(NULL);
3289}
3290
3300xmlChar *
3301xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3303 if ((reader == NULL) || (reader->node == NULL))
3304 return(NULL);
3305 if (reader->curnode != NULL)
3306 node = reader->curnode;
3307 else
3308 node = reader->node;
3309 if (node->type == XML_NAMESPACE_DECL)
3310 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3311 if ((node->type != XML_ELEMENT_NODE) &&
3312 (node->type != XML_ATTRIBUTE_NODE))
3313 return(NULL);
3314 if (node->ns != NULL)
3315 return(xmlStrdup(node->ns->href));
3316 return(NULL);
3317}
3318
3328const xmlChar *
3329xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3331 if ((reader == NULL) || (reader->node == NULL))
3332 return(NULL);
3333 if (reader->curnode != NULL)
3334 node = reader->curnode;
3335 else
3336 node = reader->node;
3337 if (node->type == XML_NAMESPACE_DECL)
3338 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3339 if ((node->type != XML_ELEMENT_NODE) &&
3340 (node->type != XML_ATTRIBUTE_NODE))
3341 return(NULL);
3342 if (node->ns != NULL)
3343 return(CONSTSTR(node->ns->href));
3344 return(NULL);
3345}
3346
3356xmlChar *
3357xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3358 if ((reader == NULL) || (reader->node == NULL))
3359 return(NULL);
3360 return(xmlNodeGetBase(NULL, reader->node));
3361}
3362
3372const xmlChar *
3373xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3374 xmlChar *tmp;
3375 const xmlChar *ret;
3376
3377 if ((reader == NULL) || (reader->node == NULL))
3378 return(NULL);
3379 tmp = xmlNodeGetBase(NULL, reader->node);
3380 if (tmp == NULL)
3381 return(NULL);
3382 ret = CONSTSTR(tmp);
3383 xmlFree(tmp);
3384 return(ret);
3385}
3386
3395int
3396xmlTextReaderDepth(xmlTextReaderPtr reader) {
3397 if (reader == NULL)
3398 return(-1);
3399 if (reader->node == NULL)
3400 return(0);
3401
3402 if (reader->curnode != NULL) {
3403 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3404 (reader->curnode->type == XML_NAMESPACE_DECL))
3405 return(reader->depth + 1);
3406 return(reader->depth + 2);
3407 }
3408 return(reader->depth);
3409}
3410
3419int
3420xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3422 if (reader == NULL)
3423 return(-1);
3424 if (reader->node == NULL)
3425 return(0);
3426 if (reader->curnode != NULL)
3427 node = reader->curnode;
3428 else
3429 node = reader->node;
3430
3431 if ((node->type == XML_ELEMENT_NODE) &&
3432 ((node->properties != NULL) || (node->nsDef != NULL)))
3433 return(1);
3434 /* TODO: handle the xmlDecl */
3435 return(0);
3436}
3437
3446int
3447xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3449 if (reader == NULL)
3450 return(-1);
3451 if (reader->node == NULL)
3452 return(0);
3453 if (reader->curnode != NULL)
3454 node = reader->curnode;
3455 else
3456 node = reader->node;
3457
3458 switch (node->type) {
3459 case XML_ATTRIBUTE_NODE:
3460 case XML_TEXT_NODE:
3462 case XML_PI_NODE:
3463 case XML_COMMENT_NODE:
3464 case XML_NAMESPACE_DECL:
3465 return(1);
3466 default:
3467 break;
3468 }
3469 return(0);
3470}
3471
3481xmlChar *
3482xmlTextReaderValue(xmlTextReaderPtr reader) {
3484 if (reader == NULL)
3485 return(NULL);
3486 if (reader->node == NULL)
3487 return(NULL);
3488 if (reader->curnode != NULL)
3489 node = reader->curnode;
3490 else
3491 node = reader->node;
3492
3493 switch (node->type) {
3494 case XML_NAMESPACE_DECL:
3495 return(xmlStrdup(((xmlNsPtr) node)->href));
3496 case XML_ATTRIBUTE_NODE:{
3498
3499 if (attr->parent != NULL)
3500 return (xmlNodeListGetString
3501 (attr->parent->doc, attr->children, 1));
3502 else
3503 return (xmlNodeListGetString(NULL, attr->children, 1));
3504 break;
3505 }
3506 case XML_TEXT_NODE:
3508 case XML_PI_NODE:
3509 case XML_COMMENT_NODE:
3510 if (node->content != NULL)
3511 return (xmlStrdup(node->content));
3512 default:
3513 break;
3514 }
3515 return(NULL);
3516}
3517
3527const xmlChar *
3528xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3530 if (reader == NULL)
3531 return(NULL);
3532 if (reader->node == NULL)
3533 return(NULL);
3534 if (reader->curnode != NULL)
3535 node = reader->curnode;
3536 else
3537 node = reader->node;
3538
3539 switch (node->type) {
3540 case XML_NAMESPACE_DECL:
3541 return(((xmlNsPtr) node)->href);
3542 case XML_ATTRIBUTE_NODE:{
3544 const xmlChar *ret;
3545
3546 if ((attr->children != NULL) &&
3547 (attr->children->type == XML_TEXT_NODE) &&
3548 (attr->children->next == NULL))
3549 return(attr->children->content);
3550 else {
3551 if (reader->buffer == NULL) {
3552 reader->buffer = xmlBufCreateSize(100);
3553 if (reader->buffer == NULL) {
3555 "xmlTextReaderSetup : malloc failed\n");
3556 return (NULL);
3557 }
3560 } else
3561 xmlBufEmpty(reader->buffer);
3563 ret = xmlBufContent(reader->buffer);
3564 if (ret == NULL) {
3565 /* error on the buffer best to reallocate */
3566 xmlBufFree(reader->buffer);
3567 reader->buffer = xmlBufCreateSize(100);
3570 ret = BAD_CAST "";
3571 }
3572 return(ret);
3573 }
3574 break;
3575 }
3576 case XML_TEXT_NODE:
3578 case XML_PI_NODE:
3579 case XML_COMMENT_NODE:
3580 return(node->content);
3581 default:
3582 break;
3583 }
3584 return(NULL);
3585}
3586
3596int
3597xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3598 if (reader == NULL)
3599 return(-1);
3600 return(0);
3601}
3602
3611int
3612xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3613 if (reader == NULL)
3614 return(-1);
3615 /* TODO maybe lookup the attribute value for " first */
3616 return((int) '"');
3617}
3618
3628xmlChar *
3629xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3630 if (reader == NULL)
3631 return(NULL);
3632 if (reader->node == NULL)
3633 return(NULL);
3634 return(xmlNodeGetLang(reader->node));
3635}
3636
3645const xmlChar *
3646xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3647 xmlChar *tmp;
3648 const xmlChar *ret;
3649
3650 if (reader == NULL)
3651 return(NULL);
3652 if (reader->node == NULL)
3653 return(NULL);
3654 tmp = xmlNodeGetLang(reader->node);
3655 if (tmp == NULL)
3656 return(NULL);
3657 ret = CONSTSTR(tmp);
3658 xmlFree(tmp);
3659 return(ret);
3660}
3661
3673const xmlChar *
3674xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3675 if (reader == NULL)
3676 return(NULL);
3677 return(CONSTSTR(str));
3678}
3679
3692int
3693xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3694 if (reader == NULL)
3695 return(-1);
3696 return(1);
3697}
3698
3699/************************************************************************
3700 * *
3701 * Extensions to the base APIs *
3702 * *
3703 ************************************************************************/
3704
3717int
3718xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3719 xmlParserProperties p = (xmlParserProperties) prop;
3720 xmlParserCtxtPtr ctxt;
3721
3722 if ((reader == NULL) || (reader->ctxt == NULL))
3723 return(-1);
3724 ctxt = reader->ctxt;
3725
3726 switch (p) {
3727 case XML_PARSER_LOADDTD:
3728 if (value != 0) {
3729 if (ctxt->loadsubset == 0) {
3730 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3731 return(-1);
3732 ctxt->loadsubset = XML_DETECT_IDS;
3733 }
3734 } else {
3735 ctxt->loadsubset = 0;
3736 }
3737 return(0);
3738 case XML_PARSER_DEFAULTATTRS:
3739 if (value != 0) {
3741 } else {
3742 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3744 }
3745 return(0);
3746 case XML_PARSER_VALIDATE:
3747 if (value != 0) {
3748 ctxt->options |= XML_PARSE_DTDVALID;
3749 ctxt->validate = 1;
3750 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3751 } else {
3752 ctxt->options &= ~XML_PARSE_DTDVALID;
3753 ctxt->validate = 0;
3754 }
3755 return(0);
3756 case XML_PARSER_SUBST_ENTITIES:
3757 if (value != 0) {
3758 ctxt->options |= XML_PARSE_NOENT;
3759 ctxt->replaceEntities = 1;
3760 } else {
3761 ctxt->options &= ~XML_PARSE_NOENT;
3762 ctxt->replaceEntities = 0;
3763 }
3764 return(0);
3765 }
3766 return(-1);
3767}
3768
3778int
3779xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3780 xmlParserProperties p = (xmlParserProperties) prop;
3781 xmlParserCtxtPtr ctxt;
3782
3783 if ((reader == NULL) || (reader->ctxt == NULL))
3784 return(-1);
3785 ctxt = reader->ctxt;
3786
3787 switch (p) {
3788 case XML_PARSER_LOADDTD:
3789 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3790 return(1);
3791 return(0);
3792 case XML_PARSER_DEFAULTATTRS:
3793 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3794 return(1);
3795 return(0);
3796 case XML_PARSER_VALIDATE:
3797 return(reader->validate);
3798 case XML_PARSER_SUBST_ENTITIES:
3799 return(ctxt->replaceEntities);
3800 }
3801 return(-1);
3802}
3803
3804
3813int
3814xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3815{
3816 if ((reader == NULL) || (reader->ctxt == NULL) ||
3817 (reader->ctxt->input == NULL)) {
3818 return (0);
3819 }
3820 return (reader->ctxt->input->line);
3821}
3822
3831int
3832xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3833{
3834 if ((reader == NULL) || (reader->ctxt == NULL) ||
3835 (reader->ctxt->input == NULL)) {
3836 return (0);
3837 }
3838 return (reader->ctxt->input->col);
3839}
3840
3852xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3853 if (reader == NULL)
3854 return(NULL);
3855
3856 if (reader->curnode != NULL)
3857 return(reader->curnode);
3858 return(reader->node);
3859}
3860
3872xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3874
3875 if (reader == NULL)
3876 return(NULL);
3877
3878 if (reader->curnode != NULL)
3879 cur = reader->curnode;
3880 else
3881 cur = reader->node;
3882 if (cur == NULL)
3883 return(NULL);
3884
3885 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3886 cur->extra |= NODE_IS_PRESERVED;
3887 cur->extra |= NODE_IS_SPRESERVED;
3888 }
3889 reader->preserves++;
3890
3891 parent = cur->parent;;
3892 while (parent != NULL) {
3893 if (parent->type == XML_ELEMENT_NODE)
3894 parent->extra |= NODE_IS_PRESERVED;
3895 parent = parent->parent;
3896 }
3897 return(cur);
3898}
3899
3900#ifdef LIBXML_PATTERN_ENABLED
3913int
3914xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3915 const xmlChar **namespaces)
3916{
3917 xmlPatternPtr comp;
3918
3919 if ((reader == NULL) || (pattern == NULL))
3920 return(-1);
3921
3922 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3923 if (comp == NULL)
3924 return(-1);
3925
3926 if (reader->patternMax <= 0) {
3927 reader->patternMax = 4;
3928 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3929 sizeof(reader->patternTab[0]));
3930 if (reader->patternTab == NULL) {
3931 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3932 return (-1);
3933 }
3934 }
3935 if (reader->patternNr >= reader->patternMax) {
3936 xmlPatternPtr *tmp;
3937 reader->patternMax *= 2;
3938 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3939 reader->patternMax *
3940 sizeof(reader->patternTab[0]));
3941 if (tmp == NULL) {
3942 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3943 reader->patternMax /= 2;
3944 return (-1);
3945 }
3946 reader->patternTab = tmp;
3947 }
3948 reader->patternTab[reader->patternNr] = comp;
3949 return(reader->patternNr++);
3950}
3951#endif
3952
3966xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
3967 if (reader == NULL)
3968 return(NULL);
3969 if (reader->doc != NULL)
3970 return(reader->doc);
3971 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
3972 return(NULL);
3973
3974 reader->preserve = 1;
3975 return(reader->ctxt->myDoc);
3976}
3977
3978#ifdef LIBXML_SCHEMAS_ENABLED
3979static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
3980
3981static void XMLCDECL
3982xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3983
3984static void XMLCDECL
3985xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3986
3987static void XMLCDECL
3988xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3989
3990static void XMLCDECL
3991xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3992
3993static void XMLCDECL
3994xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
3995{
3996 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3997
3998 char *str;
3999
4000 va_list ap;
4001
4002 va_start(ap, msg);
4003 str = xmlTextReaderBuildMessage(msg, ap);
4004 if (!reader->errorFunc) {
4005 xmlTextReaderValidityError(ctx, "%s", str);
4006 } else {
4007 reader->errorFunc(reader->errorFuncArg, str,
4009 NULL /* locator */ );
4010 }
4011 if (str != NULL)
4012 xmlFree(str);
4013 va_end(ap);
4014}
4015
4016static void XMLCDECL
4017xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4018{
4019 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4020
4021 char *str;
4022
4023 va_list ap;
4024
4025 va_start(ap, msg);
4026 str = xmlTextReaderBuildMessage(msg, ap);
4027 if (!reader->errorFunc) {
4028 xmlTextReaderValidityWarning(ctx, "%s", str);
4029 } else {
4030 reader->errorFunc(reader->errorFuncArg, str,
4032 NULL /* locator */ );
4033 }
4034 if (str != NULL)
4035 xmlFree(str);
4036 va_end(ap);
4037}
4038
4039static void
4040 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4041
4042static void
4043xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4044{
4045 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4046
4047 if (reader->sErrorFunc) {
4048 reader->sErrorFunc(reader->errorFuncArg, error);
4049 } else {
4050 xmlTextReaderStructuredError(reader, error);
4051 }
4052}
4067int
4068xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4069 if (reader == NULL)
4070 return(-1);
4071 if (schema == NULL) {
4072 if (reader->rngSchemas != NULL) {
4073 xmlRelaxNGFree(reader->rngSchemas);
4074 reader->rngSchemas = NULL;
4075 }
4076 if (reader->rngValidCtxt != NULL) {
4077 if (! reader->rngPreserveCtxt)
4078 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4079 reader->rngValidCtxt = NULL;
4080 }
4081 reader->rngPreserveCtxt = 0;
4082 return(0);
4083 }
4084 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4085 return(-1);
4086 if (reader->rngSchemas != NULL) {
4087 xmlRelaxNGFree(reader->rngSchemas);
4088 reader->rngSchemas = NULL;
4089 }
4090 if (reader->rngValidCtxt != NULL) {
4091 if (! reader->rngPreserveCtxt)
4092 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4093 reader->rngValidCtxt = NULL;
4094 }
4095 reader->rngPreserveCtxt = 0;
4096 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4097 if (reader->rngValidCtxt == NULL)
4098 return(-1);
4099 if (reader->errorFunc != NULL) {
4100 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4101 xmlTextReaderValidityErrorRelay,
4102 xmlTextReaderValidityWarningRelay,
4103 reader);
4104 }
4105 if (reader->sErrorFunc != NULL) {
4106 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4107 xmlTextReaderValidityStructuredRelay,
4108 reader);
4109 }
4110 reader->rngValidErrors = 0;
4111 reader->rngFullNode = NULL;
4112 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4113 return(0);
4114}
4115
4127static int
4128xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4129 xmlTextReaderPtr reader;
4130
4131 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4132 return(-1);
4133
4134 if (file != NULL)
4135 *file = NULL;
4136 if (line != NULL)
4137 *line = 0;
4138
4139 reader = (xmlTextReaderPtr) ctx;
4140 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4141 if (file != NULL)
4142 *file = reader->ctxt->input->filename;
4143 if (line != NULL)
4144 *line = reader->ctxt->input->line;
4145 return(0);
4146 }
4147 if (reader->node != NULL) {
4148 long res;
4149 int ret = 0;
4150
4151 if (line != NULL) {
4152 res = xmlGetLineNo(reader->node);
4153 if (res > 0)
4154 *line = (unsigned long) res;
4155 else
4156 ret = -1;
4157 }
4158 if (file != NULL) {
4159 xmlDocPtr doc = reader->node->doc;
4160 if ((doc != NULL) && (doc->URL != NULL))
4161 *file = (const char *) doc->URL;
4162 else
4163 ret = -1;
4164 }
4165 return(ret);
4166 }
4167 return(-1);
4168}
4169
4184int
4185xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4186 if (reader == NULL)
4187 return(-1);
4188 if (schema == NULL) {
4189 if (reader->xsdPlug != NULL) {
4190 xmlSchemaSAXUnplug(reader->xsdPlug);
4191 reader->xsdPlug = NULL;
4192 }
4193 if (reader->xsdValidCtxt != NULL) {
4194 if (! reader->xsdPreserveCtxt)
4195 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4196 reader->xsdValidCtxt = NULL;
4197 }
4198 reader->xsdPreserveCtxt = 0;
4199 if (reader->xsdSchemas != NULL) {
4200 xmlSchemaFree(reader->xsdSchemas);
4201 reader->xsdSchemas = NULL;
4202 }
4203 return(0);
4204 }
4205 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4206 return(-1);
4207 if (reader->xsdPlug != NULL) {
4208 xmlSchemaSAXUnplug(reader->xsdPlug);
4209 reader->xsdPlug = NULL;
4210 }
4211 if (reader->xsdValidCtxt != NULL) {
4212 if (! reader->xsdPreserveCtxt)
4213 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4214 reader->xsdValidCtxt = NULL;
4215 }
4216 reader->xsdPreserveCtxt = 0;
4217 if (reader->xsdSchemas != NULL) {
4218 xmlSchemaFree(reader->xsdSchemas);
4219 reader->xsdSchemas = NULL;
4220 }
4221 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4222 if (reader->xsdValidCtxt == NULL) {
4223 xmlSchemaFree(reader->xsdSchemas);
4224 reader->xsdSchemas = NULL;
4225 return(-1);
4226 }
4227 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4228 &(reader->ctxt->sax),
4229 &(reader->ctxt->userData));
4230 if (reader->xsdPlug == NULL) {
4231 xmlSchemaFree(reader->xsdSchemas);
4232 reader->xsdSchemas = NULL;
4233 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4234 reader->xsdValidCtxt = NULL;
4235 return(-1);
4236 }
4237 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4238 xmlTextReaderLocator,
4239 (void *) reader);
4240
4241 if (reader->errorFunc != NULL) {
4242 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4243 xmlTextReaderValidityErrorRelay,
4244 xmlTextReaderValidityWarningRelay,
4245 reader);
4246 }
4247 if (reader->sErrorFunc != NULL) {
4248 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4249 xmlTextReaderValidityStructuredRelay,
4250 reader);
4251 }
4252 reader->xsdValidErrors = 0;
4253 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4254 return(0);
4255}
4256
4271static int
4272xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4273 const char *rng,
4274 xmlRelaxNGValidCtxtPtr ctxt,
4276{
4277 if (reader == NULL)
4278 return(-1);
4279
4280 if ((rng != NULL) && (ctxt != NULL))
4281 return (-1);
4282
4283 if (((rng != NULL) || (ctxt != NULL)) &&
4284 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4285 (reader->ctxt == NULL)))
4286 return(-1);
4287
4288 /* Cleanup previous validation stuff. */
4289 if (reader->rngValidCtxt != NULL) {
4290 if ( !reader->rngPreserveCtxt)
4291 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4292 reader->rngValidCtxt = NULL;
4293 }
4294 reader->rngPreserveCtxt = 0;
4295 if (reader->rngSchemas != NULL) {
4296 xmlRelaxNGFree(reader->rngSchemas);
4297 reader->rngSchemas = NULL;
4298 }
4299
4300 if ((rng == NULL) && (ctxt == NULL)) {
4301 /* We just want to deactivate the validation, so get out. */
4302 return(0);
4303 }
4304
4305
4306 if (rng != NULL) {
4307 xmlRelaxNGParserCtxtPtr pctxt;
4308 /* Parse the schema and create validation environment. */
4309
4310 pctxt = xmlRelaxNGNewParserCtxt(rng);
4311 if (reader->errorFunc != NULL) {
4312 xmlRelaxNGSetParserErrors(pctxt,
4313 xmlTextReaderValidityErrorRelay,
4314 xmlTextReaderValidityWarningRelay,
4315 reader);
4316 }
4317 if (reader->sErrorFunc != NULL) {
4318 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4319 xmlTextReaderValidityStructuredRelay,
4320 reader);
4321 }
4322 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4323 xmlRelaxNGFreeParserCtxt(pctxt);
4324 if (reader->rngSchemas == NULL)
4325 return(-1);
4326 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4327 if (reader->rngValidCtxt == NULL) {
4328 xmlRelaxNGFree(reader->rngSchemas);
4329 reader->rngSchemas = NULL;
4330 return(-1);
4331 }
4332 } else {
4333 /* Use the given validation context. */
4334 reader->rngValidCtxt = ctxt;
4335 reader->rngPreserveCtxt = 1;
4336 }
4337 /*
4338 * Redirect the validation context's error channels to use
4339 * the reader channels.
4340 * TODO: In case the user provides the validation context we
4341 * could make this redirection optional.
4342 */
4343 if (reader->errorFunc != NULL) {
4344 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4345 xmlTextReaderValidityErrorRelay,
4346 xmlTextReaderValidityWarningRelay,
4347 reader);
4348 }
4349 if (reader->sErrorFunc != NULL) {
4350 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4351 xmlTextReaderValidityStructuredRelay,
4352 reader);
4353 }
4354 reader->rngValidErrors = 0;
4355 reader->rngFullNode = NULL;
4356 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4357 return(0);
4358}
4359
4374static int
4375xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4376 const char *xsd,
4377 xmlSchemaValidCtxtPtr ctxt,
4379{
4380 if (reader == NULL)
4381 return(-1);
4382
4383 if ((xsd != NULL) && (ctxt != NULL))
4384 return(-1);
4385
4386 if (((xsd != NULL) || (ctxt != NULL)) &&
4387 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4388 (reader->ctxt == NULL)))
4389 return(-1);
4390
4391 /* Cleanup previous validation stuff. */
4392 if (reader->xsdPlug != NULL) {
4393 xmlSchemaSAXUnplug(reader->xsdPlug);
4394 reader->xsdPlug = NULL;
4395 }
4396 if (reader->xsdValidCtxt != NULL) {
4397 if (! reader->xsdPreserveCtxt)
4398 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4399 reader->xsdValidCtxt = NULL;
4400 }
4401 reader->xsdPreserveCtxt = 0;
4402 if (reader->xsdSchemas != NULL) {
4403 xmlSchemaFree(reader->xsdSchemas);
4404 reader->xsdSchemas = NULL;
4405 }
4406
4407 if ((xsd == NULL) && (ctxt == NULL)) {
4408 /* We just want to deactivate the validation, so get out. */
4409 return(0);
4410 }
4411
4412 if (xsd != NULL) {
4413 xmlSchemaParserCtxtPtr pctxt;
4414 /* Parse the schema and create validation environment. */
4415 pctxt = xmlSchemaNewParserCtxt(xsd);
4416 if (reader->errorFunc != NULL) {
4417 xmlSchemaSetParserErrors(pctxt,
4418 xmlTextReaderValidityErrorRelay,
4419 xmlTextReaderValidityWarningRelay,
4420 reader);
4421 }
4422 reader->xsdSchemas = xmlSchemaParse(pctxt);
4423 xmlSchemaFreeParserCtxt(pctxt);
4424 if (reader->xsdSchemas == NULL)
4425 return(-1);
4426 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4427 if (reader->xsdValidCtxt == NULL) {
4428 xmlSchemaFree(reader->xsdSchemas);
4429 reader->xsdSchemas = NULL;
4430 return(-1);
4431 }
4432 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4433 &(reader->ctxt->sax),
4434 &(reader->ctxt->userData));
4435 if (reader->xsdPlug == NULL) {
4436 xmlSchemaFree(reader->xsdSchemas);
4437 reader->xsdSchemas = NULL;
4438 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4439 reader->xsdValidCtxt = NULL;
4440 return(-1);
4441 }
4442 } else {
4443 /* Use the given validation context. */
4444 reader->xsdValidCtxt = ctxt;
4445 reader->xsdPreserveCtxt = 1;
4446 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4447 &(reader->ctxt->sax),
4448 &(reader->ctxt->userData));
4449 if (reader->xsdPlug == NULL) {
4450 reader->xsdValidCtxt = NULL;
4451 reader->xsdPreserveCtxt = 0;
4452 return(-1);
4453 }
4454 }
4455 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4456 xmlTextReaderLocator,
4457 (void *) reader);
4458 /*
4459 * Redirect the validation context's error channels to use
4460 * the reader channels.
4461 * TODO: In case the user provides the validation context we
4462 * could make this redirection optional.
4463 */
4464 if (reader->errorFunc != NULL) {
4465 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4466 xmlTextReaderValidityErrorRelay,
4467 xmlTextReaderValidityWarningRelay,
4468 reader);
4469 }
4470 if (reader->sErrorFunc != NULL) {
4471 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4472 xmlTextReaderValidityStructuredRelay,
4473 reader);
4474 }
4475 reader->xsdValidErrors = 0;
4476 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4477 return(0);
4478}
4479
4493int
4494xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4495 xmlSchemaValidCtxtPtr ctxt,
4496 int options)
4497{
4498 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4499}
4500
4513int
4514xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4515{
4516 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4517}
4518
4532int
4533xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4534 xmlRelaxNGValidCtxtPtr ctxt,
4535 int options)
4536{
4537 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4538}
4539
4552int
4553xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4554{
4555 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4556}
4557
4558#endif
4559
4571int
4572xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4574 if (reader == NULL)
4575 return(-1);
4576 if (reader->node == NULL)
4577 return(-1);
4578 if (reader->curnode != NULL)
4579 node = reader->curnode;
4580 else
4581 node = reader->node;
4582
4583 if (XML_NAMESPACE_DECL == node->type)
4584 return(1);
4585 else
4586 return(0);
4587}
4588
4598const xmlChar *
4599xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4600 xmlDocPtr doc = NULL;
4601 if (reader == NULL)
4602 return(NULL);
4603 if (reader->doc != NULL)
4604 doc = reader->doc;
4605 else if (reader->ctxt != NULL)
4606 doc = reader->ctxt->myDoc;
4607 if (doc == NULL)
4608 return(NULL);
4609
4610 if (doc->version == NULL)
4611 return(NULL);
4612 else
4613 return(CONSTSTR(doc->version));
4614}
4615
4626int
4627xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4628 xmlDocPtr doc = NULL;
4629 if (reader == NULL)
4630 return(-1);
4631 if (reader->doc != NULL)
4632 doc = reader->doc;
4633 else if (reader->ctxt != NULL)
4634 doc = reader->ctxt->myDoc;
4635 if (doc == NULL)
4636 return(-1);
4637
4638 return(doc->standalone);
4639}
4640
4641/************************************************************************
4642 * *
4643 * Error Handling Extensions *
4644 * *
4645 ************************************************************************/
4646
4647/* helper to build a xmlMalloc'ed string from a format and va_list */
4648static char *
4649xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4650 int size = 0;
4651 int chars;
4652 char *larger;
4653 char *str = NULL;
4654 va_list aq;
4655
4656 while (1) {
4657 VA_COPY(aq, ap);
4658 chars = vsnprintf(str, size, msg, aq);
4659 va_end(aq);
4660 if (chars < 0) {
4661 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4662 if (str)
4663 xmlFree(str);
4664 return NULL;
4665 }
4666 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4667 break;
4668 if (chars < MAX_ERR_MSG_SIZE)
4669 size = chars + 1;
4670 else
4671 size = MAX_ERR_MSG_SIZE;
4672 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4673 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4674 if (str)
4675 xmlFree(str);
4676 return NULL;
4677 }
4678 str = larger;
4679 }
4680
4681 return str;
4682}
4683
4692int
4693xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4694 /* we know that locator is a xmlParserCtxtPtr */
4696 int ret = -1;
4697
4698 if (locator == NULL)
4699 return(-1);
4700 if (ctx->node != NULL) {
4701 ret = xmlGetLineNo(ctx->node);
4702 }
4703 else {
4704 /* inspired from error.c */
4706 input = ctx->input;
4707 if ((input->filename == NULL) && (ctx->inputNr > 1))
4708 input = ctx->inputTab[ctx->inputNr - 2];
4709 if (input != NULL) {
4710 ret = input->line;
4711 }
4712 else {
4713 ret = -1;
4714 }
4715 }
4716
4717 return ret;
4718}
4719
4729xmlChar *
4730xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4731 /* we know that locator is a xmlParserCtxtPtr */
4733 xmlChar *ret = NULL;
4734
4735 if (locator == NULL)
4736 return(NULL);
4737 if (ctx->node != NULL) {
4738 ret = xmlNodeGetBase(NULL,ctx->node);
4739 }
4740 else {
4741 /* inspired from error.c */
4743 input = ctx->input;
4744 if ((input->filename == NULL) && (ctx->inputNr > 1))
4745 input = ctx->inputTab[ctx->inputNr - 2];
4746 if (input != NULL) {
4747 ret = xmlStrdup(BAD_CAST input->filename);
4748 }
4749 else {
4750 ret = NULL;
4751 }
4752 }
4753
4754 return ret;
4755}
4756
4757static void
4758xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4759 char *str)
4760{
4762
4763 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4764
4765 if (str != NULL) {
4766 if (reader->errorFunc)
4767 reader->errorFunc(reader->errorFuncArg, str, severity,
4768 (xmlTextReaderLocatorPtr) ctx);
4769 xmlFree(str);
4770 }
4771}
4772
4773static void
4774xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4775{
4777
4778 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4779
4780 if (error && reader->sErrorFunc) {
4781 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4782 }
4783}
4784
4785static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4786xmlTextReaderError(void *ctxt, const char *msg, ...)
4787{
4788 va_list ap;
4789
4790 va_start(ap, msg);
4791 xmlTextReaderGenericError(ctxt,
4793 xmlTextReaderBuildMessage(msg, ap));
4794 va_end(ap);
4795
4796}
4797
4798static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4799xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4800{
4801 va_list ap;
4802
4803 va_start(ap, msg);
4804 xmlTextReaderGenericError(ctxt,
4806 xmlTextReaderBuildMessage(msg, ap));
4807 va_end(ap);
4808}
4809
4810static void XMLCDECL
4811xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4812{
4813 va_list ap;
4814
4815 int len = xmlStrlen((const xmlChar *) msg);
4816
4817 if ((len > 1) && (msg[len - 2] != ':')) {
4818 /*
4819 * some callbacks only report locator information:
4820 * skip them (mimicking behaviour in error.c)
4821 */
4822 va_start(ap, msg);
4823 xmlTextReaderGenericError(ctxt,
4825 xmlTextReaderBuildMessage(msg, ap));
4826 va_end(ap);
4827 }
4828}
4829
4830static void XMLCDECL
4831xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4832{
4833 va_list ap;
4834
4835 int len = xmlStrlen((const xmlChar *) msg);
4836
4837 if ((len != 0) && (msg[len - 1] != ':')) {
4838 /*
4839 * some callbacks only report locator information:
4840 * skip them (mimicking behaviour in error.c)
4841 */
4842 va_start(ap, msg);
4843 xmlTextReaderGenericError(ctxt,
4845 xmlTextReaderBuildMessage(msg, ap));
4846 va_end(ap);
4847 }
4848}
4849
4860void
4861xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4862 xmlTextReaderErrorFunc f, void *arg)
4863{
4864 if (f != NULL) {
4865 reader->ctxt->sax->error = xmlTextReaderError;
4866 reader->ctxt->sax->serror = NULL;
4867 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4868 reader->ctxt->sax->warning = xmlTextReaderWarning;
4869 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4870 reader->errorFunc = f;
4871 reader->sErrorFunc = NULL;
4872 reader->errorFuncArg = arg;
4873#ifdef LIBXML_SCHEMAS_ENABLED
4874 if (reader->rngValidCtxt) {
4875 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4876 xmlTextReaderValidityErrorRelay,
4877 xmlTextReaderValidityWarningRelay,
4878 reader);
4879 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4880 reader);
4881 }
4882 if (reader->xsdValidCtxt) {
4883 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4884 xmlTextReaderValidityErrorRelay,
4885 xmlTextReaderValidityWarningRelay,
4886 reader);
4887 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4888 reader);
4889 }
4890#endif
4891 } else {
4892 /* restore defaults */
4893 reader->ctxt->sax->error = xmlParserError;
4894 reader->ctxt->vctxt.error = xmlParserValidityError;
4895 reader->ctxt->sax->warning = xmlParserWarning;
4896 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4897 reader->errorFunc = NULL;
4898 reader->sErrorFunc = NULL;
4899 reader->errorFuncArg = NULL;
4900#ifdef LIBXML_SCHEMAS_ENABLED
4901 if (reader->rngValidCtxt) {
4902 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4903 reader);
4904 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4905 reader);
4906 }
4907 if (reader->xsdValidCtxt) {
4908 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4909 reader);
4910 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4911 reader);
4912 }
4913#endif
4914 }
4915}
4916
4927void
4928xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4930{
4931 if (f != NULL) {
4932 reader->ctxt->sax->error = NULL;
4933 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4934 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4935 reader->ctxt->sax->warning = xmlTextReaderWarning;
4936 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4937 reader->sErrorFunc = f;
4938 reader->errorFunc = NULL;
4939 reader->errorFuncArg = arg;
4940#ifdef LIBXML_SCHEMAS_ENABLED
4941 if (reader->rngValidCtxt) {
4942 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4943 reader);
4944 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4945 xmlTextReaderValidityStructuredRelay,
4946 reader);
4947 }
4948 if (reader->xsdValidCtxt) {
4949 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4950 reader);
4951 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4952 xmlTextReaderValidityStructuredRelay,
4953 reader);
4954 }
4955#endif
4956 } else {
4957 /* restore defaults */
4958 reader->ctxt->sax->error = xmlParserError;
4959 reader->ctxt->sax->serror = NULL;
4960 reader->ctxt->vctxt.error = xmlParserValidityError;
4961 reader->ctxt->sax->warning = xmlParserWarning;
4962 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4963 reader->errorFunc = NULL;
4964 reader->sErrorFunc = NULL;
4965 reader->errorFuncArg = NULL;
4966#ifdef LIBXML_SCHEMAS_ENABLED
4967 if (reader->rngValidCtxt) {
4968 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4969 reader);
4970 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4971 reader);
4972 }
4973 if (reader->xsdValidCtxt) {
4974 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4975 reader);
4976 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4977 reader);
4978 }
4979#endif
4980 }
4981}
4982
4991int
4992xmlTextReaderIsValid(xmlTextReaderPtr reader)
4993{
4994 if (reader == NULL)
4995 return (-1);
4996#ifdef LIBXML_SCHEMAS_ENABLED
4997 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4998 return (reader->rngValidErrors == 0);
4999 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5000 return (reader->xsdValidErrors == 0);
5001#endif
5002 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5003 return (reader->ctxt->valid);
5004 return (0);
5005}
5006
5015void
5016xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5017 xmlTextReaderErrorFunc * f, void **arg)
5018{
5019 if (f != NULL)
5020 *f = reader->errorFunc;
5021 if (arg != NULL)
5022 *arg = reader->errorFuncArg;
5023}
5024/************************************************************************
5025 * *
5026 * New set (2.6.0) of simpler and more flexible APIs *
5027 * *
5028 ************************************************************************/
5029
5043int
5044xmlTextReaderSetup(xmlTextReaderPtr reader,
5045 xmlParserInputBufferPtr input, const char *URL,
5046 const char *encoding, int options)
5047{
5048 if (reader == NULL) {
5049 if (input != NULL)
5051 return (-1);
5052 }
5053
5054 /*
5055 * we force the generation of compact text nodes on the reader
5056 * since usr applications should never modify the tree
5057 */
5059
5060 reader->doc = NULL;
5061 reader->entNr = 0;
5062 reader->parserFlags = options;
5063 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5064 if ((input != NULL) && (reader->input != NULL) &&
5065 (reader->allocs & XML_TEXTREADER_INPUT)) {
5067 reader->input = NULL;
5068 reader->allocs -= XML_TEXTREADER_INPUT;
5069 }
5070 if (input != NULL) {
5071 reader->input = input;
5072 reader->allocs |= XML_TEXTREADER_INPUT;
5073 }
5074 if (reader->buffer == NULL)
5075 reader->buffer = xmlBufCreateSize(100);
5076 if (reader->buffer == NULL) {
5078 "xmlTextReaderSetup : malloc failed\n");
5079 return (-1);
5080 }
5081 /* no operation on a reader should require a huge buffer */
5084 if (reader->sax == NULL)
5085 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5086 if (reader->sax == NULL) {
5088 "xmlTextReaderSetup : malloc failed\n");
5089 return (-1);
5090 }
5091 xmlSAXVersion(reader->sax, 2);
5092 reader->startElement = reader->sax->startElement;
5093 reader->sax->startElement = xmlTextReaderStartElement;
5094 reader->endElement = reader->sax->endElement;
5095 reader->sax->endElement = xmlTextReaderEndElement;
5096#ifdef LIBXML_SAX1_ENABLED
5097 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5098#endif /* LIBXML_SAX1_ENABLED */
5099 reader->startElementNs = reader->sax->startElementNs;
5100 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5101 reader->endElementNs = reader->sax->endElementNs;
5102 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5103#ifdef LIBXML_SAX1_ENABLED
5104 } else {
5105 reader->startElementNs = NULL;
5106 reader->endElementNs = NULL;
5107 }
5108#endif /* LIBXML_SAX1_ENABLED */
5109 reader->characters = reader->sax->characters;
5110 reader->sax->characters = xmlTextReaderCharacters;
5111 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5112 reader->cdataBlock = reader->sax->cdataBlock;
5113 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5114
5115 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5116 reader->node = NULL;
5117 reader->curnode = NULL;
5118 if (input != NULL) {
5119 if (xmlBufUse(reader->input->buffer) < 4) {
5121 }
5122 if (reader->ctxt == NULL) {
5123 if (xmlBufUse(reader->input->buffer) >= 4) {
5124 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5125 (const char *) xmlBufContent(reader->input->buffer),
5126 4, URL);
5127 reader->base = 0;
5128 reader->cur = 4;
5129 } else {
5130 reader->ctxt =
5131 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5132 reader->base = 0;
5133 reader->cur = 0;
5134 }
5135 } else {
5136 xmlParserInputPtr inputStream;
5139
5140 xmlCtxtReset(reader->ctxt);
5142 if (buf == NULL) return(-1);
5143 inputStream = xmlNewInputStream(reader->ctxt);
5144 if (inputStream == NULL) {
5146 return(-1);
5147 }
5148
5149 if (URL == NULL)
5150 inputStream->filename = NULL;
5151 else
5152 inputStream->filename = (char *)
5153 xmlCanonicPath((const xmlChar *) URL);
5154 inputStream->buf = buf;
5155 xmlBufResetInput(buf->buffer, inputStream);
5156
5157 inputPush(reader->ctxt, inputStream);
5158 reader->cur = 0;
5159 }
5160 if (reader->ctxt == NULL) {
5162 "xmlTextReaderSetup : malloc failed\n");
5163 return (-1);
5164 }
5165 }
5166 if (reader->dict != NULL) {
5167 if (reader->ctxt->dict != NULL) {
5168 if (reader->dict != reader->ctxt->dict) {
5169 xmlDictFree(reader->dict);
5170 reader->dict = reader->ctxt->dict;
5171 }
5172 } else {
5173 reader->ctxt->dict = reader->dict;
5174 }
5175 } else {
5176 if (reader->ctxt->dict == NULL)
5177 reader->ctxt->dict = xmlDictCreate();
5178 reader->dict = reader->ctxt->dict;
5179 }
5180 reader->ctxt->_private = reader;
5181 reader->ctxt->linenumbers = 1;
5182 reader->ctxt->dictNames = 1;
5183 /*
5184 * use the parser dictionary to allocate all elements and attributes names
5185 */
5186 reader->ctxt->docdict = 1;
5187 reader->ctxt->parseMode = XML_PARSE_READER;
5188
5189#ifdef LIBXML_XINCLUDE_ENABLED
5190 if (reader->xincctxt != NULL) {
5191 xmlXIncludeFreeContext(reader->xincctxt);
5192 reader->xincctxt = NULL;
5193 }
5195 reader->xinclude = 1;
5196 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5198 } else
5199 reader->xinclude = 0;
5200 reader->in_xinclude = 0;
5201#endif
5202#ifdef LIBXML_PATTERN_ENABLED
5203 if (reader->patternTab == NULL) {
5204 reader->patternNr = 0;
5205 reader->patternMax = 0;
5206 }
5207 while (reader->patternNr > 0) {
5208 reader->patternNr--;
5209 if (reader->patternTab[reader->patternNr] != NULL) {
5210 xmlFreePattern(reader->patternTab[reader->patternNr]);
5211 reader->patternTab[reader->patternNr] = NULL;
5212 }
5213 }
5214#endif
5215
5217 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5218
5220 if (encoding != NULL) {
5222
5224 if (hdlr != NULL)
5225 xmlSwitchToEncoding(reader->ctxt, hdlr);
5226 }
5227 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5228 (reader->ctxt->input->filename == NULL))
5229 reader->ctxt->input->filename = (char *)
5230 xmlStrdup((const xmlChar *) URL);
5231
5232 reader->doc = NULL;
5233
5234 return (0);
5235}
5236
5250long
5251xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5252 if ((reader == NULL) || (reader->ctxt == NULL))
5253 return(-1);
5254 return(xmlByteConsumed(reader->ctxt));
5255}
5256
5257
5266xmlTextReaderPtr
5267xmlReaderWalker(xmlDocPtr doc)
5268{
5269 xmlTextReaderPtr ret;
5270
5271 if (doc == NULL)
5272 return(NULL);
5273
5274 ret = xmlMalloc(sizeof(xmlTextReader));
5275 if (ret == NULL) {
5277 "xmlNewTextReader : malloc failed\n");
5278 return(NULL);
5279 }
5280 memset(ret, 0, sizeof(xmlTextReader));
5281 ret->entNr = 0;
5282 ret->input = NULL;
5283 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5284 ret->node = NULL;
5285 ret->curnode = NULL;
5286 ret->base = 0;
5287 ret->cur = 0;
5288 ret->allocs = XML_TEXTREADER_CTXT;
5289 ret->doc = doc;
5290 ret->state = XML_TEXTREADER_START;
5291 ret->dict = xmlDictCreate();
5292 return(ret);
5293}
5294
5307xmlTextReaderPtr
5308xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5309 int options)
5310{
5311 int len;
5312
5313 if (cur == NULL)
5314 return (NULL);
5315 len = xmlStrlen(cur);
5316
5317 return (xmlReaderForMemory
5318 ((const char *) cur, len, URL, encoding, options));
5319}
5320
5332xmlTextReaderPtr
5333xmlReaderForFile(const char *filename, const char *encoding, int options)
5334{
5335 xmlTextReaderPtr reader;
5336
5337 reader = xmlNewTextReaderFilename(filename);
5338 if (reader == NULL)
5339 return (NULL);
5340 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5341 return (reader);
5342}
5343
5357xmlTextReaderPtr
5358xmlReaderForMemory(const char *buffer, int size, const char *URL,
5359 const char *encoding, int options)
5360{
5361 xmlTextReaderPtr reader;
5363
5366 if (buf == NULL) {
5367 return (NULL);
5368 }
5369 reader = xmlNewTextReader(buf, URL);
5370 if (reader == NULL) {
5372 return (NULL);
5373 }
5374 reader->allocs |= XML_TEXTREADER_INPUT;
5375 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5376 return (reader);
5377}
5378
5393xmlTextReaderPtr
5394xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5395{
5396 xmlTextReaderPtr reader;
5398
5399 if (fd < 0)
5400 return (NULL);
5401
5403 if (input == NULL)
5404 return (NULL);
5405 input->closecallback = NULL;
5406 reader = xmlNewTextReader(input, URL);
5407 if (reader == NULL) {
5409 return (NULL);
5410 }
5411 reader->allocs |= XML_TEXTREADER_INPUT;
5412 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5413 return (reader);
5414}
5415
5430xmlTextReaderPtr
5431xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5432 void *ioctx, const char *URL, const char *encoding,
5433 int options)
5434{
5435 xmlTextReaderPtr reader;