ReactOS  0.4.15-dev-3303-g1ade494
xmlreader.c
Go to the documentation of this file.
1 /*
2  * xmlreader.c: implements the xmlTextReader streaming node API
3  *
4  * NOTE:
5  * XmlTextReader.Normalization Property won't be supported, since
6  * it makes the parser non compliant to the XML recommendation
7  *
8  * See Copyright for the status of this software.
9  *
10  * daniel@veillard.com
11  */
12 
13 /*
14  * TODOs:
15  * - XML Schemas validation
16  */
17 #define IN_LIBXML
18 #include "libxml.h"
19 
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
23 
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 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
52 /* Keeping free objects can hide memory errors. */
53 #define MAX_FREE_NODES 1
54 #else
55 #define MAX_FREE_NODES 100
56 #endif
57 
58 /*
59  * The following VA_COPY was coded following an example in
60  * the Samba project. It may not be sufficient for some
61  * esoteric implementations of va_list but (hopefully) will
62  * be sufficient for libxml2.
63  */
64 #ifndef VA_COPY
65  #ifdef HAVE_VA_COPY
66  #define VA_COPY(dest, src) va_copy(dest, src)
67  #else
68  #ifdef HAVE___VA_COPY
69  #define VA_COPY(dest,src) __va_copy(dest, src)
70  #else
71  #ifndef VA_LIST_IS_ARRAY
72  #define VA_COPY(dest,src) (dest) = (src)
73  #else
74  #include <string.h>
75  #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
76  #endif
77  #endif
78  #endif
79 #endif
80 
81 /* #define DEBUG_CALLBACKS */
82 /* #define DEBUG_READER */
83 
89 #define TODO \
90  xmlGenericError(xmlGenericErrorContext, \
91  "Unimplemented block at %s:%d\n", \
92  __FILE__, __LINE__);
93 
94 #ifdef DEBUG_READER
95 #define DUMP_READER xmlTextReaderDebug(reader);
96 #else
97 #define DUMP_READER
98 #endif
99 
100 #define CHUNK_SIZE 512
101 /************************************************************************
102  * *
103  * The parser: maps the Text Reader API on top of the existing *
104  * parsing routines building a tree *
105  * *
106  ************************************************************************/
107 
108 #define XML_TEXTREADER_INPUT 1
109 #define XML_TEXTREADER_CTXT 2
110 
111 typedef enum {
112  XML_TEXTREADER_NONE = -1,
113  XML_TEXTREADER_START= 0,
114  XML_TEXTREADER_ELEMENT= 1,
115  XML_TEXTREADER_END= 2,
116  XML_TEXTREADER_EMPTY= 3,
117  XML_TEXTREADER_BACKTRACK= 4,
118  XML_TEXTREADER_DONE= 5,
119  XML_TEXTREADER_ERROR= 6
120 } xmlTextReaderState;
121 
122 typedef enum {
123  XML_TEXTREADER_NOT_VALIDATE = 0,
124  XML_TEXTREADER_VALIDATE_DTD = 1,
125  XML_TEXTREADER_VALIDATE_RNG = 2,
126  XML_TEXTREADER_VALIDATE_XSD = 4
127 } xmlTextReaderValidate;
128 
129 struct _xmlTextReader {
130  int mode; /* the parsing mode */
131  xmlDocPtr doc; /* when walking an existing doc */
132  xmlTextReaderValidate validate;/* is there any validation */
133  int allocs; /* what structure were deallocated */
134  xmlTextReaderState state;
135  xmlParserCtxtPtr ctxt; /* the parser context */
136  xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
137  xmlParserInputBufferPtr input; /* the input */
138  startElementSAXFunc startElement;/* initial SAX callbacks */
139  endElementSAXFunc endElement; /* idem */
140  startElementNsSAX2Func startElementNs;/* idem */
141  endElementNsSAX2Func endElementNs; /* idem */
142  charactersSAXFunc characters;
143  cdataBlockSAXFunc cdataBlock;
144  unsigned int base; /* base of the segment in the input */
145  unsigned int cur; /* current position in the input */
146  xmlNodePtr node; /* current node */
147  xmlNodePtr curnode;/* current attribute node */
148  int depth; /* depth of the current node */
149  xmlNodePtr faketext;/* fake xmlNs chld */
150  int preserve;/* preserve the resulting document */
151  xmlBufPtr buffer; /* used to return const xmlChar * */
152  xmlDictPtr dict; /* the context dictionary */
153 
154  /* entity stack when traversing entities content */
155  xmlNodePtr ent; /* Current Entity Ref Node */
156  int entNr; /* Depth of the entities stack */
157  int entMax; /* Max depth of the entities stack */
158  xmlNodePtr *entTab; /* array of entities */
159 
160  /* error handling */
161  xmlTextReaderErrorFunc errorFunc; /* callback function */
162  void *errorFuncArg; /* callback function user argument */
163 
164 #ifdef LIBXML_SCHEMAS_ENABLED
165  /* Handling of RelaxNG validation */
166  xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
167  xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
168  int rngPreserveCtxt; /* 1 if the context was provided by the user */
169  int rngValidErrors;/* The number of errors detected */
170  xmlNodePtr rngFullNode; /* the node if RNG not progressive */
171  /* Handling of Schemas validation */
172  xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
173  xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
174  int xsdPreserveCtxt; /* 1 if the context was provided by the user */
175  int xsdValidErrors;/* The number of errors detected */
176  xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
177 #endif
178 #ifdef LIBXML_XINCLUDE_ENABLED
179  /* Handling of XInclude processing */
180  int xinclude; /* is xinclude asked for */
181  const xmlChar * xinclude_name; /* the xinclude name from dict */
182  xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
183  int in_xinclude; /* counts for xinclude */
184 #endif
185 #ifdef LIBXML_PATTERN_ENABLED
186  int patternNr; /* number of preserve patterns */
187  int patternMax; /* max preserve patterns */
188  xmlPatternPtr *patternTab; /* array of preserve patterns */
189 #endif
190  int preserves; /* level of preserves */
191  int parserFlags; /* the set of options set */
192  /* Structured error handling */
193  xmlStructuredErrorFunc sErrorFunc; /* callback function */
194 };
195 
196 #define NODE_IS_EMPTY 0x1
197 #define NODE_IS_PRESERVED 0x2
198 #define NODE_IS_SPRESERVED 0x4
199 
205 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
206 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
207 
208 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
209 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
210 
211 /************************************************************************
212  * *
213  * Our own version of the freeing routines as we recycle nodes *
214  * *
215  ************************************************************************/
223 #define DICT_FREE(str) \
224  if ((str) && ((!dict) || \
225  (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
226  xmlFree((char *)(str));
227 
228 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
229 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
230 
237 static void
238 xmlFreeID(xmlIDPtr id) {
239  xmlDictPtr dict = NULL;
240 
241  if (id == NULL) return;
242 
243  if (id->doc != NULL)
244  dict = id->doc->dict;
245 
246  if (id->value != NULL)
247  DICT_FREE(id->value)
248  if (id->name != NULL)
249  DICT_FREE(id->name)
250  xmlFree(id);
251 }
252 
262 static int
263 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
265  xmlIDPtr id;
266  xmlChar *ID;
267 
268  if (doc == NULL) return(-1);
269  if (attr == NULL) return(-1);
270  table = (xmlIDTablePtr) doc->ids;
271  if (table == NULL)
272  return(-1);
273 
274  ID = xmlNodeListGetString(doc, attr->children, 1);
275  if (ID == NULL)
276  return(-1);
277  id = xmlHashLookup(table, ID);
278  xmlFree(ID);
279  if (id == NULL || id->attr != attr) {
280  return(-1);
281  }
282  id->name = attr->name;
283  attr->name = NULL;
284  id->attr = NULL;
285  return(0);
286 }
287 
295 static int
296 xmlTextReaderWalkRemoveRef(const void *data, void *user)
297 {
300 
301  if (ref->attr == attr) { /* Matched: remove and terminate walk */
302  ref->name = xmlStrdup(attr->name);
303  ref->attr = NULL;
304  return 0;
305  }
306  return 1;
307 }
308 
318 static int
319 xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
320  xmlListPtr ref_list;
322  xmlChar *ID;
323 
324  if (doc == NULL) return(-1);
325  if (attr == NULL) return(-1);
326  table = (xmlRefTablePtr) doc->refs;
327  if (table == NULL)
328  return(-1);
329 
330  ID = xmlNodeListGetString(doc, attr->children, 1);
331  if (ID == NULL)
332  return(-1);
333  ref_list = xmlHashLookup(table, ID);
334  xmlFree(ID);
335  if(ref_list == NULL)
336  return (-1);
337  xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
338  return(0);
339 }
340 
348 static void
349 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
350  xmlDictPtr dict;
351 
352  if ((reader != NULL) && (reader->ctxt != NULL))
353  dict = reader->ctxt->dict;
354  else
355  dict = NULL;
356  if (cur == NULL) return;
357 
360 
361  /* Check for ID removal -> leading to invalid references ! */
362  if ((cur->parent != NULL) && (cur->parent->doc != NULL)) {
363  if (xmlIsID(cur->parent->doc, cur->parent, cur))
364  xmlTextReaderRemoveID(cur->parent->doc, cur);
365  if (((cur->parent->doc->intSubset != NULL) ||
366  (cur->parent->doc->extSubset != NULL)) &&
367  (xmlIsRef(cur->parent->doc, cur->parent, cur)))
368  xmlTextReaderRemoveRef(cur->parent->doc, cur);
369  }
370  if (cur->children != NULL)
371  xmlTextReaderFreeNodeList(reader, cur->children);
372 
373  DICT_FREE(cur->name);
374  if ((reader != NULL) && (reader->ctxt != NULL) &&
375  (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
376  cur->next = reader->ctxt->freeAttrs;
377  reader->ctxt->freeAttrs = cur;
378  reader->ctxt->freeAttrsNr++;
379  } else {
380  xmlFree(cur);
381  }
382 }
383 
391 static void
392 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
394 
395  while (cur != NULL) {
396  next = cur->next;
397  xmlTextReaderFreeProp(reader, cur);
398  cur = next;
399  }
400 }
401 
410 static void
411 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
414  xmlDictPtr dict;
415  size_t depth = 0;
416 
417  if ((reader != NULL) && (reader->ctxt != NULL))
418  dict = reader->ctxt->dict;
419  else
420  dict = NULL;
421  if (cur == NULL) return;
422  if (cur->type == XML_NAMESPACE_DECL) {
424  return;
425  }
426  if ((cur->type == XML_DOCUMENT_NODE) ||
427  (cur->type == XML_HTML_DOCUMENT_NODE)) {
429  return;
430  }
431  while (1) {
432  while ((cur->type != XML_DTD_NODE) &&
433  (cur->type != XML_ENTITY_REF_NODE) &&
434  (cur->children != NULL) &&
435  (cur->children->parent == cur)) {
436  cur = cur->children;
437  depth += 1;
438  }
439 
440  next = cur->next;
441  parent = cur->parent;
442 
443  /* unroll to speed up freeing the document */
444  if (cur->type != XML_DTD_NODE) {
445 
448 
449  if (((cur->type == XML_ELEMENT_NODE) ||
450  (cur->type == XML_XINCLUDE_START) ||
451  (cur->type == XML_XINCLUDE_END)) &&
452  (cur->properties != NULL))
453  xmlTextReaderFreePropList(reader, cur->properties);
454  if ((cur->content != (xmlChar *) &(cur->properties)) &&
455  (cur->type != XML_ELEMENT_NODE) &&
456  (cur->type != XML_XINCLUDE_START) &&
457  (cur->type != XML_XINCLUDE_END) &&
458  (cur->type != XML_ENTITY_REF_NODE)) {
459  DICT_FREE(cur->content);
460  }
461  if (((cur->type == XML_ELEMENT_NODE) ||
462  (cur->type == XML_XINCLUDE_START) ||
463  (cur->type == XML_XINCLUDE_END)) &&
464  (cur->nsDef != NULL))
465  xmlFreeNsList(cur->nsDef);
466 
467  /*
468  * we don't free element names here they are interned now
469  */
470  if ((cur->type != XML_TEXT_NODE) &&
471  (cur->type != XML_COMMENT_NODE))
472  DICT_FREE(cur->name);
473  if (((cur->type == XML_ELEMENT_NODE) ||
474  (cur->type == XML_TEXT_NODE)) &&
475  (reader != NULL) && (reader->ctxt != NULL) &&
476  (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
477  cur->next = reader->ctxt->freeElems;
478  reader->ctxt->freeElems = cur;
479  reader->ctxt->freeElemsNr++;
480  } else {
481  xmlFree(cur);
482  }
483  }
484 
485  if (next != NULL) {
486  cur = next;
487  } else {
488  if ((depth == 0) || (parent == NULL))
489  break;
490  depth -= 1;
491  cur = parent;
492  cur->children = NULL;
493  }
494  }
495 }
496 
505 static void
506 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
507  xmlDictPtr dict;
508 
509  if ((reader != NULL) && (reader->ctxt != NULL))
510  dict = reader->ctxt->dict;
511  else
512  dict = NULL;
513  if (cur->type == XML_DTD_NODE) {
515  return;
516  }
517  if (cur->type == XML_NAMESPACE_DECL) {
519  return;
520  }
521  if (cur->type == XML_ATTRIBUTE_NODE) {
522  xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
523  return;
524  }
525 
526  if ((cur->children != NULL) &&
527  (cur->type != XML_ENTITY_REF_NODE)) {
528  if (cur->children->parent == cur)
529  xmlTextReaderFreeNodeList(reader, cur->children);
530  cur->children = NULL;
531  }
532 
535 
536  if (((cur->type == XML_ELEMENT_NODE) ||
537  (cur->type == XML_XINCLUDE_START) ||
538  (cur->type == XML_XINCLUDE_END)) &&
539  (cur->properties != NULL))
540  xmlTextReaderFreePropList(reader, cur->properties);
541  if ((cur->content != (xmlChar *) &(cur->properties)) &&
542  (cur->type != XML_ELEMENT_NODE) &&
543  (cur->type != XML_XINCLUDE_START) &&
544  (cur->type != XML_XINCLUDE_END) &&
545  (cur->type != XML_ENTITY_REF_NODE)) {
546  DICT_FREE(cur->content);
547  }
548  if (((cur->type == XML_ELEMENT_NODE) ||
549  (cur->type == XML_XINCLUDE_START) ||
550  (cur->type == XML_XINCLUDE_END)) &&
551  (cur->nsDef != NULL))
552  xmlFreeNsList(cur->nsDef);
553 
554  /*
555  * we don't free names here they are interned now
556  */
557  if ((cur->type != XML_TEXT_NODE) &&
558  (cur->type != XML_COMMENT_NODE))
559  DICT_FREE(cur->name);
560 
561  if (((cur->type == XML_ELEMENT_NODE) ||
562  (cur->type == XML_TEXT_NODE)) &&
563  (reader != NULL) && (reader->ctxt != NULL) &&
564  (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
565  cur->next = reader->ctxt->freeElems;
566  reader->ctxt->freeElems = cur;
567  reader->ctxt->freeElemsNr++;
568  } else {
569  xmlFree(cur);
570  }
571 }
572 
573 static void
574 xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
575  xmlFreeID((xmlIDPtr) id);
576 }
577 
584 static void
585 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
586  xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
587 }
588 
596 static void
597 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
598  xmlDtdPtr extSubset, intSubset;
599 
600  if (cur == NULL) return;
601 
604 
605  /*
606  * Do this before freeing the children list to avoid ID lookups
607  */
608  if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
609  cur->ids = NULL;
610  if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
611  cur->refs = NULL;
612  extSubset = cur->extSubset;
613  intSubset = cur->intSubset;
614  if (intSubset == extSubset)
615  extSubset = NULL;
616  if (extSubset != NULL) {
617  xmlUnlinkNode((xmlNodePtr) cur->extSubset);
618  cur->extSubset = NULL;
619  xmlFreeDtd(extSubset);
620  }
621  if (intSubset != NULL) {
622  xmlUnlinkNode((xmlNodePtr) cur->intSubset);
623  cur->intSubset = NULL;
624  xmlFreeDtd(intSubset);
625  }
626 
627  if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
628 
629  if (cur->version != NULL) xmlFree((char *) cur->version);
630  if (cur->name != NULL) xmlFree((char *) cur->name);
631  if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
632  if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
633  if (cur->URL != NULL) xmlFree((char *) cur->URL);
634  if (cur->dict != NULL) xmlDictFree(cur->dict);
635 
636  xmlFree(cur);
637 }
638 
639 /************************************************************************
640  * *
641  * The reader core parser *
642  * *
643  ************************************************************************/
644 #ifdef DEBUG_READER
645 static void
646 xmlTextReaderDebug(xmlTextReaderPtr reader) {
647  if ((reader == NULL) || (reader->ctxt == NULL)) {
648  fprintf(stderr, "xmlTextReader NULL\n");
649  return;
650  }
651  fprintf(stderr, "xmlTextReader: state %d depth %d ",
652  reader->state, reader->depth);
653  if (reader->node == NULL) {
654  fprintf(stderr, "node = NULL\n");
655  } else {
656  fprintf(stderr, "node %s\n", reader->node->name);
657  }
658  fprintf(stderr, " input: base %d, cur %d, depth %d: ",
659  reader->base, reader->cur, reader->ctxt->nodeNr);
660  if (reader->input->buffer == NULL) {
661  fprintf(stderr, "buffer is NULL\n");
662  } else {
663 #ifdef LIBXML_DEBUG_ENABLED
664  xmlDebugDumpString(stderr,
665  &reader->input->buffer->content[reader->cur]);
666 #endif
667  fprintf(stderr, "\n");
668  }
669 }
670 #endif
671 
681 static int
682 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
683 {
684  if (reader->entMax <= 0) {
685  reader->entMax = 10;
686  reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
687  sizeof(reader->entTab[0]));
688  if (reader->entTab == NULL) {
689  xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
690  return (0);
691  }
692  }
693  if (reader->entNr >= reader->entMax) {
694  reader->entMax *= 2;
695  reader->entTab =
696  (xmlNodePtr *) xmlRealloc(reader->entTab,
697  reader->entMax *
698  sizeof(reader->entTab[0]));
699  if (reader->entTab == NULL) {
700  xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
701  return (0);
702  }
703  }
704  reader->entTab[reader->entNr] = value;
705  reader->ent = value;
706  return (reader->entNr++);
707 }
708 
717 static xmlNodePtr
718 xmlTextReaderEntPop(xmlTextReaderPtr reader)
719 {
720  xmlNodePtr ret;
721 
722  if (reader->entNr <= 0)
723  return (NULL);
724  reader->entNr--;
725  if (reader->entNr > 0)
726  reader->ent = reader->entTab[reader->entNr - 1];
727  else
728  reader->ent = NULL;
729  ret = reader->entTab[reader->entNr];
730  reader->entTab[reader->entNr] = NULL;
731  return (ret);
732 }
733 
742 static void
743 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
744  const xmlChar **atts) {
746  xmlTextReaderPtr reader = ctxt->_private;
747 
748 #ifdef DEBUG_CALLBACKS
749  printf("xmlTextReaderStartElement(%s)\n", fullname);
750 #endif
751  if ((reader != NULL) && (reader->startElement != NULL)) {
752  reader->startElement(ctx, fullname, atts);
753  if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
754  (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
755  (ctxt->input->cur[1] == '>'))
756  ctxt->node->extra = NODE_IS_EMPTY;
757  }
758  if (reader != NULL)
759  reader->state = XML_TEXTREADER_ELEMENT;
760 }
761 
769 static void
770 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
772  xmlTextReaderPtr reader = ctxt->_private;
773 
774 #ifdef DEBUG_CALLBACKS
775  printf("xmlTextReaderEndElement(%s)\n", fullname);
776 #endif
777  if ((reader != NULL) && (reader->endElement != NULL)) {
778  reader->endElement(ctx, fullname);
779  }
780 }
781 
797 static void
798 xmlTextReaderStartElementNs(void *ctx,
799  const xmlChar *localname,
800  const xmlChar *prefix,
801  const xmlChar *URI,
802  int nb_namespaces,
803  const xmlChar **namespaces,
804  int nb_attributes,
805  int nb_defaulted,
806  const xmlChar **attributes)
807 {
809  xmlTextReaderPtr reader = ctxt->_private;
810 
811 #ifdef DEBUG_CALLBACKS
812  printf("xmlTextReaderStartElementNs(%s)\n", localname);
813 #endif
814  if ((reader != NULL) && (reader->startElementNs != NULL)) {
815  reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
816  namespaces, nb_attributes, nb_defaulted,
817  attributes);
818  if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
819  (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
820  (ctxt->input->cur[1] == '>'))
821  ctxt->node->extra = NODE_IS_EMPTY;
822  }
823  if (reader != NULL)
824  reader->state = XML_TEXTREADER_ELEMENT;
825 }
826 
836 static void
837 xmlTextReaderEndElementNs(void *ctx,
838  const xmlChar * localname,
839  const xmlChar * prefix,
840  const xmlChar * URI)
841 {
843  xmlTextReaderPtr reader = ctxt->_private;
844 
845 #ifdef DEBUG_CALLBACKS
846  printf("xmlTextReaderEndElementNs(%s)\n", localname);
847 #endif
848  if ((reader != NULL) && (reader->endElementNs != NULL)) {
849  reader->endElementNs(ctx, localname, prefix, URI);
850  }
851 }
852 
853 
862 static void
863 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
864 {
866  xmlTextReaderPtr reader = ctxt->_private;
867 
868 #ifdef DEBUG_CALLBACKS
869  printf("xmlTextReaderCharacters()\n");
870 #endif
871  if ((reader != NULL) && (reader->characters != NULL)) {
872  reader->characters(ctx, ch, len);
873  }
874 }
875 
884 static void
885 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
886 {
888  xmlTextReaderPtr reader = ctxt->_private;
889 
890 #ifdef DEBUG_CALLBACKS
891  printf("xmlTextReaderCDataBlock()\n");
892 #endif
893  if ((reader != NULL) && (reader->cdataBlock != NULL)) {
894  reader->cdataBlock(ctx, ch, len);
895  }
896 }
897 
907 static int
908 xmlTextReaderPushData(xmlTextReaderPtr reader) {
910  int val, s;
911  xmlTextReaderState oldstate;
912  int alloc;
913 
914  if ((reader->input == NULL) || (reader->input->buffer == NULL))
915  return(-1);
916 
917  oldstate = reader->state;
918  reader->state = XML_TEXTREADER_NONE;
919  inbuf = reader->input->buffer;
921 
922  while (reader->state == XML_TEXTREADER_NONE) {
923  if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
924  /*
925  * Refill the buffer unless we are at the end of the stream
926  */
927  if (reader->mode != XML_TEXTREADER_MODE_EOF) {
928  val = xmlParserInputBufferRead(reader->input, 4096);
929  if ((val == 0) &&
931  if (xmlBufUse(inbuf) == reader->cur) {
932  reader->mode = XML_TEXTREADER_MODE_EOF;
933  reader->state = oldstate;
934  }
935  } else if (val < 0) {
936  reader->mode = XML_TEXTREADER_MODE_EOF;
937  reader->state = oldstate;
938  if ((oldstate != XML_TEXTREADER_START) ||
939  (reader->ctxt->myDoc != NULL))
940  return(val);
941  } else if (val == 0) {
942  /* mark the end of the stream and process the remains */
943  reader->mode = XML_TEXTREADER_MODE_EOF;
944  break;
945  }
946 
947  } else
948  break;
949  }
950  /*
951  * parse by block of CHUNK_SIZE bytes, various tests show that
952  * it's the best tradeoff at least on a 1.2GH Duron
953  */
954  if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
955  val = xmlParseChunk(reader->ctxt,
956  (const char *) xmlBufContent(inbuf) + reader->cur,
957  CHUNK_SIZE, 0);
958  reader->cur += CHUNK_SIZE;
959  if (val != 0)
960  reader->ctxt->wellFormed = 0;
961  if (reader->ctxt->wellFormed == 0)
962  break;
963  } else {
964  s = xmlBufUse(inbuf) - reader->cur;
965  val = xmlParseChunk(reader->ctxt,
966  (const char *) xmlBufContent(inbuf) + reader->cur,
967  s, 0);
968  reader->cur += s;
969  if (val != 0)
970  reader->ctxt->wellFormed = 0;
971  break;
972  }
973  }
974 
975  /*
976  * Discard the consumed input when needed and possible
977  */
978  if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
980  if ((reader->cur >= 4096) &&
981  (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
982  val = xmlBufShrink(inbuf, reader->cur);
983  if (val >= 0) {
984  reader->cur -= val;
985  }
986  }
987  }
988  }
989 
990  /*
991  * At the end of the stream signal that the work is done to the Push
992  * parser.
993  */
994  else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
995  if (reader->state != XML_TEXTREADER_DONE) {
996  s = xmlBufUse(inbuf) - reader->cur;
997  val = xmlParseChunk(reader->ctxt,
998  (const char *) xmlBufContent(inbuf) + reader->cur,
999  s, 1);
1000  reader->cur = xmlBufUse(inbuf);
1001  reader->state = XML_TEXTREADER_DONE;
1002  if (val != 0) {
1003  if (reader->ctxt->wellFormed)
1004  reader->ctxt->wellFormed = 0;
1005  else
1006  return(-1);
1007  }
1008  }
1009  }
1010  reader->state = oldstate;
1011  if (reader->ctxt->wellFormed == 0) {
1012  reader->mode = XML_TEXTREADER_MODE_EOF;
1013  return(-1);
1014  }
1015 
1016  return(0);
1017 }
1018 
1019 #ifdef LIBXML_REGEXP_ENABLED
1020 
1026 static void
1027 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
1028  xmlNodePtr node = reader->node;
1029 
1030 #ifdef LIBXML_VALID_ENABLED
1031  if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1032  (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1033  if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1034  reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
1035  reader->ctxt->myDoc, node, node->name);
1036  } else {
1037  /* TODO use the BuildQName interface */
1038  xmlChar *qname;
1039 
1040  qname = xmlStrdup(node->ns->prefix);
1041  qname = xmlStrcat(qname, BAD_CAST ":");
1042  qname = xmlStrcat(qname, node->name);
1043  reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
1044  reader->ctxt->myDoc, node, qname);
1045  if (qname != NULL)
1046  xmlFree(qname);
1047  }
1048  }
1049 #endif /* LIBXML_VALID_ENABLED */
1050 #ifdef LIBXML_SCHEMAS_ENABLED
1051  if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1052  (reader->rngValidCtxt != NULL)) {
1053  int ret;
1054 
1055  if (reader->rngFullNode != NULL) return;
1056  ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
1057  reader->ctxt->myDoc,
1058  node);
1059  if (ret == 0) {
1060  /*
1061  * this element requires a full tree
1062  */
1063  node = xmlTextReaderExpand(reader);
1064  if (node == NULL) {
1065  ret = -1;
1066  } else {
1067  ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
1068  reader->ctxt->myDoc,
1069  node);
1070  reader->rngFullNode = node;
1071  }
1072  }
1073  if (ret != 1)
1074  reader->rngValidErrors++;
1075  }
1076 #endif
1077 }
1078 
1087 static void
1088 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
1089  const xmlChar *data, int len) {
1090 #ifdef LIBXML_VALID_ENABLED
1091  if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1092  (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1093  reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1094  data, len);
1095  }
1096 #endif /* LIBXML_VALID_ENABLED */
1097 #ifdef LIBXML_SCHEMAS_ENABLED
1098  if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1099  (reader->rngValidCtxt != NULL)) {
1100  int ret;
1101 
1102  if (reader->rngFullNode != NULL) return;
1103  ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1104  if (ret != 1)
1105  reader->rngValidErrors++;
1106  }
1107 #endif
1108 }
1109 
1116 static void
1117 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1118  xmlNodePtr node = reader->node;
1119 
1120 #ifdef LIBXML_VALID_ENABLED
1121  if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1122  (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1123  if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1124  reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1125  reader->ctxt->myDoc, node, node->name);
1126  } else {
1127  /* TODO use the BuildQName interface */
1128  xmlChar *qname;
1129 
1130  qname = xmlStrdup(node->ns->prefix);
1131  qname = xmlStrcat(qname, BAD_CAST ":");
1132  qname = xmlStrcat(qname, node->name);
1133  reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1134  reader->ctxt->myDoc, node, qname);
1135  if (qname != NULL)
1136  xmlFree(qname);
1137  }
1138  }
1139 #endif /* LIBXML_VALID_ENABLED */
1140 #ifdef LIBXML_SCHEMAS_ENABLED
1141  if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1142  (reader->rngValidCtxt != NULL)) {
1143  int ret;
1144 
1145  if (reader->rngFullNode != NULL) {
1146  if (node == reader->rngFullNode)
1147  reader->rngFullNode = NULL;
1148  return;
1149  }
1150  ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1151  reader->ctxt->myDoc,
1152  node);
1153  if (ret != 1)
1154  reader->rngValidErrors++;
1155  }
1156 #endif
1157 }
1158 
1167 static void
1168 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1169  xmlNodePtr oldnode = reader->node;
1170  xmlNodePtr node = reader->node;
1171 
1172  do {
1173  if (node->type == XML_ENTITY_REF_NODE) {
1174  if ((node->children != NULL) &&
1175  (node->children->type == XML_ENTITY_DECL) &&
1176  (node->children->children != NULL)) {
1177  xmlTextReaderEntPush(reader, node);
1178  node = node->children->children;
1179  continue;
1180  } else {
1181  /*
1182  * The error has probably been raised already.
1183  */
1184  if (node == oldnode)
1185  break;
1186  goto skip_children;
1187  }
1188 #ifdef LIBXML_REGEXP_ENABLED
1189  } else if (node->type == XML_ELEMENT_NODE) {
1190  reader->node = node;
1191  xmlTextReaderValidatePush(reader);
1192  } else if ((node->type == XML_TEXT_NODE) ||
1193  (node->type == XML_CDATA_SECTION_NODE)) {
1194  xmlTextReaderValidateCData(reader, node->content,
1195  xmlStrlen(node->content));
1196 #endif
1197  }
1198 
1199  /*
1200  * go to next node
1201  */
1202  if (node->children != NULL) {
1203  node = node->children;
1204  continue;
1205  } else if (node->type == XML_ELEMENT_NODE) {
1206  xmlTextReaderValidatePop(reader);
1207  }
1208 skip_children:
1209  if (node->next != NULL) {
1210  node = node->next;
1211  continue;
1212  }
1213  do {
1214  node = node->parent;
1215  if (node->type == XML_ELEMENT_NODE) {
1216  xmlNodePtr tmp;
1217  if (reader->entNr == 0) {
1218  while ((tmp = node->last) != NULL) {
1219  if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1220  xmlUnlinkNode(tmp);
1221  xmlTextReaderFreeNode(reader, tmp);
1222  } else
1223  break;
1224  }
1225  }
1226  reader->node = node;
1227  xmlTextReaderValidatePop(reader);
1228  }
1229  if ((node->type == XML_ENTITY_DECL) &&
1230  (reader->ent != NULL) && (reader->ent->children == node)) {
1231  node = xmlTextReaderEntPop(reader);
1232  }
1233  if (node == oldnode)
1234  break;
1235  if (node->next != NULL) {
1236  node = node->next;
1237  break;
1238  }
1239  } while ((node != NULL) && (node != oldnode));
1240  } while ((node != NULL) && (node != oldnode));
1241  reader->node = oldnode;
1242 }
1243 #endif /* LIBXML_REGEXP_ENABLED */
1244 
1245 
1254 static xmlNodePtr
1255 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1256  if (cur == NULL) return(NULL) ; /* ERROR */
1257  if (cur->next != NULL) return(cur->next) ;
1258  do {
1259  cur = cur->parent;
1260  if (cur == NULL) break;
1261  if (cur->next != NULL) return(cur->next);
1262  } while (cur != NULL);
1263  return(cur);
1264 }
1265 
1277 static int
1278 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1279  int val;
1280 
1281  if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1282  return(-1);
1283  do {
1284  if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1285 
1286  if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1287  return(1);
1288  if (reader->ctxt->nodeNr < reader->depth)
1289  return(1);
1290  if (reader->mode == XML_TEXTREADER_MODE_EOF)
1291  return(1);
1292  val = xmlTextReaderPushData(reader);
1293  if (val < 0){
1294  reader->mode = XML_TEXTREADER_MODE_ERROR;
1295  return(-1);
1296  }
1297  } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1298  return(1);
1299 }
1300 
1311 static xmlChar *
1312 xmlTextReaderCollectSiblings(xmlNodePtr node)
1313 {
1315  xmlChar *ret;
1316 
1317  if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1318  return(NULL);
1319 
1320  buffer = xmlBufferCreate();
1321  if (buffer == NULL)
1322  return NULL;
1323 
1324  for ( ; node != NULL; node = node->next) {
1325  switch (node->type) {
1326  case XML_TEXT_NODE:
1328  xmlBufferCat(buffer, node->content);
1329  break;
1330  case XML_ELEMENT_NODE: {
1331  xmlChar *tmp;
1332 
1333  tmp = xmlTextReaderCollectSiblings(node->children);
1334  xmlBufferCat(buffer, tmp);
1335  xmlFree(tmp);
1336  break;
1337  }
1338  default:
1339  break;
1340  }
1341  }
1342  ret = buffer->content;
1343  buffer->content = NULL;
1345  return(ret);
1346 }
1347 
1358 int
1359 xmlTextReaderRead(xmlTextReaderPtr reader) {
1360  int val, olddepth = 0;
1361  xmlTextReaderState oldstate = XML_TEXTREADER_START;
1362  xmlNodePtr oldnode = NULL;
1363 
1364 
1365  if (reader == NULL)
1366  return(-1);
1367  reader->curnode = NULL;
1368  if (reader->doc != NULL)
1369  return(xmlTextReaderReadTree(reader));
1370  if (reader->ctxt == NULL)
1371  return(-1);
1372 
1373 #ifdef DEBUG_READER
1374  fprintf(stderr, "\nREAD ");
1375  DUMP_READER
1376 #endif
1377  if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1378  reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1379  /*
1380  * Initial state
1381  */
1382  do {
1383  val = xmlTextReaderPushData(reader);
1384  if (val < 0){
1385  reader->mode = XML_TEXTREADER_MODE_ERROR;
1386  reader->state = XML_TEXTREADER_ERROR;
1387  return(-1);
1388  }
1389  } while ((reader->ctxt->node == NULL) &&
1390  ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1391  (reader->state != XML_TEXTREADER_DONE)));
1392  if (reader->ctxt->node == NULL) {
1393  if (reader->ctxt->myDoc != NULL) {
1394  reader->node = reader->ctxt->myDoc->children;
1395  }
1396  if (reader->node == NULL){
1397  reader->mode = XML_TEXTREADER_MODE_ERROR;
1398  reader->state = XML_TEXTREADER_ERROR;
1399  return(-1);
1400  }
1401  reader->state = XML_TEXTREADER_ELEMENT;
1402  } else {
1403  if (reader->ctxt->myDoc != NULL) {
1404  reader->node = reader->ctxt->myDoc->children;
1405  }
1406  if (reader->node == NULL)
1407  reader->node = reader->ctxt->nodeTab[0];
1408  reader->state = XML_TEXTREADER_ELEMENT;
1409  }
1410  reader->depth = 0;
1411  reader->ctxt->parseMode = XML_PARSE_READER;
1412  goto node_found;
1413  }
1414  oldstate = reader->state;
1415  olddepth = reader->ctxt->nodeNr;
1416  oldnode = reader->node;
1417 
1418 get_next_node:
1419  if (reader->node == NULL) {
1420  if (reader->mode == XML_TEXTREADER_MODE_EOF)
1421  return(0);
1422  else
1423  return(-1);
1424  }
1425 
1426  /*
1427  * If we are not backtracking on ancestors or examined nodes,
1428  * that the parser didn't finished or that we aren't at the end
1429  * of stream, continue processing.
1430  */
1431  while ((reader->node != NULL) && (reader->node->next == NULL) &&
1432  (reader->ctxt->nodeNr == olddepth) &&
1433  ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1434  (reader->node->children == NULL) ||
1435  (reader->node->type == XML_ENTITY_REF_NODE) ||
1436  ((reader->node->children != NULL) &&
1437  (reader->node->children->type == XML_TEXT_NODE) &&
1438  (reader->node->children->next == NULL)) ||
1439  (reader->node->type == XML_DTD_NODE) ||
1440  (reader->node->type == XML_DOCUMENT_NODE) ||
1441  (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1442  ((reader->ctxt->node == NULL) ||
1443  (reader->ctxt->node == reader->node) ||
1444  (reader->ctxt->node == reader->node->parent)) &&
1445  (reader->ctxt->instate != XML_PARSER_EOF)) {
1446  val = xmlTextReaderPushData(reader);
1447  if (val < 0){
1448  reader->mode = XML_TEXTREADER_MODE_ERROR;
1449  reader->state = XML_TEXTREADER_ERROR;
1450  return(-1);
1451  }
1452  if (reader->node == NULL)
1453  goto node_end;
1454  }
1455  if (oldstate != XML_TEXTREADER_BACKTRACK) {
1456  if ((reader->node->children != NULL) &&
1457  (reader->node->type != XML_ENTITY_REF_NODE) &&
1458  (reader->node->type != XML_XINCLUDE_START) &&
1459  (reader->node->type != XML_DTD_NODE)) {
1460  reader->node = reader->node->children;
1461  reader->depth++;
1462  reader->state = XML_TEXTREADER_ELEMENT;
1463  goto node_found;
1464  }
1465  }
1466  if (reader->node->next != NULL) {
1467  if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1468  (reader->node->type == XML_ELEMENT_NODE) &&
1469  (reader->node->children == NULL) &&
1470  ((reader->node->extra & NODE_IS_EMPTY) == 0)
1472  && (reader->in_xinclude <= 0)
1473 #endif
1474  ) {
1475  reader->state = XML_TEXTREADER_END;
1476  goto node_found;
1477  }
1478 #ifdef LIBXML_REGEXP_ENABLED
1479  if ((reader->validate) &&
1480  (reader->node->type == XML_ELEMENT_NODE))
1481  xmlTextReaderValidatePop(reader);
1482 #endif /* LIBXML_REGEXP_ENABLED */
1483  if ((reader->preserves > 0) &&
1484  (reader->node->extra & NODE_IS_SPRESERVED))
1485  reader->preserves--;
1486  reader->node = reader->node->next;
1487  reader->state = XML_TEXTREADER_ELEMENT;
1488 
1489  /*
1490  * Cleanup of the old node
1491  */
1492  if ((reader->preserves == 0) &&
1494  (reader->in_xinclude == 0) &&
1495 #endif
1496  (reader->entNr == 0) &&
1497  (reader->node->prev != NULL) &&
1498  (reader->node->prev->type != XML_DTD_NODE)) {
1499  xmlNodePtr tmp = reader->node->prev;
1500  if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1501  if (oldnode == tmp)
1502  oldnode = NULL;
1503  xmlUnlinkNode(tmp);
1504  xmlTextReaderFreeNode(reader, tmp);
1505  }
1506  }
1507 
1508  goto node_found;
1509  }
1510  if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1511  (reader->node->type == XML_ELEMENT_NODE) &&
1512  (reader->node->children == NULL) &&
1513  ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1514  reader->state = XML_TEXTREADER_END;
1515  goto node_found;
1516  }
1517 #ifdef LIBXML_REGEXP_ENABLED
1518  if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1519  xmlTextReaderValidatePop(reader);
1520 #endif /* LIBXML_REGEXP_ENABLED */
1521  if ((reader->preserves > 0) &&
1522  (reader->node->extra & NODE_IS_SPRESERVED))
1523  reader->preserves--;
1524  reader->node = reader->node->parent;
1525  if ((reader->node == NULL) ||
1526  (reader->node->type == XML_DOCUMENT_NODE) ||
1527 #ifdef LIBXML_DOCB_ENABLED
1528  (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1529 #endif
1530  (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1531  if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1532  val = xmlParseChunk(reader->ctxt, "", 0, 1);
1533  reader->state = XML_TEXTREADER_DONE;
1534  if (val != 0)
1535  return(-1);
1536  }
1537  reader->node = NULL;
1538  reader->depth = -1;
1539 
1540  /*
1541  * Cleanup of the old node
1542  */
1543  if ((oldnode != NULL) && (reader->preserves == 0) &&
1545  (reader->in_xinclude == 0) &&
1546 #endif
1547  (reader->entNr == 0) &&
1548  (oldnode->type != XML_DTD_NODE) &&
1549  ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1550  xmlUnlinkNode(oldnode);
1551  xmlTextReaderFreeNode(reader, oldnode);
1552  }
1553 
1554  goto node_end;
1555  }
1556  if ((reader->preserves == 0) &&
1558  (reader->in_xinclude == 0) &&
1559 #endif
1560  (reader->entNr == 0) &&
1561  (reader->node->last != NULL) &&
1562  ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1563  xmlNodePtr tmp = reader->node->last;
1564  xmlUnlinkNode(tmp);
1565  xmlTextReaderFreeNode(reader, tmp);
1566  }
1567  reader->depth--;
1568  reader->state = XML_TEXTREADER_BACKTRACK;
1569 
1570 node_found:
1571  DUMP_READER
1572 
1573  /*
1574  * If we are in the middle of a piece of CDATA make sure it's finished
1575  */
1576  if ((reader->node != NULL) &&
1577  (reader->node->next == NULL) &&
1578  ((reader->node->type == XML_TEXT_NODE) ||
1579  (reader->node->type == XML_CDATA_SECTION_NODE))) {
1580  if (xmlTextReaderExpand(reader) == NULL)
1581  return -1;
1582  }
1583 
1584 #ifdef LIBXML_XINCLUDE_ENABLED
1585  /*
1586  * Handle XInclude if asked for
1587  */
1588  if ((reader->xinclude) && (reader->in_xinclude == 0) &&
1589  (reader->node != NULL) &&
1590  (reader->node->type == XML_ELEMENT_NODE) &&
1591  (reader->node->ns != NULL) &&
1592  ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1593  (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1594  if (reader->xincctxt == NULL) {
1595  reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1596  xmlXIncludeSetFlags(reader->xincctxt,
1597  reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1598  }
1599  /*
1600  * expand that node and process it
1601  */
1602  if (xmlTextReaderExpand(reader) == NULL)
1603  return -1;
1604  xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1605  }
1606  if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1607  reader->in_xinclude++;
1608  goto get_next_node;
1609  }
1610  if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1611  reader->in_xinclude--;
1612  goto get_next_node;
1613  }
1614 #endif
1615  /*
1616  * Handle entities enter and exit when in entity replacement mode
1617  */
1618  if ((reader->node != NULL) &&
1619  (reader->node->type == XML_ENTITY_REF_NODE) &&
1620  (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1621  if ((reader->node->children != NULL) &&
1622  (reader->node->children->type == XML_ENTITY_DECL) &&
1623  (reader->node->children->children != NULL)) {
1624  xmlTextReaderEntPush(reader, reader->node);
1625  reader->node = reader->node->children->children;
1626  }
1627 #ifdef LIBXML_REGEXP_ENABLED
1628  } else if ((reader->node != NULL) &&
1629  (reader->node->type == XML_ENTITY_REF_NODE) &&
1630  (reader->ctxt != NULL) && (reader->validate)) {
1631  xmlTextReaderValidateEntity(reader);
1632 #endif /* LIBXML_REGEXP_ENABLED */
1633  }
1634  if ((reader->node != NULL) &&
1635  (reader->node->type == XML_ENTITY_DECL) &&
1636  (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1637  reader->node = xmlTextReaderEntPop(reader);
1638  reader->depth++;
1639  goto get_next_node;
1640  }
1641 #ifdef LIBXML_REGEXP_ENABLED
1642  if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1643  xmlNodePtr node = reader->node;
1644 
1645  if ((node->type == XML_ELEMENT_NODE) &&
1646  ((reader->state != XML_TEXTREADER_END) &&
1647  (reader->state != XML_TEXTREADER_BACKTRACK))) {
1648  xmlTextReaderValidatePush(reader);
1649  } else if ((node->type == XML_TEXT_NODE) ||
1650  (node->type == XML_CDATA_SECTION_NODE)) {
1651  xmlTextReaderValidateCData(reader, node->content,
1652  xmlStrlen(node->content));
1653  }
1654  }
1655 #endif /* LIBXML_REGEXP_ENABLED */
1656 #ifdef LIBXML_PATTERN_ENABLED
1657  if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1658  (reader->state != XML_TEXTREADER_BACKTRACK)) {
1659  int i;
1660  for (i = 0;i < reader->patternNr;i++) {
1661  if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1662  xmlTextReaderPreserve(reader);
1663  break;
1664  }
1665  }
1666  }
1667 #endif /* LIBXML_PATTERN_ENABLED */
1668 #ifdef LIBXML_SCHEMAS_ENABLED
1669  if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1670  (reader->xsdValidErrors == 0) &&
1671  (reader->xsdValidCtxt != NULL)) {
1672  reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1673  }
1674 #endif /* LIBXML_PATTERN_ENABLED */
1675  return(1);
1676 node_end:
1677  reader->state = XML_TEXTREADER_DONE;
1678  return(0);
1679 }
1680 
1689 int
1690 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1691  if (reader == NULL)
1692  return(-1);
1693  return(reader->mode);
1694 }
1695 
1706 xmlNodePtr
1707 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1708  if ((reader == NULL) || (reader->node == NULL))
1709  return(NULL);
1710  if (reader->doc != NULL)
1711  return(reader->node);
1712  if (reader->ctxt == NULL)
1713  return(NULL);
1714  if (xmlTextReaderDoExpand(reader) < 0)
1715  return(NULL);
1716  return(reader->node);
1717 }
1718 
1729 int
1730 xmlTextReaderNext(xmlTextReaderPtr reader) {
1731  int ret;
1732  xmlNodePtr cur;
1733 
1734  if (reader == NULL)
1735  return(-1);
1736  if (reader->doc != NULL)
1737  return(xmlTextReaderNextTree(reader));
1738  cur = reader->node;
1739  if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1740  return(xmlTextReaderRead(reader));
1741  if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1742  return(xmlTextReaderRead(reader));
1743  if (cur->extra & NODE_IS_EMPTY)
1744  return(xmlTextReaderRead(reader));
1745  do {
1746  ret = xmlTextReaderRead(reader);
1747  if (ret != 1)
1748  return(ret);
1749  } while (reader->node != cur);
1750  return(xmlTextReaderRead(reader));
1751 }
1752 
1753 #ifdef LIBXML_WRITER_ENABLED
1754 
1764 xmlChar *
1765 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1766 {
1767  xmlChar *resbuf;
1768  xmlNodePtr node, cur_node;
1769  xmlBufferPtr buff, buff2;
1770  xmlDocPtr doc;
1771 
1772  if (xmlTextReaderExpand(reader) == NULL) {
1773  return NULL;
1774  }
1775  doc = reader->node->doc;
1776  buff = xmlBufferCreate();
1777  if (buff == NULL)
1778  return NULL;
1779  for (cur_node = reader->node->children; cur_node != NULL;
1780  cur_node = cur_node->next) {
1781  /* XXX: Why is the node copied? */
1782  node = xmlDocCopyNode(cur_node, doc, 1);
1783  buff2 = xmlBufferCreate();
1784  if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1785  xmlFreeNode(node);
1786  xmlBufferFree(buff2);
1788  return NULL;
1789  }
1790  xmlBufferCat(buff, buff2->content);
1791  xmlFreeNode(node);
1792  xmlBufferFree(buff2);
1793  }
1794  resbuf = buff->content;
1795  buff->content = NULL;
1796 
1798  return resbuf;
1799 }
1800 #endif
1801 
1802 #ifdef LIBXML_WRITER_ENABLED
1803 
1813 xmlChar *
1814 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1815 {
1816  xmlChar *resbuf;
1817  xmlNodePtr node;
1819  xmlDocPtr doc;
1820 
1821  if (xmlTextReaderExpand(reader) == NULL) {
1822  return NULL;
1823  }
1824  node = reader->node;
1825  doc = node->doc;
1826  /* XXX: Why is the node copied? */
1827  if (node->type == XML_DTD_NODE) {
1828  node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1829  } else {
1830  node = xmlDocCopyNode(node, doc, 1);
1831  }
1832  buff = xmlBufferCreate();
1833  if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1834  xmlFreeNode(node);
1836  return NULL;
1837  }
1838 
1839  resbuf = buff->content;
1840  buff->content = NULL;
1841 
1842  xmlFreeNode(node);
1844  return resbuf;
1845 }
1846 #endif
1847 
1858 xmlChar *
1859 xmlTextReaderReadString(xmlTextReaderPtr reader)
1860 {
1861  xmlNodePtr node;
1862 
1863  if ((reader == NULL) || (reader->node == NULL))
1864  return(NULL);
1865 
1866  node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1867  switch (node->type) {
1868  case XML_TEXT_NODE:
1869  if (node->content != NULL)
1870  return(xmlStrdup(node->content));
1871  break;
1872  case XML_ELEMENT_NODE:
1873  if (xmlTextReaderDoExpand(reader) != -1) {
1874  return xmlTextReaderCollectSiblings(node->children);
1875  }
1876  break;
1877  case XML_ATTRIBUTE_NODE:
1878  TODO
1879  break;
1880  default:
1881  break;
1882  }
1883  return(NULL);
1884 }
1885 
1886 #if 0
1887 
1901 int
1902 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1903  unsigned char *array ATTRIBUTE_UNUSED,
1905  int len ATTRIBUTE_UNUSED) {
1906  if ((reader == NULL) || (reader->ctxt == NULL))
1907  return(-1);
1908  if (reader->ctxt->wellFormed != 1)
1909  return(-1);
1910 
1911  if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1912  return(0);
1913  TODO
1914  return(0);
1915 }
1916 
1931 int
1932 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1933  unsigned char *array ATTRIBUTE_UNUSED,
1935  int len ATTRIBUTE_UNUSED) {
1936  if ((reader == NULL) || (reader->ctxt == NULL))
1937  return(-1);
1938  if (reader->ctxt->wellFormed != 1)
1939  return(-1);
1940 
1941  if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1942  return(0);
1943  TODO
1944  return(0);
1945 }
1946 #endif
1947 
1948 /************************************************************************
1949  * *
1950  * Operating on a preparsed tree *
1951  * *
1952  ************************************************************************/
1953 static int
1954 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1955 {
1956  if (reader == NULL)
1957  return(-1);
1958 
1959  if (reader->state == XML_TEXTREADER_END)
1960  return(0);
1961 
1962  if (reader->node == NULL) {
1963  if (reader->doc->children == NULL) {
1964  reader->state = XML_TEXTREADER_END;
1965  return(0);
1966  }
1967 
1968  reader->node = reader->doc->children;
1969  reader->state = XML_TEXTREADER_START;
1970  return(1);
1971  }
1972 
1973  if (reader->state != XML_TEXTREADER_BACKTRACK) {
1974  /* Here removed traversal to child, because we want to skip the subtree,
1975  replace with traversal to sibling to skip subtree */
1976  if (reader->node->next != 0) {
1977  /* Move to sibling if present,skipping sub-tree */
1978  reader->node = reader->node->next;
1979  reader->state = XML_TEXTREADER_START;
1980  return(1);
1981  }
1982 
1983  /* if reader->node->next is NULL mean no subtree for current node,
1984  so need to move to sibling of parent node if present */
1985  reader->state = XML_TEXTREADER_BACKTRACK;
1986  /* This will move to parent if present */
1987  xmlTextReaderRead(reader);
1988  }
1989 
1990  if (reader->node->next != 0) {
1991  reader->node = reader->node->next;
1992  reader->state = XML_TEXTREADER_START;
1993  return(1);
1994  }
1995 
1996  if (reader->node->parent != 0) {
1997  if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1998  reader->state = XML_TEXTREADER_END;
1999  return(0);
2000  }
2001 
2002  reader->node = reader->node->parent;
2003  reader->depth--;
2004  reader->state = XML_TEXTREADER_BACKTRACK;
2005  /* Repeat process to move to sibling of parent node if present */
2006  xmlTextReaderNextTree(reader);
2007  }
2008 
2009  reader->state = XML_TEXTREADER_END;
2010 
2011  return(1);
2012 }
2013 
2024 static int
2025 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
2026  if (reader->state == XML_TEXTREADER_END)
2027  return(0);
2028 
2029 next_node:
2030  if (reader->node == NULL) {
2031  if (reader->doc->children == NULL) {
2032  reader->state = XML_TEXTREADER_END;
2033  return(0);
2034  }
2035 
2036  reader->node = reader->doc->children;
2037  reader->state = XML_TEXTREADER_START;
2038  goto found_node;
2039  }
2040 
2041  if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
2042  (reader->node->type != XML_DTD_NODE) &&
2043  (reader->node->type != XML_XINCLUDE_START) &&
2044  (reader->node->type != XML_ENTITY_REF_NODE)) {
2045  if (reader->node->children != NULL) {
2046  reader->node = reader->node->children;
2047  reader->depth++;
2048  reader->state = XML_TEXTREADER_START;
2049  goto found_node;
2050  }
2051 
2052  if (reader->node->type == XML_ATTRIBUTE_NODE) {
2053  reader->state = XML_TEXTREADER_BACKTRACK;
2054  goto found_node;
2055  }
2056  }
2057 
2058  if (reader->node->next != NULL) {
2059  reader->node = reader->node->next;
2060  reader->state = XML_TEXTREADER_START;
2061  goto found_node;
2062  }
2063 
2064  if (reader->node->parent != NULL) {
2065  if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
2066  (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2067  reader->state = XML_TEXTREADER_END;
2068  return(0);
2069  }
2070 
2071  reader->node = reader->node->parent;
2072  reader->depth--;
2073  reader->state = XML_TEXTREADER_BACKTRACK;
2074  goto found_node;
2075  }
2076 
2077  reader->state = XML_TEXTREADER_END;
2078 
2079 found_node:
2080  if ((reader->node->type == XML_XINCLUDE_START) ||
2081  (reader->node->type == XML_XINCLUDE_END))
2082  goto next_node;
2083 
2084  return(1);
2085 }
2086 
2098 int
2099 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2100  if (reader == NULL)
2101  return(-1);
2102  if (reader->doc == NULL) {
2103  /* TODO */
2104  return(-1);
2105  }
2106 
2107  if (reader->state == XML_TEXTREADER_END)
2108  return(0);
2109 
2110  if (reader->node == NULL)
2111  return(xmlTextReaderNextTree(reader));
2112 
2113  if (reader->node->next != NULL) {
2114  reader->node = reader->node->next;
2115  reader->state = XML_TEXTREADER_START;
2116  return(1);
2117  }
2118 
2119  return(0);
2120 }
2121 
2122 /************************************************************************
2123  * *
2124  * Constructor and destructors *
2125  * *
2126  ************************************************************************/
2136 xmlTextReaderPtr
2137 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2138  xmlTextReaderPtr ret;
2139 
2140  if (input == NULL)
2141  return(NULL);
2142  ret = xmlMalloc(sizeof(xmlTextReader));
2143  if (ret == NULL) {
2145  "xmlNewTextReader : malloc failed\n");
2146  return(NULL);
2147  }
2148  memset(ret, 0, sizeof(xmlTextReader));
2149  ret->doc = NULL;
2150  ret->entTab = NULL;
2151  ret->entMax = 0;
2152  ret->entNr = 0;
2153  ret->input = input;
2154  ret->buffer = xmlBufCreateSize(100);
2155  if (ret->buffer == NULL) {
2156  xmlFree(ret);
2158  "xmlNewTextReader : malloc failed\n");
2159  return(NULL);
2160  }
2161  /* no operation on a reader should require a huge buffer */
2164  ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2165  if (ret->sax == NULL) {
2166  xmlBufFree(ret->buffer);
2167  xmlFree(ret);
2169  "xmlNewTextReader : malloc failed\n");
2170  return(NULL);
2171  }
2172  xmlSAXVersion(ret->sax, 2);
2173  ret->startElement = ret->sax->startElement;
2174  ret->sax->startElement = xmlTextReaderStartElement;
2175  ret->endElement = ret->sax->endElement;
2176  ret->sax->endElement = xmlTextReaderEndElement;
2177 #ifdef LIBXML_SAX1_ENABLED
2178  if (ret->sax->initialized == XML_SAX2_MAGIC) {
2179 #endif /* LIBXML_SAX1_ENABLED */
2180  ret->startElementNs = ret->sax->startElementNs;
2181  ret->sax->startElementNs = xmlTextReaderStartElementNs;
2182  ret->endElementNs = ret->sax->endElementNs;
2183  ret->sax->endElementNs = xmlTextReaderEndElementNs;
2184 #ifdef LIBXML_SAX1_ENABLED
2185  } else {
2186  ret->startElementNs = NULL;
2187  ret->endElementNs = NULL;
2188  }
2189 #endif /* LIBXML_SAX1_ENABLED */
2190  ret->characters = ret->sax->characters;
2191  ret->sax->characters = xmlTextReaderCharacters;
2192  ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2193  ret->cdataBlock = ret->sax->cdataBlock;
2194  ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2195 
2196  ret->mode = XML_TEXTREADER_MODE_INITIAL;
2197  ret->node = NULL;
2198  ret->curnode = NULL;
2199  if (xmlBufUse(ret->input->buffer) < 4) {
2201  }
2202  if (xmlBufUse(ret->input->buffer) >= 4) {
2203  ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2204  (const char *) xmlBufContent(ret->input->buffer),
2205  4, URI);
2206  ret->base = 0;
2207  ret->cur = 4;
2208  } else {
2209  ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2210  ret->base = 0;
2211  ret->cur = 0;
2212  }
2213 
2214  if (ret->ctxt == NULL) {
2216  "xmlNewTextReader : malloc failed\n");
2217  xmlBufFree(ret->buffer);
2218  xmlFree(ret->sax);
2219  xmlFree(ret);
2220  return(NULL);
2221  }
2222  ret->ctxt->parseMode = XML_PARSE_READER;
2223  ret->ctxt->_private = ret;
2224  ret->ctxt->linenumbers = 1;
2225  ret->ctxt->dictNames = 1;
2226  ret->allocs = XML_TEXTREADER_CTXT;
2227  /*
2228  * use the parser dictionary to allocate all elements and attributes names
2229  */
2230  ret->ctxt->docdict = 1;
2231  ret->dict = ret->ctxt->dict;
2232 #ifdef LIBXML_XINCLUDE_ENABLED
2233  ret->xinclude = 0;
2234 #endif
2235 #ifdef LIBXML_PATTERN_ENABLED
2236  ret->patternMax = 0;
2237  ret->patternTab = NULL;
2238 #endif
2239  return(ret);
2240 }
2241 
2250 xmlTextReaderPtr
2251 xmlNewTextReaderFilename(const char *URI) {
2253  xmlTextReaderPtr ret;
2254  char *directory = NULL;
2255 
2257  if (input == NULL)
2258  return(NULL);
2259  ret = xmlNewTextReader(input, URI);
2260  if (ret == NULL) {
2262  return(NULL);
2263  }
2264  ret->allocs |= XML_TEXTREADER_INPUT;
2265  if (ret->ctxt->directory == NULL)
2267  if ((ret->ctxt->directory == NULL) && (directory != NULL))
2268  ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2269  if (directory != NULL)
2270  xmlFree(directory);
2271  return(ret);
2272 }
2273 
2280 void
2281 xmlFreeTextReader(xmlTextReaderPtr reader) {
2282  if (reader == NULL)
2283  return;
2284 #ifdef LIBXML_SCHEMAS_ENABLED
2285  if (reader->rngSchemas != NULL) {
2286  xmlRelaxNGFree(reader->rngSchemas);
2287  reader->rngSchemas = NULL;
2288  }
2289  if (reader->rngValidCtxt != NULL) {
2290  if (! reader->rngPreserveCtxt)
2291  xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2292  reader->rngValidCtxt = NULL;
2293  }
2294  if (reader->xsdPlug != NULL) {
2295  xmlSchemaSAXUnplug(reader->xsdPlug);
2296  reader->xsdPlug = NULL;
2297  }
2298  if (reader->xsdValidCtxt != NULL) {
2299  if (! reader->xsdPreserveCtxt)
2300  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2301  reader->xsdValidCtxt = NULL;
2302  }
2303  if (reader->xsdSchemas != NULL) {
2304  xmlSchemaFree(reader->xsdSchemas);
2305  reader->xsdSchemas = NULL;
2306  }
2307 #endif
2308 #ifdef LIBXML_XINCLUDE_ENABLED
2309  if (reader->xincctxt != NULL)
2310  xmlXIncludeFreeContext(reader->xincctxt);
2311 #endif
2312 #ifdef LIBXML_PATTERN_ENABLED
2313  if (reader->patternTab != NULL) {
2314  int i;
2315  for (i = 0;i < reader->patternNr;i++) {
2316  if (reader->patternTab[i] != NULL)
2317  xmlFreePattern(reader->patternTab[i]);
2318  }
2319  xmlFree(reader->patternTab);
2320  }
2321 #endif
2322  if (reader->faketext != NULL) {
2323  xmlFreeNode(reader->faketext);
2324  }
2325  if (reader->ctxt != NULL) {
2326  if (reader->dict == reader->ctxt->dict)
2327  reader->dict = NULL;
2328 #ifdef LIBXML_VALID_ENABLED
2329  if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2330  (reader->ctxt->vctxt.vstateMax > 0)){
2331 #ifdef LIBXML_REGEXP_ENABLED
2332  while (reader->ctxt->vctxt.vstateNr > 0)
2333  xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2334 #endif /* LIBXML_REGEXP_ENABLED */
2335  xmlFree(reader->ctxt->vctxt.vstateTab);
2336  reader->ctxt->vctxt.vstateTab = NULL;
2337  reader->ctxt->vctxt.vstateMax = 0;
2338  }
2339 #endif /* LIBXML_VALID_ENABLED */
2340  if (reader->ctxt->myDoc != NULL) {
2341  if (reader->preserve == 0)
2342  xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2343  reader->ctxt->myDoc = NULL;
2344  }
2345  if (reader->allocs & XML_TEXTREADER_CTXT)
2346  xmlFreeParserCtxt(reader->ctxt);
2347  }
2348  if (reader->sax != NULL)
2349  xmlFree(reader->sax);
2350  if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2352  if (reader->buffer != NULL)
2353  xmlBufFree(reader->buffer);
2354  if (reader->entTab != NULL)
2355  xmlFree(reader->entTab);
2356  if (reader->dict != NULL)
2357  xmlDictFree(reader->dict);
2358  xmlFree(reader);
2359 }
2360 
2361 /************************************************************************
2362  * *
2363  * Methods for XmlTextReader *
2364  * *
2365  ************************************************************************/
2375 int
2376 xmlTextReaderClose(xmlTextReaderPtr reader) {
2377  if (reader == NULL)
2378  return(-1);
2379  reader->node = NULL;
2380  reader->curnode = NULL;
2381  reader->mode = XML_TEXTREADER_MODE_CLOSED;
2382  if (reader->ctxt != NULL) {
2383  xmlStopParser(reader->ctxt);
2384  if (reader->ctxt->myDoc != NULL) {
2385  if (reader->preserve == 0)
2386  xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2387  reader->ctxt->myDoc = NULL;
2388  }
2389  }
2390  if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2392  reader->allocs -= XML_TEXTREADER_INPUT;
2393  }
2394  return(0);
2395 }
2396 
2408 xmlChar *
2409 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2410  xmlChar *ret;
2411  int i;
2412  xmlAttrPtr cur;
2413  xmlNsPtr ns;
2414 
2415  if (reader == NULL)
2416  return(NULL);
2417  if (reader->node == NULL)
2418  return(NULL);
2419  if (reader->curnode != NULL)
2420  return(NULL);
2421  /* TODO: handle the xmlDecl */
2422  if (reader->node->type != XML_ELEMENT_NODE)
2423  return(NULL);
2424 
2425  ns = reader->node->nsDef;
2426  for (i = 0;(i < no) && (ns != NULL);i++) {
2427  ns = ns->next;
2428  }
2429  if (ns != NULL)
2430  return(xmlStrdup(ns->href));
2431 
2432  cur = reader->node->properties;
2433  if (cur == NULL)
2434  return(NULL);
2435  for (;i < no;i++) {
2436  cur = cur->next;
2437  if (cur == NULL)
2438  return(NULL);
2439  }
2440  /* TODO walk the DTD if present */
2441 
2442  ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2443  if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2444  return(ret);
2445 }
2446 
2457 xmlChar *
2458 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2459  xmlChar *prefix = NULL;
2460  xmlChar *localname;
2461  xmlNsPtr ns;
2462  xmlChar *ret = NULL;
2463 
2464  if ((reader == NULL) || (name == NULL))
2465  return(NULL);
2466  if (reader->node == NULL)
2467  return(NULL);
2468  if (reader->curnode != NULL)
2469  return(NULL);
2470 
2471  /* TODO: handle the xmlDecl */
2472  if (reader->node->type != XML_ELEMENT_NODE)
2473  return(NULL);
2474 
2475  localname = xmlSplitQName2(name, &prefix);
2476  if (localname == NULL) {
2477  /*
2478  * Namespace default decl
2479  */
2480  if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2481  ns = reader->node->nsDef;
2482  while (ns != NULL) {
2483  if (ns->prefix == NULL) {
2484  return(xmlStrdup(ns->href));
2485  }
2486  ns = ns->next;
2487  }
2488  return NULL;
2489  }
2490  return(xmlGetNoNsProp(reader->node, name));
2491  }
2492 
2493  /*
2494  * Namespace default decl
2495  */
2496  if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2497  ns = reader->node->nsDef;
2498  while (ns != NULL) {
2499  if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2500  ret = xmlStrdup(ns->href);
2501  break;
2502  }
2503  ns = ns->next;
2504  }
2505  } else {
2506  ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2507  if (ns != NULL)
2508  ret = xmlGetNsProp(reader->node, localname, ns->href);
2509  }
2510 
2511  xmlFree(localname);
2512  if (prefix != NULL)
2513  xmlFree(prefix);
2514  return(ret);
2515 }
2516 
2517 
2529 xmlChar *
2530 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2531  const xmlChar *namespaceURI) {
2532  xmlChar *prefix = NULL;
2533  xmlNsPtr ns;
2534 
2535  if ((reader == NULL) || (localName == NULL))
2536  return(NULL);
2537  if (reader->node == NULL)
2538  return(NULL);
2539  if (reader->curnode != NULL)
2540  return(NULL);
2541 
2542  /* TODO: handle the xmlDecl */
2543  if (reader->node->type != XML_ELEMENT_NODE)
2544  return(NULL);
2545 
2546  if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2547  if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2548  prefix = BAD_CAST localName;
2549  }
2550  ns = reader->node->nsDef;
2551  while (ns != NULL) {
2552  if ((prefix == NULL && ns->prefix == NULL) ||
2553  ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2554  return xmlStrdup(ns->href);
2555  }
2556  ns = ns->next;
2557  }
2558  return NULL;
2559  }
2560 
2561  return(xmlGetNsProp(reader->node, localName, namespaceURI));
2562 }
2563 
2580 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2582 
2583  if (reader == NULL)
2584  return(NULL);
2585  if (reader->node == NULL)
2586  return(NULL);
2587 
2588  reader->node = NULL;
2589  reader->curnode = NULL;
2590  reader->mode = XML_TEXTREADER_MODE_EOF;
2591  if (reader->ctxt != NULL) {
2592  xmlStopParser(reader->ctxt);
2593  if (reader->ctxt->myDoc != NULL) {
2594  if (reader->preserve == 0)
2595  xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2596  reader->ctxt->myDoc = NULL;
2597  }
2598  }
2599  if (reader->allocs & XML_TEXTREADER_INPUT) {
2600  ret = reader->input;
2601  reader->input = NULL;
2602  reader->allocs -= XML_TEXTREADER_INPUT;
2603  } else {
2604  /*
2605  * Hum, one may need to duplicate the data structure because
2606  * without reference counting the input may be freed twice:
2607  * - by the layer which allocated it.
2608  * - by the layer to which would have been returned to.
2609  */
2610  TODO
2611  return(NULL);
2612  }
2613  return(ret);
2614 }
2615 
2627 xmlChar *
2628 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2629  xmlNsPtr ns;
2630 
2631  if (reader == NULL)
2632  return(NULL);
2633  if (reader->node == NULL)
2634  return(NULL);
2635 
2636  ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2637  if (ns == NULL)
2638  return(NULL);
2639  return(xmlStrdup(ns->href));
2640 }
2641 
2653 int
2654 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2655  int i;
2656  xmlAttrPtr cur;
2657  xmlNsPtr ns;
2658 
2659  if (reader == NULL)
2660  return(-1);
2661  if (reader->node == NULL)
2662  return(-1);
2663  /* TODO: handle the xmlDecl */
2664  if (reader->node->type != XML_ELEMENT_NODE)
2665  return(-1);
2666 
2667  reader->curnode = NULL;
2668 
2669  ns = reader->node->nsDef;
2670  for (i = 0;(i < no) && (ns != NULL);i++) {
2671  ns = ns->next;
2672  }
2673  if (ns != NULL) {
2674  reader->curnode = (xmlNodePtr) ns;
2675  return(1);
2676  }
2677 
2678  cur = reader->node->properties;
2679  if (cur == NULL)
2680  return(0);
2681  for (;i < no;i++) {
2682  cur = cur->next;
2683  if (cur == NULL)
2684  return(0);
2685  }
2686  /* TODO walk the DTD if present */
2687 
2688  reader->curnode = (xmlNodePtr) cur;
2689  return(1);
2690 }
2691 
2702 int
2703 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2704  xmlChar *prefix = NULL;
2705  xmlChar *localname;
2706  xmlNsPtr ns;
2707  xmlAttrPtr prop;
2708 
2709  if ((reader == NULL) || (name == NULL))
2710  return(-1);
2711  if (reader->node == NULL)
2712  return(-1);
2713 
2714  /* TODO: handle the xmlDecl */
2715  if (reader->node->type != XML_ELEMENT_NODE)
2716  return(0);
2717 
2718  localname = xmlSplitQName2(name, &prefix);
2719  if (localname == NULL) {
2720  /*
2721  * Namespace default decl
2722  */
2723  if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2724  ns = reader->node->nsDef;
2725  while (ns != NULL) {
2726  if (ns->prefix == NULL) {
2727  reader->curnode = (xmlNodePtr) ns;
2728  return(1);
2729  }
2730  ns = ns->next;
2731  }
2732  return(0);
2733  }
2734 
2735  prop = reader->node->properties;
2736  while (prop != NULL) {
2737  /*
2738  * One need to have
2739  * - same attribute names
2740  * - and the attribute carrying that namespace
2741  */
2742  if ((xmlStrEqual(prop->name, name)) &&
2743  ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2744  reader->curnode = (xmlNodePtr) prop;
2745  return(1);
2746  }
2747  prop = prop->next;
2748  }
2749  return(0);
2750  }
2751 
2752  /*
2753  * Namespace default decl
2754  */
2755  if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2756  ns = reader->node->nsDef;
2757  while (ns != NULL) {
2758  if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2759  reader->curnode = (xmlNodePtr) ns;
2760  goto found;
2761  }
2762  ns = ns->next;
2763  }
2764  goto not_found;
2765  }
2766  prop = reader->node->properties;
2767  while (prop != NULL) {
2768  /*
2769  * One need to have
2770  * - same attribute names
2771  * - and the attribute carrying that namespace
2772  */
2773  if ((xmlStrEqual(prop->name, localname)) &&
2774  (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2775  reader->curnode = (xmlNodePtr) prop;
2776  goto found;
2777  }
2778  prop = prop->next;
2779  }
2780 not_found:
2781  if (localname != NULL)
2782  xmlFree(localname);
2783  if (prefix != NULL)
2784  xmlFree(prefix);
2785  return(0);
2786 
2787 found:
2788  if (localname != NULL)
2789  xmlFree(localname);
2790  if (prefix != NULL)
2791  xmlFree(prefix);
2792  return(1);
2793 }
2794 
2806 int
2807 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2808  const xmlChar *localName, const xmlChar *namespaceURI) {
2809  xmlAttrPtr prop;
2810  xmlNodePtr node;
2811  xmlNsPtr ns;
2812  xmlChar *prefix = NULL;
2813 
2814  if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2815  return(-1);
2816  if (reader->node == NULL)
2817  return(-1);
2818  if (reader->node->type != XML_ELEMENT_NODE)
2819  return(0);
2820  node = reader->node;
2821 
2822  if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2823  if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2824  prefix = BAD_CAST localName;
2825  }
2826  ns = reader->node->nsDef;
2827  while (ns != NULL) {
2828  if ((prefix == NULL && ns->prefix == NULL) ||
2829  ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2830  reader->curnode = (xmlNodePtr) ns;
2831  return(1);
2832  }
2833  ns = ns->next;
2834  }
2835  return(0);
2836  }
2837 
2838  prop = node->properties;
2839  while (prop != NULL) {
2840  /*
2841  * One need to have
2842  * - same attribute names
2843  * - and the attribute carrying that namespace
2844  */
2845  if (xmlStrEqual(prop->name, localName) &&
2846  ((prop->ns != NULL) &&
2847  (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2848  reader->curnode = (xmlNodePtr) prop;
2849  return(1);
2850  }
2851  prop = prop->next;
2852  }
2853  return(0);
2854 }
2855 
2865 int
2866 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2867  if (reader == NULL)
2868  return(-1);
2869  if (reader->node == NULL)
2870  return(-1);
2871  if (reader->node->type != XML_ELEMENT_NODE)
2872  return(0);
2873 
2874  if (reader->node->nsDef != NULL) {
2875  reader->curnode = (xmlNodePtr) reader->node->nsDef;
2876  return(1);
2877  }
2878  if (reader->node->properties != NULL) {
2879  reader->curnode = (xmlNodePtr) reader->node->properties;
2880  return(1);
2881  }
2882  return(0);
2883 }
2884 
2894 int
2895 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2896  if (reader == NULL)
2897  return(-1);
2898  if (reader->node == NULL)
2899  return(-1);
2900  if (reader->node->type != XML_ELEMENT_NODE)
2901  return(0);
2902  if (reader->curnode == NULL)
2903  return(xmlTextReaderMoveToFirstAttribute(reader));
2904 
2905  if (reader->curnode->type == XML_NAMESPACE_DECL) {
2906  xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2907  if (ns->next != NULL) {
2908  reader->curnode = (xmlNodePtr) ns->next;
2909  return(1);
2910  }
2911  if (reader->node->properties != NULL) {
2912  reader->curnode = (xmlNodePtr) reader->node->properties;
2913  return(1);
2914  }
2915  return(0);
2916  } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2917  (reader->curnode->next != NULL)) {
2918  reader->curnode = reader->curnode->next;
2919  return(1);
2920  }
2921  return(0);
2922 }
2923 
2933 int
2934 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2935  if (reader == NULL)
2936  return(-1);
2937  if (reader->node == NULL)
2938  return(-1);
2939  if (reader->node->type != XML_ELEMENT_NODE)
2940  return(0);
2941  if (reader->curnode != NULL) {
2942  reader->curnode = NULL;
2943  return(1);
2944  }
2945  return(0);
2946 }
2947 
2958 int
2959 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2960  if (reader == NULL)
2961  return(-1);
2962  if (reader->node == NULL)
2963  return(-1);
2964  if (reader->curnode == NULL)
2965  return(0);
2966  if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2967  if (reader->curnode->children == NULL)
2968  return(0);
2969  reader->curnode = reader->curnode->children;
2970  } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2971  xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2972 
2973  if (reader->faketext == NULL) {
2974  reader->faketext = xmlNewDocText(reader->node->doc,
2975  ns->href);
2976  } else {
2977  if ((reader->faketext->content != NULL) &&
2978  (reader->faketext->content !=
2979  (xmlChar *) &(reader->faketext->properties)))
2980  xmlFree(reader->faketext->content);
2981  reader->faketext->content = xmlStrdup(ns->href);
2982  }
2983  reader->curnode = reader->faketext;
2984  } else {
2985  if (reader->curnode->next == NULL)
2986  return(0);
2987  reader->curnode = reader->curnode->next;
2988  }
2989  return(1);
2990 }
2991 
3001 const xmlChar *
3002 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
3003  xmlDocPtr doc = NULL;
3004  if (reader == NULL)
3005  return(NULL);
3006  if (reader->doc != NULL)
3007  doc = reader->doc;
3008  else if (reader->ctxt != NULL)
3009  doc = reader->ctxt->myDoc;
3010  if (doc == NULL)
3011  return(NULL);
3012 
3013  if (doc->encoding == NULL)
3014  return(NULL);
3015  else
3016  return(CONSTSTR(doc->encoding));
3017 }
3018 
3019 
3020 /************************************************************************
3021  * *
3022  * Access API to the current node *
3023  * *
3024  ************************************************************************/
3033 int
3034 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
3035  int ret;
3036  xmlAttrPtr attr;
3037  xmlNsPtr ns;
3038  xmlNodePtr node;
3039 
3040  if (reader == NULL)
3041  return(-1);
3042  if (reader->node == NULL)
3043  return(0);
3044 
3045  if (reader->curnode != NULL)
3046  node = reader->curnode;
3047  else
3048  node = reader->node;
3049 
3050  if (node->type != XML_ELEMENT_NODE)
3051  return(0);
3052  if ((reader->state == XML_TEXTREADER_END) ||
3053  (reader->state == XML_TEXTREADER_BACKTRACK))
3054  return(0);
3055  ret = 0;
3056  attr = node->properties;
3057  while (attr != NULL) {
3058  ret++;
3059  attr = attr->next;
3060  }
3061  ns = node->nsDef;
3062  while (ns != NULL) {
3063  ret++;
3064  ns = ns->next;
3065  }
3066  return(ret);
3067 }
3068 
3079 int
3080 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
3081  xmlNodePtr node;
3082 
3083  if (reader == NULL)
3084  return(-1);
3085  if (reader->node == NULL)
3086  return(XML_READER_TYPE_NONE);
3087  if (reader->curnode != NULL)
3088  node = reader->curnode;
3089  else
3090  node = reader->node;
3091  switch (node->type) {
3092  case XML_ELEMENT_NODE:
3093  if ((reader->state == XML_TEXTREADER_END) ||
3094  (reader->state == XML_TEXTREADER_BACKTRACK))
3095  return(XML_READER_TYPE_END_ELEMENT);
3096  return(XML_READER_TYPE_ELEMENT);
3097  case XML_NAMESPACE_DECL:
3098  case XML_ATTRIBUTE_NODE:
3099  return(XML_READER_TYPE_ATTRIBUTE);
3100  case XML_TEXT_NODE:
3101  if (xmlIsBlankNode(reader->node)) {
3102  if (xmlNodeGetSpacePreserve(reader->node))
3103  return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3104  else
3105  return(XML_READER_TYPE_WHITESPACE);
3106  } else {
3107  return(XML_READER_TYPE_TEXT);
3108  }
3110  return(XML_READER_TYPE_CDATA);
3111  case XML_ENTITY_REF_NODE:
3112  return(XML_READER_TYPE_ENTITY_REFERENCE);
3113  case XML_ENTITY_NODE:
3114  return(XML_READER_TYPE_ENTITY);
3115  case XML_PI_NODE:
3116  return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3117  case XML_COMMENT_NODE:
3118  return(XML_READER_TYPE_COMMENT);
3119  case XML_DOCUMENT_NODE:
3121 #ifdef LIBXML_DOCB_ENABLED
3122  case XML_DOCB_DOCUMENT_NODE:
3123 #endif
3124  return(XML_READER_TYPE_DOCUMENT);
3126  return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3127  case XML_NOTATION_NODE:
3128  return(XML_READER_TYPE_NOTATION);
3130  case XML_DTD_NODE:
3131  return(XML_READER_TYPE_DOCUMENT_TYPE);
3132 
3133  case XML_ELEMENT_DECL:
3134  case XML_ATTRIBUTE_DECL:
3135  case XML_ENTITY_DECL:
3136  case XML_XINCLUDE_START:
3137  case XML_XINCLUDE_END:
3138  return(XML_READER_TYPE_NONE);
3139  }
3140  return(-1);
3141 }
3142 
3151 int
3152 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3153  if ((reader == NULL) || (reader->node == NULL))
3154  return(-1);
3155  if (reader->node->type != XML_ELEMENT_NODE)
3156  return(0);
3157  if (reader->curnode != NULL)
3158  return(0);
3159  if (reader->node->children != NULL)
3160  return(0);
3161  if (reader->state == XML_TEXTREADER_END)
3162  return(0);
3163  if (reader->doc != NULL)
3164  return(1);
3165 #ifdef LIBXML_XINCLUDE_ENABLED
3166  if (reader->in_xinclude > 0)
3167  return(1);
3168 #endif
3169  return((reader->node->extra & NODE_IS_EMPTY) != 0);
3170 }
3171 
3181 xmlChar *
3182 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3183  xmlNodePtr node;
3184  if ((reader == NULL) || (reader->node == NULL))
3185  return(NULL);
3186  if (reader->curnode != NULL)
3187  node = reader->curnode;
3188  else
3189  node = reader->node;
3190  if (node->type == XML_NAMESPACE_DECL) {
3191  xmlNsPtr ns = (xmlNsPtr) node;
3192  if (ns->prefix == NULL)
3193  return(xmlStrdup(BAD_CAST "xmlns"));
3194  else
3195  return(xmlStrdup(ns->prefix));
3196  }
3197  if ((node->type != XML_ELEMENT_NODE) &&
3198  (node->type != XML_ATTRIBUTE_NODE))
3199  return(xmlTextReaderName(reader));
3200  return(xmlStrdup(node->name));
3201 }
3202 
3212 const xmlChar *
3213 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3214  xmlNodePtr node;
3215  if ((reader == NULL) || (reader->node == NULL))
3216  return(NULL);
3217  if (reader->curnode != NULL)
3218  node = reader->curnode;
3219  else
3220  node = reader->node;
3221  if (node->type == XML_NAMESPACE_DECL) {
3222  xmlNsPtr ns = (xmlNsPtr) node;
3223  if (ns->prefix == NULL)
3224  return(CONSTSTR(BAD_CAST "xmlns"));
3225  else
3226  return(ns->prefix);
3227  }
3228  if ((node->type != XML_ELEMENT_NODE) &&
3229  (node->type != XML_ATTRIBUTE_NODE))
3230  return(xmlTextReaderConstName(reader));
3231  return(node->name);
3232 }
3233 
3243 xmlChar *
3244 xmlTextReaderName(xmlTextReaderPtr reader) {
3245  xmlNodePtr node;
3246  xmlChar *ret;
3247 
3248  if ((reader == NULL) || (reader->node == NULL))
3249  return(NULL);
3250  if (reader->curnode != NULL)
3251  node = reader->curnode;
3252  else
3253  node = reader->node;
3254  switch (node->type) {
3255  case XML_ELEMENT_NODE:
3256  case XML_ATTRIBUTE_NODE:
3257  if ((node->ns == NULL) ||
3258  (node->ns->prefix == NULL))
3259  return(xmlStrdup(node->name));
3260 
3261  ret = xmlStrdup(node->ns->prefix);
3262  ret = xmlStrcat(ret, BAD_CAST ":");
3263  ret = xmlStrcat(ret, node->name);
3264  return(ret);
3265  case XML_TEXT_NODE:
3266  return(xmlStrdup(BAD_CAST "#text"));
3268  return(xmlStrdup(BAD_CAST "#cdata-section"));
3269  case XML_ENTITY_NODE:
3270  case XML_ENTITY_REF_NODE:
3271  return(xmlStrdup(node->name));
3272  case XML_PI_NODE:
3273  return(xmlStrdup(node->name));
3274  case XML_COMMENT_NODE:
3275  return(xmlStrdup(BAD_CAST "#comment"));
3276  case XML_DOCUMENT_NODE:
3278 #ifdef LIBXML_DOCB_ENABLED
3279  case XML_DOCB_DOCUMENT_NODE:
3280 #endif
3281  return(xmlStrdup(BAD_CAST "#document"));
3283  return(xmlStrdup(BAD_CAST "#document-fragment"));
3284  case XML_NOTATION_NODE:
3285  return(xmlStrdup(node->name));
3287  case XML_DTD_NODE:
3288  return(xmlStrdup(node->name));
3289  case XML_NAMESPACE_DECL: {
3290  xmlNsPtr ns = (xmlNsPtr) node;
3291 
3292  ret = xmlStrdup(BAD_CAST "xmlns");
3293  if (ns->prefix == NULL)
3294  return(ret);
3295  ret = xmlStrcat(ret, BAD_CAST ":");
3296  ret = xmlStrcat(ret, ns->prefix);
3297  return(ret);
3298  }
3299 
3300  case XML_ELEMENT_DECL:
3301  case XML_ATTRIBUTE_DECL:
3302  case XML_ENTITY_DECL:
3303  case XML_XINCLUDE_START:
3304  case XML_XINCLUDE_END:
3305  return(NULL);
3306  }
3307  return(NULL);
3308 }
3309 
3319 const xmlChar *
3320 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3321  xmlNodePtr node;
3322 
3323  if ((reader == NULL) || (reader->node == NULL))
3324  return(NULL);
3325  if (reader->curnode != NULL)
3326  node = reader->curnode;
3327  else
3328  node = reader->node;
3329  switch (node->type) {
3330  case XML_ELEMENT_NODE:
3331  case XML_ATTRIBUTE_NODE:
3332  if ((node->ns == NULL) ||
3333  (node->ns->prefix == NULL))
3334  return(node->name);
3335  return(CONSTQSTR(node->ns->prefix, node->name));
3336  case XML_TEXT_NODE:
3337  return(CONSTSTR(BAD_CAST "#text"));
3339  return(CONSTSTR(BAD_CAST "#cdata-section"));
3340  case XML_ENTITY_NODE:
3341  case XML_ENTITY_REF_NODE:
3342  return(CONSTSTR(node->name));
3343  case XML_PI_NODE:
3344  return(CONSTSTR(node->name));
3345  case XML_COMMENT_NODE:
3346  return(CONSTSTR(BAD_CAST "#comment"));
3347  case XML_DOCUMENT_NODE:
3349 #ifdef LIBXML_DOCB_ENABLED
3350  case XML_DOCB_DOCUMENT_NODE:
3351 #endif
3352  return(CONSTSTR(BAD_CAST "#document"));
3354  return(CONSTSTR(BAD_CAST "#document-fragment"));
3355  case XML_NOTATION_NODE:
3356  return(CONSTSTR(node->name));
3358  case XML_DTD_NODE:
3359  return(CONSTSTR(node->name));
3360  case XML_NAMESPACE_DECL: {
3361  xmlNsPtr ns = (xmlNsPtr) node;
3362 
3363  if (ns->prefix == NULL)
3364  return(CONSTSTR(BAD_CAST "xmlns"));
3365  return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3366  }
3367 
3368  case XML_ELEMENT_DECL:
3369  case XML_ATTRIBUTE_DECL:
3370  case XML_ENTITY_DECL:
3371  case XML_XINCLUDE_START:
3372  case XML_XINCLUDE_END:
3373  return(NULL);
3374  }
3375  return(NULL);
3376 }
3377 
3387 xmlChar *
3388 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3389  xmlNodePtr node;
3390  if ((reader == NULL) || (reader->node == NULL))
3391  return(NULL);
3392  if (reader->curnode != NULL)
3393  node = reader->curnode;
3394  else
3395  node = reader->node;
3396  if (node->type == XML_NAMESPACE_DECL) {
3397  xmlNsPtr ns = (xmlNsPtr) node;
3398  if (ns->prefix == NULL)
3399  return(NULL);
3400  return(xmlStrdup(BAD_CAST "xmlns"));
3401  }
3402  if ((node->type != XML_ELEMENT_NODE) &&
3403  (node->type != XML_ATTRIBUTE_NODE))
3404  return(NULL);
3405  if ((node->ns != NULL) && (node->ns->prefix != NULL))
3406  return(xmlStrdup(node->ns->prefix));
3407  return(NULL);
3408 }
3409 
3419 const xmlChar *
3420 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3421  xmlNodePtr node;
3422  if ((reader == NULL) || (reader->node == NULL))
3423  return(NULL);
3424  if (reader->curnode != NULL)
3425  node = reader->curnode;
3426  else
3427  node = reader->node;
3428  if (node->type == XML_NAMESPACE_DECL) {
3429  xmlNsPtr ns = (xmlNsPtr) node;
3430  if (ns->prefix == NULL)
3431  return(NULL);
3432  return(CONSTSTR(BAD_CAST "xmlns"));
3433  }
3434  if ((node->type != XML_ELEMENT_NODE) &&
3435  (node->type != XML_ATTRIBUTE_NODE))
3436  return(NULL);
3437  if ((node->ns != NULL) && (node->ns->prefix != NULL))
3438  return(CONSTSTR(node->ns->prefix));
3439  return(NULL);
3440 }
3441 
3451 xmlChar *
3452 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3453  xmlNodePtr node;
3454  if ((reader == NULL) || (reader->node == NULL))
3455  return(NULL);
3456  if (reader->curnode != NULL)
3457  node = reader->curnode;
3458  else
3459  node = reader->node;
3460  if (node->type == XML_NAMESPACE_DECL)
3461  return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3462  if ((node->type != XML_ELEMENT_NODE) &&
3463  (node->type != XML_ATTRIBUTE_NODE))
3464  return(NULL);
3465  if (node->ns != NULL)
3466  return(xmlStrdup(node->ns->href));
3467  return(NULL);
3468 }
3469 
3479 const xmlChar *
3480 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3481  xmlNodePtr node;
3482  if ((reader == NULL) || (reader->node == NULL))
3483  return(NULL);
3484  if (reader->curnode != NULL)
3485  node = reader->curnode;
3486  else
3487  node = reader->node;
3488  if (node->type == XML_NAMESPACE_DECL)
3489  return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3490  if ((node->type != XML_ELEMENT_NODE) &&
3491  (node->type != XML_ATTRIBUTE_NODE))
3492  return(NULL);
3493  if (node->ns != NULL)
3494  return(CONSTSTR(node->ns->href));
3495  return(NULL);
3496 }
3497 
3507 xmlChar *
3508 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3509  if ((reader == NULL) || (reader->node == NULL))
3510  return(NULL);
3511  return(xmlNodeGetBase(NULL, reader->node));
3512 }
3513 
3523 const xmlChar *
3524 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3525  xmlChar *tmp;
3526  const xmlChar *ret;
3527 
3528  if ((reader == NULL) || (reader->node == NULL))
3529  return(NULL);
3530  tmp = xmlNodeGetBase(NULL, reader->node);
3531  if (tmp == NULL)
3532  return(NULL);
3533  ret = CONSTSTR(tmp);
3534  xmlFree(tmp);
3535  return(ret);
3536 }
3537 
3546 int
3547 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3548  if (reader == NULL)
3549  return(-1);
3550  if (reader->node == NULL)
3551  return(0);
3552 
3553  if (reader->curnode != NULL) {
3554  if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3555  (reader->curnode->type == XML_NAMESPACE_DECL))
3556  return(reader->depth + 1);
3557  return(reader->depth + 2);
3558  }
3559  return(reader->depth);
3560 }
3561 
3570 int
3571 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3572  xmlNodePtr node;
3573  if (reader == NULL)
3574  return(-1);
3575  if (reader->node == NULL)
3576  return(0);
3577  if (reader->curnode != NULL)
3578  node = reader->curnode;
3579  else
3580  node = reader->node;
3581 
3582  if ((node->type == XML_ELEMENT_NODE) &&
3583  ((node->properties != NULL) || (node->nsDef != NULL)))
3584  return(1);
3585  /* TODO: handle the xmlDecl */
3586  return(0);
3587 }
3588 
3597 int
3598 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3599  xmlNodePtr node;
3600  if (reader == NULL)
3601  return(-1);
3602  if (reader->node == NULL)
3603  return(0);
3604  if (reader->curnode != NULL)
3605  node = reader->curnode;
3606  else
3607  node = reader->node;
3608 
3609  switch (node->type) {
3610  case XML_ATTRIBUTE_NODE:
3611  case XML_TEXT_NODE:
3613  case XML_PI_NODE:
3614  case XML_COMMENT_NODE:
3615  case XML_NAMESPACE_DECL:
3616  return(1);
3617  default:
3618  break;
3619  }
3620  return(0);
3621 }
3622 
3632 xmlChar *
3633 xmlTextReaderValue(xmlTextReaderPtr reader) {
3634  xmlNodePtr node;
3635  if (reader == NULL)
3636  return(NULL);
3637  if (reader->node == NULL)
3638  return(NULL);
3639  if (reader->curnode != NULL)
3640  node = reader->curnode;
3641  else
3642  node = reader->node;
3643 
3644  switch (node->type) {
3645  case XML_NAMESPACE_DECL:
3646  return(xmlStrdup(((xmlNsPtr) node)->href));
3647  case XML_ATTRIBUTE_NODE:{
3649 
3650  if (attr->parent != NULL)
3651  return (xmlNodeListGetString
3652  (attr->parent->doc, attr->children, 1));
3653  else
3654  return (xmlNodeListGetString(NULL, attr->children, 1));
3655  break;
3656  }
3657  case XML_TEXT_NODE:
3659  case XML_PI_NODE:
3660  case XML_COMMENT_NODE:
3661  if (node->content != NULL)
3662  return (xmlStrdup(node->content));
3663  default:
3664  break;
3665  }
3666  return(NULL);
3667 }
3668 
3678 const xmlChar *
3679 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3680  xmlNodePtr node;
3681  if (reader == NULL)
3682  return(NULL);
3683  if (reader->node == NULL)
3684  return(NULL);
3685  if (reader->curnode != NULL)
3686  node = reader->curnode;
3687  else
3688  node = reader->node;
3689 
3690  switch (node->type) {
3691  case XML_NAMESPACE_DECL:
3692  return(((xmlNsPtr) node)->href);
3693  case XML_ATTRIBUTE_NODE:{
3695  const xmlChar *ret;
3696 
3697  if ((attr->children != NULL) &&
3698  (attr->children->type == XML_TEXT_NODE) &&
3699  (attr->children->next == NULL))
3700  return(attr->children->content);
3701  else {
3702  if (reader->buffer == NULL) {
3703  reader->buffer = xmlBufCreateSize(100);
3704  if (reader->buffer == NULL) {
3706  "xmlTextReaderSetup : malloc failed\n");
3707  return (NULL);
3708  }
3711  } else
3712  xmlBufEmpty(reader->buffer);
3713  xmlBufGetNodeContent(reader->buffer, node);
3714  ret = xmlBufContent(reader->buffer);
3715  if (ret == NULL) {
3716  /* error on the buffer best to reallocate */
3717  xmlBufFree(reader->buffer);
3718  reader->buffer = xmlBufCreateSize(100);
3721  ret = BAD_CAST "";
3722  }
3723  return(ret);
3724  }
3725  break;
3726  }
3727  case XML_TEXT_NODE:
3729  case XML_PI_NODE:
3730  case XML_COMMENT_NODE:
3731  return(node->content);
3732  default:
3733  break;
3734  }
3735  return(NULL);
3736 }
3737 
3747 int
3748 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3749  if (reader == NULL)
3750  return(-1);
3751  return(0);
3752 }
3753 
3762 int
3763 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3764  if (reader == NULL)
3765  return(-1);
3766  /* TODO maybe lookup the attribute value for " first */
3767  return((int) '"');
3768 }
3769 
3779 xmlChar *
3780 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3781  if (reader == NULL)
3782  return(NULL);
3783  if (reader->node == NULL)
3784  return(NULL);
3785  return(xmlNodeGetLang(reader->node));
3786 }
3787 
3796 const xmlChar *
3797 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3798  xmlChar *tmp;
3799  const xmlChar *ret;
3800 
3801  if (reader == NULL)
3802  return(NULL);
3803  if (reader->node == NULL)
3804  return(NULL);
3805  tmp = xmlNodeGetLang(reader->node);
3806  if (tmp == NULL)
3807  return(NULL);
3808  ret = CONSTSTR(tmp);
3809  xmlFree(tmp);
3810  return(ret);
3811 }
3812 
3824 const xmlChar *
3825 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3826  if (reader == NULL)
3827  return(NULL);
3828  return(CONSTSTR(str));
3829 }
3830 
3843 int
3844 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3845  if (reader == NULL)
3846  return(-1);
3847  return(1);
3848 }
3849 
3850 /************************************************************************
3851  * *
3852  * Extensions to the base APIs *
3853  * *
3854  ************************************************************************/
3855 
3868 int
3869 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3870  xmlParserProperties p = (xmlParserProperties) prop;
3871  xmlParserCtxtPtr ctxt;
3872 
3873  if ((reader == NULL) || (reader->ctxt == NULL))
3874  return(-1);
3875  ctxt = reader->ctxt;
3876 
3877  switch (p) {
3878  case XML_PARSER_LOADDTD:
3879  if (value != 0) {
3880  if (ctxt->loadsubset == 0) {
3881  if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3882  return(-1);
3883  ctxt->loadsubset = XML_DETECT_IDS;
3884  }
3885  } else {
3886  ctxt->loadsubset = 0;
3887  }
3888  return(0);
3889  case XML_PARSER_DEFAULTATTRS:
3890  if (value != 0) {
3891  ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3892  } else {
3893  if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3894  ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3895  }
3896  return(0);
3897  case XML_PARSER_VALIDATE:
3898  if (value != 0) {
3899  ctxt->options |= XML_PARSE_DTDVALID;
3900  ctxt->validate = 1;
3901  reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3902  } else {
3903  ctxt->options &= ~XML_PARSE_DTDVALID;
3904  ctxt->validate = 0;
3905  }
3906  return(0);
3907  case XML_PARSER_SUBST_ENTITIES:
3908  if (value != 0) {
3909  ctxt->options |= XML_PARSE_NOENT;
3910  ctxt->replaceEntities = 1;
3911  } else {
3912  ctxt->options &= ~XML_PARSE_NOENT;
3913  ctxt->replaceEntities = 0;
3914  }
3915  return(0);
3916  }
3917  return(-1);
3918 }
3919 
3929 int
3930 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3931  xmlParserProperties p = (xmlParserProperties) prop;
3932  xmlParserCtxtPtr ctxt;
3933 
3934  if ((reader == NULL) || (reader->ctxt == NULL))
3935  return(-1);
3936  ctxt = reader->ctxt;
3937 
3938  switch (p) {
3939  case XML_PARSER_LOADDTD:
3940  if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3941  return(1);
3942  return(0);
3943  case XML_PARSER_DEFAULTATTRS:
3944  if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3945  return(1);
3946  return(0);
3947  case XML_PARSER_VALIDATE:
3948  return(reader->validate);
3949  case XML_PARSER_SUBST_ENTITIES:
3950  return(ctxt->replaceEntities);
3951  }
3952  return(-1);
3953 }
3954 
3955 
3964 int
3965 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3966 {
3967  if ((reader == NULL) || (reader->ctxt == NULL) ||
3968  (reader->ctxt->input == NULL)) {
3969  return (0);
3970  }
3971  return (reader->ctxt->input->line);
3972 }
3973 
3982 int
3983 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3984 {
3985  if ((reader == NULL) || (reader->ctxt == NULL) ||
3986  (reader->ctxt->input == NULL)) {
3987  return (0);
3988  }
3989  return (reader->ctxt->input->col);
3990 }
3991 
4002 xmlNodePtr
4003 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
4004  if (reader == NULL)
4005  return(NULL);
4006 
4007  if (reader->curnode != NULL)
4008  return(reader->curnode);
4009  return(reader->node);
4010 }
4011 
4022 xmlNodePtr
4023 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
4025 
4026  if (reader == NULL)
4027  return(NULL);
4028 
4029  if (reader->curnode != NULL)
4030  cur = reader->curnode;
4031  else
4032  cur = reader->node;
4033  if (cur == NULL)
4034  return(NULL);
4035 
4036  if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
4037  cur->extra |= NODE_IS_PRESERVED;
4038  cur->extra |= NODE_IS_SPRESERVED;
4039  }
4040  reader->preserves++;
4041 
4042  parent = cur->parent;;
4043  while (parent != NULL) {
4044  if (parent->type == XML_ELEMENT_NODE)
4045  parent->extra |= NODE_IS_PRESERVED;
4046  parent = parent->parent;
4047  }
4048  return(cur);
4049 }
4050 
4051 #ifdef LIBXML_PATTERN_ENABLED
4052 
4064 int
4065 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
4066  const xmlChar **namespaces)
4067 {
4068  xmlPatternPtr comp;
4069 
4070  if ((reader == NULL) || (pattern == NULL))
4071  return(-1);
4072 
4073  comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
4074  if (comp == NULL)
4075  return(-1);
4076 
4077  if (reader->patternMax <= 0) {
4078  reader->patternMax = 4;
4079  reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4080  sizeof(reader->patternTab[0]));
4081  if (reader->patternTab == NULL) {
4082  xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4083  return (-1);
4084  }
4085  }
4086  if (reader->patternNr >= reader->patternMax) {
4087  xmlPatternPtr *tmp;
4088  reader->patternMax *= 2;
4089  tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4090  reader->patternMax *
4091  sizeof(reader->patternTab[0]));
4092  if (tmp == NULL) {
4093  xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4094  reader->patternMax /= 2;
4095  return (-1);
4096  }
4097  reader->patternTab = tmp;
4098  }
4099  reader->patternTab[reader->patternNr] = comp;
4100  return(reader->patternNr++);
4101 }
4102 #endif
4103 
4116 xmlDocPtr
4117 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4118  if (reader == NULL)
4119  return(NULL);
4120  if (reader->doc != NULL)
4121  return(reader->doc);
4122  if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4123  return(NULL);
4124 
4125  reader->preserve = 1;
4126  return(reader->ctxt->myDoc);
4127 }
4128 
4129 #ifdef LIBXML_SCHEMAS_ENABLED
4130 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
4131 
4132 static void XMLCDECL
4133 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4134 
4135 static void XMLCDECL
4136 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4137 
4138 static void XMLCDECL
4139 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4140 
4141 static void XMLCDECL
4142 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4143 
4144 static void XMLCDECL
4145 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4146 {
4147  xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4148 
4149  char *str;
4150 
4151  va_list ap;
4152 
4153  va_start(ap, msg);
4154  str = xmlTextReaderBuildMessage(msg, ap);
4155  if (!reader->errorFunc) {
4156  xmlTextReaderValidityError(ctx, "%s", str);
4157  } else {
4158  reader->errorFunc(reader->errorFuncArg, str,
4160  NULL /* locator */ );
4161  }
4162  if (str != NULL)
4163  xmlFree(str);
4164  va_end(ap);
4165 }
4166 
4167 static void XMLCDECL
4168 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4169 {
4170  xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4171 
4172  char *str;
4173 
4174  va_list ap;
4175 
4176  va_start(ap, msg);
4177  str = xmlTextReaderBuildMessage(msg, ap);
4178  if (!reader->errorFunc) {
4179  xmlTextReaderValidityWarning(ctx, "%s", str);
4180  } else {
4181  reader->errorFunc(reader->errorFuncArg, str,
4183  NULL /* locator */ );
4184  }
4185  if (str != NULL)
4186  xmlFree(str);
4187  va_end(ap);
4188 }
4189 
4190 static void
4191  xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4192 
4193 static void
4194 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4195 {
4196  xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4197 
4198  if (reader->sErrorFunc) {
4199  reader->sErrorFunc(reader->errorFuncArg, error);
4200  } else {
4201  xmlTextReaderStructuredError(reader, error);
4202  }
4203 }
4218 int
4219 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4220  if (reader == NULL)
4221  return(-1);
4222  if (schema == NULL) {
4223  if (reader->rngSchemas != NULL) {
4224  xmlRelaxNGFree(reader->rngSchemas);
4225  reader->rngSchemas = NULL;
4226  }
4227  if (reader->rngValidCtxt != NULL) {
4228  if (! reader->rngPreserveCtxt)
4229  xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4230  reader->rngValidCtxt = NULL;
4231  }
4232  reader->rngPreserveCtxt = 0;
4233  return(0);
4234  }
4235  if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4236  return(-1);
4237  if (reader->rngSchemas != NULL) {
4238  xmlRelaxNGFree(reader->rngSchemas);
4239  reader->rngSchemas = NULL;
4240  }
4241  if (reader->rngValidCtxt != NULL) {
4242  if (! reader->rngPreserveCtxt)
4243  xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4244  reader->rngValidCtxt = NULL;
4245  }
4246  reader->rngPreserveCtxt = 0;
4247  reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4248  if (reader->rngValidCtxt == NULL)
4249  return(-1);
4250  if (reader->errorFunc != NULL) {
4251  xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4252  xmlTextReaderValidityErrorRelay,
4253  xmlTextReaderValidityWarningRelay,
4254  reader);
4255  }
4256  if (reader->sErrorFunc != NULL) {
4257  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4258  xmlTextReaderValidityStructuredRelay,
4259  reader);
4260  }
4261  reader->rngValidErrors = 0;
4262  reader->rngFullNode = NULL;
4263  reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4264  return(0);
4265 }
4266 
4278 static int
4279 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4280  xmlTextReaderPtr reader;
4281 
4282  if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4283  return(-1);
4284 
4285  if (file != NULL)
4286  *file = NULL;
4287  if (line != NULL)
4288  *line = 0;
4289 
4290  reader = (xmlTextReaderPtr) ctx;
4291  if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4292  if (file != NULL)
4293  *file = reader->ctxt->input->filename;
4294  if (line != NULL)
4295  *line = reader->ctxt->input->line;
4296  return(0);
4297  }
4298  if (reader->node != NULL) {
4299  long res;
4300  int ret = 0;
4301 
4302  if (line != NULL) {
4303  res = xmlGetLineNo(reader->node);
4304  if (res > 0)
4305  *line = (unsigned long) res;
4306  else
4307  ret = -1;
4308  }
4309  if (file != NULL) {
4310  xmlDocPtr doc = reader->node->doc;
4311  if ((doc != NULL) && (doc->URL != NULL))
4312  *file = (const char *) doc->URL;
4313  else
4314  ret = -1;
4315  }
4316  return(ret);
4317  }
4318  return(-1);
4319 }
4320 
4335 int
4336 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4337  if (reader == NULL)
4338  return(-1);
4339  if (schema == NULL) {
4340  if (reader->xsdPlug != NULL) {
4341  xmlSchemaSAXUnplug(reader->xsdPlug);
4342  reader->xsdPlug = NULL;
4343  }
4344  if (reader->xsdValidCtxt != NULL) {
4345  if (! reader->xsdPreserveCtxt)
4346  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4347  reader->xsdValidCtxt = NULL;
4348  }
4349  reader->xsdPreserveCtxt = 0;
4350  if (reader->xsdSchemas != NULL) {
4351  xmlSchemaFree(reader->xsdSchemas);
4352  reader->xsdSchemas = NULL;
4353  }
4354  return(0);
4355  }
4356  if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4357  return(-1);
4358  if (reader->xsdPlug != NULL) {
4359  xmlSchemaSAXUnplug(reader->xsdPlug);
4360  reader->xsdPlug = NULL;
4361  }
4362  if (reader->xsdValidCtxt != NULL) {
4363  if (! reader->xsdPreserveCtxt)
4364  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4365  reader->xsdValidCtxt = NULL;
4366  }
4367  reader->xsdPreserveCtxt = 0;
4368  if (reader->xsdSchemas != NULL) {
4369  xmlSchemaFree(reader->xsdSchemas);
4370  reader->xsdSchemas = NULL;
4371  }
4372  reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4373  if (reader->xsdValidCtxt == NULL) {
4374  xmlSchemaFree(reader->xsdSchemas);
4375  reader->xsdSchemas = NULL;
4376  return(-1);
4377  }
4378  reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4379  &(reader->ctxt->sax),
4380  &(reader->ctxt->userData));
4381  if (reader->xsdPlug == NULL) {
4382  xmlSchemaFree(reader->xsdSchemas);
4383  reader->xsdSchemas = NULL;
4384  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4385  reader->xsdValidCtxt = NULL;
4386  return(-1);
4387  }
4388  xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4389  xmlTextReaderLocator,
4390  (void *) reader);
4391 
4392  if (reader->errorFunc != NULL) {
4393  xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4394  xmlTextReaderValidityErrorRelay,
4395  xmlTextReaderValidityWarningRelay,
4396  reader);
4397  }
4398  if (reader->sErrorFunc != NULL) {
4399  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4400  xmlTextReaderValidityStructuredRelay,
4401  reader);
4402  }
4403  reader->xsdValidErrors = 0;
4404  reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4405  return(0);
4406 }
4407 
4422 static int
4423 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4424  const char *rng,
4425  xmlRelaxNGValidCtxtPtr ctxt,
4427 {
4428  if (reader == NULL)
4429  return(-1);
4430 
4431  if ((rng != NULL) && (ctxt != NULL))
4432  return (-1);
4433 
4434  if (((rng != NULL) || (ctxt != NULL)) &&
4435  ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4436  (reader->ctxt == NULL)))
4437  return(-1);
4438 
4439  /* Cleanup previous validation stuff. */
4440  if (reader->rngValidCtxt != NULL) {
4441  if ( !reader->rngPreserveCtxt)
4442  xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4443  reader->rngValidCtxt = NULL;
4444  }
4445  reader->rngPreserveCtxt = 0;
4446  if (reader->rngSchemas != NULL) {
4447  xmlRelaxNGFree(reader->rngSchemas);
4448  reader->rngSchemas = NULL;
4449  }
4450 
4451  if ((rng == NULL) && (ctxt == NULL)) {
4452  /* We just want to deactivate the validation, so get out. */
4453  return(0);
4454  }
4455 
4456 
4457  if (rng != NULL) {
4458  xmlRelaxNGParserCtxtPtr pctxt;
4459  /* Parse the schema and create validation environment. */
4460 
4461  pctxt = xmlRelaxNGNewParserCtxt(rng);
4462  if (reader->errorFunc != NULL) {
4463  xmlRelaxNGSetParserErrors(pctxt,
4464  xmlTextReaderValidityErrorRelay,
4465  xmlTextReaderValidityWarningRelay,
4466  reader);
4467  }
4468  if (reader->sErrorFunc != NULL) {
4469  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4470  xmlTextReaderValidityStructuredRelay,
4471  reader);
4472  }
4473  reader->rngSchemas = xmlRelaxNGParse(pctxt);
4474  xmlRelaxNGFreeParserCtxt(pctxt);
4475  if (reader->rngSchemas == NULL)
4476  return(-1);
4477  reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4478  if (reader->rngValidCtxt == NULL) {
4479  xmlRelaxNGFree(reader->rngSchemas);
4480  reader->rngSchemas = NULL;
4481  return(-1);
4482  }
4483  } else {
4484  /* Use the given validation context. */
4485  reader->rngValidCtxt = ctxt;
4486  reader->rngPreserveCtxt = 1;
4487  }
4488  /*
4489  * Redirect the validation context's error channels to use
4490  * the reader channels.
4491  * TODO: In case the user provides the validation context we
4492  * could make this redirection optional.
4493  */
4494  if (reader->errorFunc != NULL) {
4495  xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4496  xmlTextReaderValidityErrorRelay,
4497  xmlTextReaderValidityWarningRelay,
4498  reader);
4499  }
4500  if (reader->sErrorFunc != NULL) {
4501  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4502  xmlTextReaderValidityStructuredRelay,
4503  reader);
4504  }
4505  reader->rngValidErrors = 0;
4506  reader->rngFullNode = NULL;
4507  reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4508  return(0);
4509 }
4510 
4525 static int
4526 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4527  const char *xsd,
4528  xmlSchemaValidCtxtPtr ctxt,
4530 {
4531  if (reader == NULL)
4532  return(-1);
4533 
4534  if ((xsd != NULL) && (ctxt != NULL))
4535  return(-1);
4536 
4537  if (((xsd != NULL) || (ctxt != NULL)) &&
4538  ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4539  (reader->ctxt == NULL)))
4540  return(-1);
4541 
4542  /* Cleanup previous validation stuff. */
4543  if (reader->xsdPlug != NULL) {
4544  xmlSchemaSAXUnplug(reader->xsdPlug);
4545  reader->xsdPlug = NULL;
4546  }
4547  if (reader->xsdValidCtxt != NULL) {
4548  if (! reader->xsdPreserveCtxt)
4549  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4550  reader->xsdValidCtxt = NULL;
4551  }
4552  reader->xsdPreserveCtxt = 0;
4553  if (reader->xsdSchemas != NULL) {
4554  xmlSchemaFree(reader->xsdSchemas);
4555  reader->xsdSchemas = NULL;
4556  }
4557 
4558  if ((xsd == NULL) && (ctxt == NULL)) {
4559  /* We just want to deactivate the validation, so get out. */
4560  return(0);
4561  }
4562 
4563  if (xsd != NULL) {
4564  xmlSchemaParserCtxtPtr pctxt;
4565  /* Parse the schema and create validation environment. */
4566  pctxt = xmlSchemaNewParserCtxt(xsd);
4567  if (reader->errorFunc != NULL) {
4568  xmlSchemaSetParserErrors(pctxt,
4569  xmlTextReaderValidityErrorRelay,
4570  xmlTextReaderValidityWarningRelay,
4571  reader);
4572  }
4573  reader->xsdSchemas = xmlSchemaParse(pctxt);
4574  xmlSchemaFreeParserCtxt(pctxt);
4575  if (reader->xsdSchemas == NULL)
4576  return(-1);
4577  reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4578  if (reader->xsdValidCtxt == NULL) {
4579  xmlSchemaFree(reader->xsdSchemas);
4580  reader->xsdSchemas = NULL;
4581  return(-1);
4582  }
4583  reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4584  &(reader->ctxt->sax),
4585  &(reader->ctxt->userData));
4586  if (reader->xsdPlug == NULL) {
4587  xmlSchemaFree(reader->xsdSchemas);
4588  reader->xsdSchemas = NULL;
4589  xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4590  reader->xsdValidCtxt = NULL;
4591  return(-1);
4592  }
4593  } else {
4594  /* Use the given validation context. */
4595  reader->xsdValidCtxt = ctxt;
4596  reader->xsdPreserveCtxt = 1;
4597  reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4598  &(reader->ctxt->sax),
4599  &(reader->ctxt->userData));
4600  if (reader->xsdPlug == NULL) {
4601  reader->xsdValidCtxt = NULL;
4602  reader->xsdPreserveCtxt = 0;
4603  return(-1);
4604  }
4605  }
4606  xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4607  xmlTextReaderLocator,
4608  (void *) reader);
4609  /*
4610  * Redirect the validation context's error channels to use
4611  * the reader channels.
4612  * TODO: In case the user provides the validation context we
4613  * could make this redirection optional.
4614  */
4615  if (reader->errorFunc != NULL) {
4616  xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4617  xmlTextReaderValidityErrorRelay,
4618  xmlTextReaderValidityWarningRelay,
4619  reader);
4620  }
4621  if (reader->sErrorFunc != NULL) {
4622  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4623  xmlTextReaderValidityStructuredRelay,
4624  reader);
4625  }
4626  reader->xsdValidErrors = 0;
4627  reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4628  return(0);
4629 }
4630 
4644 int
4645 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4646  xmlSchemaValidCtxtPtr ctxt,
4647  int options)
4648 {
4649  return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4650 }
4651 
4664 int
4665 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4666 {
4667  return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4668 }
4669 
4683 int
4684 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4685  xmlRelaxNGValidCtxtPtr ctxt,
4686  int options)
4687 {
4688  return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4689 }
4690 
4703 int
4704 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4705 {
4706  return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4707 }
4708 
4709 #endif
4710 
4722 int
4723 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4724  xmlNodePtr node;
4725  if (reader == NULL)
4726  return(-1);
4727  if (reader->node == NULL)
4728  return(-1);
4729  if (reader->curnode != NULL)
4730  node = reader->curnode;
4731  else
4732  node = reader->node;
4733 
4734  if (XML_NAMESPACE_DECL == node->type)
4735  return(1);
4736  else
4737  return(0);
4738 }
4739 
4749 const xmlChar *
4750 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4751  xmlDocPtr doc = NULL;
4752  if (reader == NULL)
4753  return(NULL);
4754  if (reader->doc != NULL)
4755  doc = reader->doc;
4756  else if (reader->ctxt != NULL)
4757  doc = reader->ctxt->myDoc;
4758  if (doc == NULL)
4759  return(NULL);
4760 
4761  if (doc->version == NULL)
4762  return(NULL);
4763  else
4764  return(CONSTSTR(doc->version));
4765 }
4766 
4777 int
4778 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4779  xmlDocPtr doc = NULL;
4780  if (reader == NULL)
4781  return(-1);
4782  if (reader->doc != NULL)
4783  doc = reader->doc;
4784  else if (reader->ctxt != NULL)
4785  doc = reader->ctxt->myDoc;
4786  if (doc == NULL)
4787  return(-1);
4788 
4789  return(doc->standalone);
4790 }
4791 
4792 /************************************************************************
4793  * *
4794  * Error Handling Extensions *
4795  * *
4796  ************************************************************************/
4797 
4798 /* helper to build a xmlMalloc'ed string from a format and va_list */
4799 static char *
4800 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4801  int size = 0;
4802  int chars;
4803  char *larger;
4804  char *str = NULL;
4805  va_list aq;
4806 
4807  while (1) {
4808  VA_COPY(aq, ap);
4809  chars = vsnprintf(str, size, msg, aq);
4810  va_end(aq);
4811  if (chars < 0) {
4812  xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4813  if (str)
4814  xmlFree(str);
4815  return NULL;
4816  }
4817  if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4818  break;
4819  if (chars < MAX_ERR_MSG_SIZE)
4820  size = chars + 1;
4821  else
4822  size = MAX_ERR_MSG_SIZE;
4823  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4824  xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4825  if (str)
4826  xmlFree(str);
4827  return NULL;
4828  }
4829  str = larger;
4830  }
4831 
4832  return str;
4833 }
4834 
4843 int
4844 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4845  /* we know that locator is a xmlParserCtxtPtr */
4847  int ret = -1;
4848 
4849  if (locator == NULL)
4850  return(-1);
4851  if (ctx->node != NULL) {
4852  ret = xmlGetLineNo(ctx->node);
4853  }
4854  else {
4855  /* inspired from error.c */
4857  input = ctx->input;
4858  if ((input->filename == NULL) && (ctx->inputNr > 1))
4859  input = ctx->inputTab[ctx->inputNr - 2];
4860  if (input != NULL) {
4861  ret = input->line;
4862  }
4863  else {
4864  ret = -1;
4865  }
4866  }
4867 
4868  return ret;
4869 }
4870 
4880 xmlChar *
4881 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4882  /* we know that locator is a xmlParserCtxtPtr */
4884  xmlChar *ret = NULL;
4885 
4886  if (locator == NULL)
4887  return(NULL);
4888  if (ctx->node != NULL) {
4889  ret = xmlNodeGetBase(NULL,ctx->node);
4890  }
4891  else {
4892  /* inspired from error.c */
4894  input = ctx->input;
4895  if ((input->filename == NULL) && (ctx->inputNr > 1))
4896  input = ctx->inputTab[ctx->inputNr - 2];
4897  if (input != NULL) {
4898  ret = xmlStrdup(BAD_CAST input->filename);
4899  }
4900  else {
4901  ret = NULL;
4902  }
4903  }
4904 
4905  return ret;
4906 }
4907 
4908 static void
4909 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4910  char *str)
4911 {
4913 
4914  xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4915 
4916  if (str != NULL) {
4917  if (reader->errorFunc)
4918  reader->errorFunc(reader->errorFuncArg, str, severity,
4919  (xmlTextReaderLocatorPtr) ctx);
4920  xmlFree(str);
4921  }
4922 }
4923 
4924 static void
4925 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4926 {
4928 
4929  xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4930 
4931  if (error && reader->sErrorFunc) {
4932  reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4933  }
4934 }
4935 
4936 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4937 xmlTextReaderError(void *ctxt, const char *msg, ...)
4938 {
4939  va_list ap;
4940 
4941  va_start(ap, msg);
4942  xmlTextReaderGenericError(ctxt,
4944  xmlTextReaderBuildMessage(msg, ap));
4945  va_end(ap);
4946 
4947 }
4948 
4949 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4950 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4951 {
4952  va_list ap;
4953 
4954  va_start(ap, msg);
4955  xmlTextReaderGenericError(ctxt,
4957  xmlTextReaderBuildMessage(msg, ap));
4958  va_end(ap);
4959 }
4960 
4961 static void XMLCDECL
4962 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4963 {
4964  va_list ap;
4965 
4966  int len = xmlStrlen((const xmlChar *) msg);
4967 
4968  if ((len > 1) && (msg[len - 2] != ':')) {
4969  /*
4970  * some callbacks only report locator information:
4971  * skip them (mimicking behaviour in error.c)
4972  */
4973  va_start(ap, msg);
4974  xmlTextReaderGenericError(ctxt,
4976  xmlTextReaderBuildMessage(msg, ap));
4977  va_end(ap);
4978  }
4979 }
4980 
4981 static void XMLCDECL
4982 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4983 {
4984  va_list ap;
4985 
4986  int len = xmlStrlen((const xmlChar *) msg);
4987 
4988  if ((len != 0) && (msg[len - 1] != ':')) {
4989  /*
4990  * some callbacks only report locator information:
4991  * skip them (mimicking behaviour in error.c)
4992  */
4993  va_start(ap, msg);
4994  xmlTextReaderGenericError(ctxt,
4996  xmlTextReaderBuildMessage(msg, ap));
4997  va_end(ap);
4998  }
4999 }
5000 
5011 void
5012 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
5013  xmlTextReaderErrorFunc f, void *arg)
5014 {
5015  if (f != NULL) {
5016  reader->ctxt->sax->error = xmlTextReaderError;
5017  reader->ctxt->sax->serror = NULL;
5018  reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5019  reader->ctxt->sax->warning = xmlTextReaderWarning;
5020  reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5021  reader->errorFunc = f;
5022  reader->sErrorFunc = NULL;
5023  reader->errorFuncArg = arg;
5024 #ifdef LIBXML_SCHEMAS_ENABLED
5025  if (reader->rngValidCtxt) {
5026  xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
5027  xmlTextReaderValidityErrorRelay,
5028  xmlTextReaderValidityWarningRelay,
5029  reader);
5030  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5031  reader);
5032  }
5033  if (reader->xsdValidCtxt) {
5034  xmlSchemaSetValidErrors(reader->xsdValidCtxt,
5035  xmlTextReaderValidityErrorRelay,
5036  xmlTextReaderValidityWarningRelay,
5037  reader);
5038  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5039  reader);
5040  }
5041 #endif
5042  } else {
5043  /* restore defaults */
5044  reader->ctxt->sax->error = xmlParserError;
5045  reader->ctxt->vctxt.error = xmlParserValidityError;
5046  reader->ctxt->sax->warning = xmlParserWarning;
5047  reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5048  reader->errorFunc = NULL;
5049  reader->sErrorFunc = NULL;
5050  reader->errorFuncArg = NULL;
5051 #ifdef LIBXML_SCHEMAS_ENABLED
5052  if (reader->rngValidCtxt) {
5053  xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5054  reader);
5055  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5056  reader);
5057  }
5058  if (reader->xsdValidCtxt) {
5059  xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5060  reader);
5061  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5062  reader);
5063  }
5064 #endif
5065  }
5066 }
5067 
5078 void
5079 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5080  xmlStructuredErrorFunc f, void *arg)
5081 {
5082  if (f != NULL) {
5083  reader->ctxt->sax->error = NULL;
5084  reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5085  reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5086  reader->ctxt->sax->warning = xmlTextReaderWarning;
5087  reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5088  reader->sErrorFunc = f;
5089  reader->errorFunc = NULL;
5090  reader->errorFuncArg = arg;
5091 #ifdef LIBXML_SCHEMAS_ENABLED
5092  if (reader->rngValidCtxt) {
5093  xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5094  reader);
5095  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5096  xmlTextReaderValidityStructuredRelay,
5097  reader);
5098  }
5099  if (reader->xsdValidCtxt) {
5100  xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5101  reader);
5102  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5103  xmlTextReaderValidityStructuredRelay,
5104  reader);
5105  }
5106 #endif
5107  } else {
5108  /* restore defaults */
5109  reader->ctxt->sax->error = xmlParserError;
5110  reader->ctxt->sax->serror = NULL;
5111  reader->ctxt->vctxt.error = xmlParserValidityError;
5112  reader->ctxt->sax->warning = xmlParserWarning;
5113  reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5114  reader->errorFunc = NULL;
5115  reader->sErrorFunc = NULL;
5116  reader->errorFuncArg = NULL;
5117 #ifdef LIBXML_SCHEMAS_ENABLED
5118  if (reader->rngValidCtxt) {
5119  xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5120  reader);
5121  xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5122  reader);
5123  }
5124  if (reader->xsdValidCtxt) {
5125  xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5126  reader);
5127  xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5128  reader);
5129  }
5130 #endif
5131  }
5132 }
5133 
5142 int
5143 xmlTextReaderIsValid(xmlTextReaderPtr reader)
5144 {
5145  if (reader == NULL)
5146  return (-1);
5147 #ifdef LIBXML_SCHEMAS_ENABLED
5148  if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5149  return (reader->rngValidErrors == 0);
5150  if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5151  return (reader->xsdValidErrors == 0);
5152 #endif
5153  if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5154  return (reader->ctxt->valid);
5155  return (0);
5156 }
5157 
5166 void
5167 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5168  xmlTextReaderErrorFunc * f, void **arg)
5169 {
5170  if (f != NULL)
5171  *f = reader->errorFunc;
5172  if (arg != NULL)
5173  *arg = reader->errorFuncArg;
5174 }
5175 /************************************************************************
5176  * *
5177  * New set (2.6.0) of simpler and more flexible APIs *
5178  * *
5179  ************************************************************************/
5180 
5194 int
5195 xmlTextReaderSetup(xmlTextReaderPtr reader,
5196  xmlParserInputBufferPtr input, const char *URL,
5197  const char *encoding, int options)
5198 {
5199  if (reader == NULL) {
5200  if (input != NULL)
5202  return (-1);
5203  }
5204 
5205  /*
5206  * we force the generation of compact text nodes on the reader
5207  * since usr applications should never modify the tree
5208  */
5210 
5211  reader->doc = NULL;
5212  reader->entNr = 0;
5213  reader->parserFlags = options;
5214  reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5215  if ((input != NULL) && (reader->input != NULL) &&
5216  (reader->allocs & XML_TEXTREADER_INPUT)) {
5218  reader->input = NULL;
5219  reader->allocs -= XML_TEXTREADER_INPUT;
5220  }
5221  if (input != NULL) {
5222  reader->input = input;
5223  reader->allocs |= XML_TEXTREADER_INPUT;
5224  }
5225  if (reader->buffer == NULL)
5226  reader->buffer = xmlBufCreateSize(100);
5227  if (reader->buffer == NULL) {
5229  "xmlTextReaderSetup : malloc failed\n");
5230  return (-1);
5231  }
5232  /* no operation on a reader should require a huge buffer */
5235  if (reader->sax == NULL)
5236  reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5237  if (reader->sax == NULL) {
5239  "xmlTextReaderSetup : malloc failed\n");
5240  return (-1);
5241  }
5242  xmlSAXVersion(reader->sax, 2);
5243  reader->startElement = reader->sax->startElement;
5244  reader->sax->startElement = xmlTextReaderStartElement;
5245  reader->endElement = reader->sax->endElement;
5246  reader->sax->endElement = xmlTextReaderEndElement;
5247 #ifdef LIBXML_SAX1_ENABLED
5248  if (reader->sax->initialized == XML_SAX2_MAGIC) {
5249 #endif /* LIBXML_SAX1_ENABLED */
5250  reader->startElementNs = reader->sax->startElementNs;
5251  reader->sax->startElementNs = xmlTextReaderStartElementNs;
5252  reader->endElementNs = reader->sax->endElementNs;
5253  reader->sax->endElementNs = xmlTextReaderEndElementNs;
5254 #ifdef LIBXML_SAX1_ENABLED
5255  } else {
5256  reader->startElementNs = NULL;
5257  reader->endElementNs = NULL;
5258  }
5259 #endif /* LIBXML_SAX1_ENABLED */
5260  reader->characters = reader->sax->characters;
5261  reader->sax->characters = xmlTextReaderCharacters;
5262  reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5263  reader->cdataBlock = reader->sax->cdataBlock;
5264  reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5265 
5266  reader->mode = XML_TEXTREADER_MODE_INITIAL;
5267  reader->node = NULL;
5268  reader->curnode = NULL;
5269  if (input != NULL) {
5270  if (xmlBufUse(reader->input->buffer) < 4) {
5272  }
5273  if (reader->ctxt == NULL) {
5274  if (xmlBufUse(reader->input->buffer) >= 4) {
5275  reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5276  (const char *) xmlBufContent(reader->input->buffer),
5277  4, URL);
5278  reader->base = 0;
5279  reader->cur = 4;
5280  } else {
5281  reader->ctxt =
5282  xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5283  reader->base = 0;
5284  reader->cur = 0;
5285  }
5286  } else {
5287  xmlParserInputPtr inputStream;
5290 
5291  xmlCtxtReset(reader->ctxt);
5293  if (buf == NULL) return(-1);
5294  inputStream = xmlNewInputStream(reader->ctxt);
5295  if (inputStream == NULL) {
5297  return(-1);
5298  }
5299 
5300  if (URL == NULL)
5301  inputStream->filename = NULL;
5302  else
5303  inputStream->filename = (char *)
5304  xmlCanonicPath((const xmlChar *) URL);
5305  inputStream->buf = buf;
5306  xmlBufResetInput(buf->buffer, inputStream);
5307 
5308  inputPush(reader->ctxt, inputStream);
5309  reader->cur = 0;
5310  }
5311  if (reader->ctxt == NULL) {
5313  "xmlTextReaderSetup : malloc failed\n");
5314  return (-1);
5315  }
5316  }
5317  if (reader->dict != NULL) {
5318  if (reader->ctxt->dict != NULL) {
5319  if (reader->dict != reader->ctxt->dict) {
5320  xmlDictFree(reader->dict);
5321  reader->dict = reader->ctxt->dict;
5322  }
5323  } else {
5324  reader->ctxt->dict = reader->dict;
5325  }
5326  } else {
5327  if (reader->ctxt->dict == NULL)
5328  reader->ctxt->dict = xmlDictCreate();
5329  reader->dict = reader->ctxt->dict;
5330  }
5331  reader->ctxt->_private = reader;
5332  reader->ctxt->linenumbers = 1;
5333  reader->ctxt->dictNames = 1;
5334  /*
5335  * use the parser dictionary to allocate all elements and attributes names
5336  */
5337  reader->ctxt->docdict = 1;
5338  reader->ctxt->parseMode = XML_PARSE_READER;
5339 
5340 #ifdef LIBXML_XINCLUDE_ENABLED
5341  if (reader->xincctxt != NULL) {
5342  xmlXIncludeFreeContext(reader->xincctxt);
5343  reader->xincctxt = NULL;
5344  }
5345  if (options & XML_PARSE_XINCLUDE) {
5346  reader->xinclude = 1;
5347  reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5349  } else
5350  reader->xinclude = 0;
5351  reader->in_xinclude = 0;
5352 #endif
5353 #ifdef LIBXML_PATTERN_ENABLED
5354  if (reader->patternTab == NULL) {
5355  reader->patternNr = 0;
5356  reader->patternMax = 0;
5357  }
5358  while (reader->patternNr > 0) {
5359  reader->patternNr--;
5360  if (reader->patternTab[reader->patternNr] != NULL) {
5361  xmlFreePattern(reader->patternTab[reader->patternNr]);
5362  reader->patternTab[reader->patternNr] = NULL;
5363  }
5364  }
5365 #endif
5366 
5368  reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5369 
5371  if (encoding != NULL) {
5373 
5375  if (hdlr != NULL)
5376  xmlSwitchToEncoding(reader->ctxt, hdlr);
5377  }
5378  if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5379  (reader->ctxt->input->filename == NULL))
5380  reader->ctxt->input->filename = (char *)
5381  xmlStrdup((const xmlChar *) URL);
5382 
5383  reader->doc = NULL;
5384 
5385  return (0);
5386 }
5387 
5401 long
5402 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5403  if ((reader == NULL) || (reader->ctxt == NULL))
5404  return(-1);
5405  return(xmlByteConsumed(reader->ctxt));
5406 }
5407 
5408 
5417 xmlTextReaderPtr
5418 xmlReaderWalker(xmlDocPtr doc)
5419 {
5420  xmlTextReaderPtr ret;
5421 
5422  if (doc == NULL)
5423  return(NULL);
5424 
5425  ret = xmlMalloc(sizeof(xmlTextReader));
5426  if (ret == NULL) {
5428  "xmlNewTextReader : malloc failed\n");
5429  return(NULL);
5430  }
5431  memset(ret, 0, sizeof(xmlTextReader));
5432  ret->entNr = 0;
5433  ret->input = NULL;
5434  ret->mode = XML_TEXTREADER_MODE_INITIAL;
5435  ret->node = NULL;
5436  ret->curnode = NULL;
5437  ret->base = 0;
5438  ret->cur = 0;
5439  ret->allocs = XML_TEXTREADER_CTXT;
5440  ret->doc = doc;
5441  ret->state = XML_TEXTREADER_START;
5442  ret->dict = xmlDictCreate();
5443  return(ret);
5444 }
5445 
5458 xmlTextReaderPtr
5459 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5460  int options)
5461 {
5462  int len;
5463 
5464  if (cur == NULL)
5465  return (NULL);
5466  len = xmlStrlen(cur);
5467 
5468  return (xmlReaderForMemory
5469  ((const char *) cur, len, URL, encoding, options));
5470 }
5471 
5483 xmlTextReaderPtr
5484 xmlReaderForFile(const char *filename, const char *encoding, int options)
5485 {
5486  xmlTextReaderPtr reader;
5487 
5488  reader = xmlNewTextReaderFilename(filename);
5489  if (reader == NULL)
5490  return (NULL);
5491  xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5492  return (reader);
5493 }
5494 
5508 xmlTextReaderPtr
5509 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5510  const char *encoding, int options)
5511 {
5512  xmlTextReaderPtr reader;
5514 
5517  if (buf == NULL) {
5518  return (NULL);
5519  }
5520  reader = xmlNewTextReader(buf, URL);
5521  if (reader == NULL) {
5523  return (NULL);
5524  }
5525  reader->allocs |= XML_TEXTREADER_INPUT;
5526  xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5527  return (reader);
5528 }
5529 
5544 xmlTextReaderPtr
5545 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5546 {
5547  xmlTextReaderPtr reader;
5549 
5550  if (fd < 0)
5551  return (NULL);
5552 
5554  if (input == NULL)
5555  return (NULL);
5556  input->closecallback = NULL;
5557  reader = xmlNewTextReader(input, URL);
5558  if (reader == NULL) {
5560  return (NULL);
5561  }
5562  reader->allocs |= XML_TEXTREADER_INPUT;
5563  xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5564  return (reader);
5565 }
5566 
5581 xmlTextReaderPtr
5582 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5583  void *ioctx, const char *URL, const char *encoding,
5584  int options)
5585 {
5586  xmlTextReaderPtr reader;
5588 
5589  if (ioread == NULL)
5590  return (NULL);
5591 
5592  input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5594  if (input == NULL) {
5595  if (ioclose != NULL)
5596  ioclose(ioctx);
5597  return (NULL);
5598  }
5599  reader = xmlNewTextReader(input, URL);
5600  if (reader == NULL) {
5602  return (NULL);
5603  }
5604  reader->allocs |= XML_TEXTREADER_INPUT;
5605  xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5606  return (reader);
5607 }
5608 
5619 int
5620 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5621 {
5622  if (doc == NULL)
5623  return (-1);
5624  if (reader == NULL)
5625  return (-1);
5626 
5627  if (reader->input != NULL) {
5629  }
5630  if (reader->ctxt != NULL) {
5631  xmlCtxtReset(reader->ctxt);
5632  }
5633 
5634  reader->entNr = 0;
5635  reader->input = NULL;
5636  reader->mode = XML_TEXTREADER_MODE_INITIAL;
5637  reader->node = NULL;
5638  reader->curnode = NULL;
5639  reader->base = 0;
5640  reader->cur = 0;
5641  reader->allocs = XML_TEXTREADER_CTXT;
5642  reader->doc = doc;
5643  reader->state = XML_TEXTREADER_START;
5644  if (reader->dict == NULL) {
5645  if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5646  reader->dict = reader->ctxt->dict;
5647  else
5648  reader->dict = xmlDictCreate();
5649  }
5650  return(0);
5651 }
5652 
5667 int
5668 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5669  const char *URL, const char *encoding, int options)
5670 {
5671 
5672  int len;
5673 
5674  if (cur == NULL)
5675  return (-1);
5676  if (reader == NULL)
5677  return (-1);
5678 
5679  len = xmlStrlen(cur);
5680  return (xmlReaderNewMemory(reader, (const char *)cur, len,
5681  URL, encoding, options));
5682 }
5683 
5697 int
5698 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5699  const char *encoding, int options)
5700 {
5702 
5703  if (filename == NULL)
5704  return (-1);
5705  if (reader == NULL)
5706  return (-1);
5707 
5708  input =
5711  if (input == NULL)
5712  return (-1);
5713  return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5714 }
5715 
5731 int
5732 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5733  const char *URL, const char *encoding, int options)
5734 {
5736 
5737  if (reader == NULL)
5738  return (-1);
5739  if (buffer == NULL)
5740  return (-1);
5741 
5744  if (input == NULL) {
5745  return (-1);
5746  }
5747  return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5748 }
5749 
5766 int
5767 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5768  const char *URL, const char *encoding, int options)
5769 {
5771 
5772  if (fd < 0)
5773  return (-1);
5774  if (reader == NULL)
5775  return (-1);
5776 
5778  if (input == NULL)
5779  return (-1);
5780  input->closecallback = NULL;
5781  return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5782 }
5783 
5801 int
5802 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5803  xmlInputCloseCallback ioclose, void *ioctx,
5804  const char *URL, const char *encoding, int options)
5805 {
5807 
5808  if (ioread == NULL)
5809  return (-1);
5810  if (reader == NULL)
5811  return (-1);
5812 
5813  input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5815  if (input == NULL) {
5816  if (ioclose != NULL)
5817  ioclose(ioctx);
5818  return (-1);
5819  }
5820  return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5821 }
5822 
5823 /************************************************************************
5824  * *
5825  * Utilities *
5826  * *
5827  ************************************************************************/
5828 #ifdef NOT_USED_YET
5829 
5843 static int
5844 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5845  unsigned char *to, unsigned long *tolen)
5846 {
5847  unsigned long incur; /* current index in in[] */
5848 
5849  unsigned long inblk; /* last block index in in[] */
5850 
5851  unsigned long outcur; /* current index in out[] */
5852 
5853  unsigned long inmax; /* size of in[] */
5854 
5855  unsigned long outmax; /* size of out[] */
5856 
5857  unsigned char cur; /* the current value read from in[] */
5858 
5859  unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5860 
5861  int nbintmp; /* number of byte in intmp[] */
5862 
5863  int is_ignore; /* cur should be ignored */
5864 
5865  int is_end = 0; /* the end of the base64 was found */
5866 
5867  int retval = 1;
5868 
5869  int i;
5870 
5871  if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5872  return (-1);
5873 
5874  incur = 0;
5875  inblk = 0;
5876  outcur = 0;
5877  inmax = *inlen;
5878  outmax = *tolen;
5879  nbintmp = 0;
5880 
5881  while (1) {
5882  if (incur >= inmax)
5883  break;
5884  cur = in[incur++];
5885  is_ignore = 0;
5886  if ((cur >= 'A') && (cur <= 'Z'))
5887  cur = cur - 'A';
5888  else if ((cur >= 'a') && (cur <= 'z'))
5889  cur = cur - 'a' + 26;
5890  else if ((cur >= '0') && (cur <= '9'))
5891  cur = cur - '0' + 52;
5892  else if (cur == '+')
5893  cur = 62;
5894  else if (cur == '/')
5895  cur = 63;
5896  else if (cur == '.')
5897  cur = 0;
5898  else if (cur == '=') /*no op , end of the base64 stream */
5899  is_end = 1;
5900  else {
5901  is_ignore = 1;
5902  if (nbintmp == 0)
5903  inblk = incur;
5904  }
5905 
5906  if (!is_ignore) {
5907  int nbouttmp = 3;
5908 
5909  int is_break = 0;
5910 
5911  if (is_end) {
5912  if (nbintmp == 0)
5913  break;
5914  if ((nbintmp == 1) || (nbintmp == 2))
5915