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