[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / third_party / libxml / src / xmlreader.c
blobe39faec8008c5e2c50b3a0da566c8dbeefc164f6
1 /*
2 * xmlreader.c: implements the xmlTextReader streaming node API
4 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
8 * See Copyright for the status of this software.
10 * daniel@veillard.com
14 * TODOs:
15 * - XML Schemas validation
17 #define IN_LIBXML
18 #include "libxml.h"
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
24 #ifdef HAVE_CTYPE_H
25 #include <ctype.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
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
47 #define MAX_ERR_MSG_SIZE 64000
50 * The following VA_COPY was coded following an example in
51 * the Samba project. It may not be sufficient for some
52 * esoteric implementations of va_list (i.e. it may need
53 * something involving a memcpy) but (hopefully) will be
54 * sufficient for libxml2.
56 #ifndef VA_COPY
57 #ifdef HAVE_VA_COPY
58 #define VA_COPY(dest, src) va_copy(dest, src)
59 #else
60 #ifdef HAVE___VA_COPY
61 #define VA_COPY(dest,src) __va_copy(dest, src)
62 #else
63 #define VA_COPY(dest,src) (dest) = (src)
64 #endif
65 #endif
66 #endif
68 /* #define DEBUG_CALLBACKS */
69 /* #define DEBUG_READER */
71 /**
72 * TODO:
74 * macro to flag unimplemented blocks
76 #define TODO \
77 xmlGenericError(xmlGenericErrorContext, \
78 "Unimplemented block at %s:%d\n", \
79 __FILE__, __LINE__);
81 #ifdef DEBUG_READER
82 #define DUMP_READER xmlTextReaderDebug(reader);
83 #else
84 #define DUMP_READER
85 #endif
87 #define CHUNK_SIZE 512
88 /************************************************************************
89 * *
90 * The parser: maps the Text Reader API on top of the existing *
91 * parsing routines building a tree *
92 * *
93 ************************************************************************/
95 #define XML_TEXTREADER_INPUT 1
96 #define XML_TEXTREADER_CTXT 2
98 typedef enum {
99 XML_TEXTREADER_NONE = -1,
100 XML_TEXTREADER_START= 0,
101 XML_TEXTREADER_ELEMENT= 1,
102 XML_TEXTREADER_END= 2,
103 XML_TEXTREADER_EMPTY= 3,
104 XML_TEXTREADER_BACKTRACK= 4,
105 XML_TEXTREADER_DONE= 5,
106 XML_TEXTREADER_ERROR= 6
107 } xmlTextReaderState;
109 typedef enum {
110 XML_TEXTREADER_NOT_VALIDATE = 0,
111 XML_TEXTREADER_VALIDATE_DTD = 1,
112 XML_TEXTREADER_VALIDATE_RNG = 2,
113 XML_TEXTREADER_VALIDATE_XSD = 4
114 } xmlTextReaderValidate;
116 struct _xmlTextReader {
117 int mode; /* the parsing mode */
118 xmlDocPtr doc; /* when walking an existing doc */
119 xmlTextReaderValidate validate;/* is there any validation */
120 int allocs; /* what structure were deallocated */
121 xmlTextReaderState state;
122 xmlParserCtxtPtr ctxt; /* the parser context */
123 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
124 xmlParserInputBufferPtr input; /* the input */
125 startElementSAXFunc startElement;/* initial SAX callbacks */
126 endElementSAXFunc endElement; /* idem */
127 startElementNsSAX2Func startElementNs;/* idem */
128 endElementNsSAX2Func endElementNs; /* idem */
129 charactersSAXFunc characters;
130 cdataBlockSAXFunc cdataBlock;
131 unsigned int base; /* base of the segment in the input */
132 unsigned int cur; /* current position in the input */
133 xmlNodePtr node; /* current node */
134 xmlNodePtr curnode;/* current attribute node */
135 int depth; /* depth of the current node */
136 xmlNodePtr faketext;/* fake xmlNs chld */
137 int preserve;/* preserve the resulting document */
138 xmlBufferPtr buffer; /* used to return const xmlChar * */
139 xmlDictPtr dict; /* the context dictionnary */
141 /* entity stack when traversing entities content */
142 xmlNodePtr ent; /* Current Entity Ref Node */
143 int entNr; /* Depth of the entities stack */
144 int entMax; /* Max depth of the entities stack */
145 xmlNodePtr *entTab; /* array of entities */
147 /* error handling */
148 xmlTextReaderErrorFunc errorFunc; /* callback function */
149 void *errorFuncArg; /* callback function user argument */
151 #ifdef LIBXML_SCHEMAS_ENABLED
152 /* Handling of RelaxNG validation */
153 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
154 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
155 int rngValidErrors;/* The number of errors detected */
156 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
157 /* Handling of Schemas validation */
158 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
159 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
160 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
161 int xsdValidErrors;/* The number of errors detected */
162 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
163 #endif
164 #ifdef LIBXML_XINCLUDE_ENABLED
165 /* Handling of XInclude processing */
166 int xinclude; /* is xinclude asked for */
167 const xmlChar * xinclude_name; /* the xinclude name from dict */
168 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
169 int in_xinclude; /* counts for xinclude */
170 #endif
171 #ifdef LIBXML_PATTERN_ENABLED
172 int patternNr; /* number of preserve patterns */
173 int patternMax; /* max preserve patterns */
174 xmlPatternPtr *patternTab; /* array of preserve patterns */
175 #endif
176 int preserves; /* level of preserves */
177 int parserFlags; /* the set of options set */
178 /* Structured error handling */
179 xmlStructuredErrorFunc sErrorFunc; /* callback function */
182 #define NODE_IS_EMPTY 0x1
183 #define NODE_IS_PRESERVED 0x2
184 #define NODE_IS_SPRESERVED 0x4
187 * CONSTSTR:
189 * Macro used to return an interned string
191 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
192 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
194 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
195 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
197 /************************************************************************
199 * Our own version of the freeing routines as we recycle nodes *
201 ************************************************************************/
203 * DICT_FREE:
204 * @str: a string
206 * Free a string if it is not owned by the "dict" dictionnary in the
207 * current scope
209 #define DICT_FREE(str) \
210 if ((str) && ((!dict) || \
211 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
212 xmlFree((char *)(str));
214 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
215 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
218 * xmlFreeID:
219 * @not: A id
221 * Deallocate the memory used by an id definition
223 static void
224 xmlFreeID(xmlIDPtr id) {
225 xmlDictPtr dict = NULL;
227 if (id == NULL) return;
229 if (id->doc != NULL)
230 dict = id->doc->dict;
232 if (id->value != NULL)
233 DICT_FREE(id->value)
234 xmlFree(id);
238 * xmlTextReaderRemoveID:
239 * @doc: the document
240 * @attr: the attribute
242 * Remove the given attribute from the ID table maintained internally.
244 * Returns -1 if the lookup failed and 0 otherwise
246 static int
247 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
248 xmlIDTablePtr table;
249 xmlIDPtr id;
250 xmlChar *ID;
252 if (doc == NULL) return(-1);
253 if (attr == NULL) return(-1);
254 table = (xmlIDTablePtr) doc->ids;
255 if (table == NULL)
256 return(-1);
258 ID = xmlNodeListGetString(doc, attr->children, 1);
259 if (ID == NULL)
260 return(-1);
261 id = xmlHashLookup(table, ID);
262 xmlFree(ID);
263 if (id == NULL || id->attr != attr) {
264 return(-1);
266 id->name = attr->name;
267 id->attr = NULL;
268 return(0);
272 * xmlTextReaderFreeProp:
273 * @reader: the xmlTextReaderPtr used
274 * @cur: the node
276 * Free a node.
278 static void
279 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
280 xmlDictPtr dict;
282 dict = reader->ctxt->dict;
283 if (cur == NULL) return;
285 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
286 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
288 /* Check for ID removal -> leading to invalid references ! */
289 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
290 ((cur->parent->doc->intSubset != NULL) ||
291 (cur->parent->doc->extSubset != NULL))) {
292 if (xmlIsID(cur->parent->doc, cur->parent, cur))
293 xmlTextReaderRemoveID(cur->parent->doc, cur);
295 if (cur->children != NULL)
296 xmlTextReaderFreeNodeList(reader, cur->children);
298 DICT_FREE(cur->name);
299 if ((reader != NULL) && (reader->ctxt != NULL) &&
300 (reader->ctxt->freeAttrsNr < 100)) {
301 cur->next = reader->ctxt->freeAttrs;
302 reader->ctxt->freeAttrs = cur;
303 reader->ctxt->freeAttrsNr++;
304 } else {
305 xmlFree(cur);
310 * xmlTextReaderFreePropList:
311 * @reader: the xmlTextReaderPtr used
312 * @cur: the first property in the list
314 * Free a property and all its siblings, all the children are freed too.
316 static void
317 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
318 xmlAttrPtr next;
319 if (cur == NULL) return;
320 while (cur != NULL) {
321 next = cur->next;
322 xmlTextReaderFreeProp(reader, cur);
323 cur = next;
328 * xmlTextReaderFreeNodeList:
329 * @reader: the xmlTextReaderPtr used
330 * @cur: the first node in the list
332 * Free a node and all its siblings, this is a recursive behaviour, all
333 * the children are freed too.
335 static void
336 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
337 xmlNodePtr next;
338 xmlDictPtr dict;
340 dict = reader->ctxt->dict;
341 if (cur == NULL) return;
342 if (cur->type == XML_NAMESPACE_DECL) {
343 xmlFreeNsList((xmlNsPtr) cur);
344 return;
346 if ((cur->type == XML_DOCUMENT_NODE) ||
347 (cur->type == XML_HTML_DOCUMENT_NODE)) {
348 xmlFreeDoc((xmlDocPtr) cur);
349 return;
351 while (cur != NULL) {
352 next = cur->next;
353 /* unroll to speed up freeing the document */
354 if (cur->type != XML_DTD_NODE) {
356 if ((cur->children != NULL) &&
357 (cur->type != XML_ENTITY_REF_NODE)) {
358 if (cur->children->parent == cur)
359 xmlTextReaderFreeNodeList(reader, cur->children);
360 cur->children = NULL;
363 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
364 xmlDeregisterNodeDefaultValue(cur);
366 if (((cur->type == XML_ELEMENT_NODE) ||
367 (cur->type == XML_XINCLUDE_START) ||
368 (cur->type == XML_XINCLUDE_END)) &&
369 (cur->properties != NULL))
370 xmlTextReaderFreePropList(reader, cur->properties);
371 if ((cur->content != (xmlChar *) &(cur->properties)) &&
372 (cur->type != XML_ELEMENT_NODE) &&
373 (cur->type != XML_XINCLUDE_START) &&
374 (cur->type != XML_XINCLUDE_END) &&
375 (cur->type != XML_ENTITY_REF_NODE)) {
376 DICT_FREE(cur->content);
378 if (((cur->type == XML_ELEMENT_NODE) ||
379 (cur->type == XML_XINCLUDE_START) ||
380 (cur->type == XML_XINCLUDE_END)) &&
381 (cur->nsDef != NULL))
382 xmlFreeNsList(cur->nsDef);
385 * we don't free element names here they are interned now
387 if ((cur->type != XML_TEXT_NODE) &&
388 (cur->type != XML_COMMENT_NODE))
389 DICT_FREE(cur->name);
390 if (((cur->type == XML_ELEMENT_NODE) ||
391 (cur->type == XML_TEXT_NODE)) &&
392 (reader != NULL) && (reader->ctxt != NULL) &&
393 (reader->ctxt->freeElemsNr < 100)) {
394 cur->next = reader->ctxt->freeElems;
395 reader->ctxt->freeElems = cur;
396 reader->ctxt->freeElemsNr++;
397 } else {
398 xmlFree(cur);
401 cur = next;
406 * xmlTextReaderFreeNode:
407 * @reader: the xmlTextReaderPtr used
408 * @cur: the node
410 * Free a node, this is a recursive behaviour, all the children are freed too.
411 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
413 static void
414 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
415 xmlDictPtr dict;
417 dict = reader->ctxt->dict;
418 if (cur->type == XML_DTD_NODE) {
419 xmlFreeDtd((xmlDtdPtr) cur);
420 return;
422 if (cur->type == XML_NAMESPACE_DECL) {
423 xmlFreeNs((xmlNsPtr) cur);
424 return;
426 if (cur->type == XML_ATTRIBUTE_NODE) {
427 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
428 return;
431 if ((cur->children != NULL) &&
432 (cur->type != XML_ENTITY_REF_NODE)) {
433 if (cur->children->parent == cur)
434 xmlTextReaderFreeNodeList(reader, cur->children);
435 cur->children = NULL;
438 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
439 xmlDeregisterNodeDefaultValue(cur);
441 if (((cur->type == XML_ELEMENT_NODE) ||
442 (cur->type == XML_XINCLUDE_START) ||
443 (cur->type == XML_XINCLUDE_END)) &&
444 (cur->properties != NULL))
445 xmlTextReaderFreePropList(reader, cur->properties);
446 if ((cur->content != (xmlChar *) &(cur->properties)) &&
447 (cur->type != XML_ELEMENT_NODE) &&
448 (cur->type != XML_XINCLUDE_START) &&
449 (cur->type != XML_XINCLUDE_END) &&
450 (cur->type != XML_ENTITY_REF_NODE)) {
451 DICT_FREE(cur->content);
453 if (((cur->type == XML_ELEMENT_NODE) ||
454 (cur->type == XML_XINCLUDE_START) ||
455 (cur->type == XML_XINCLUDE_END)) &&
456 (cur->nsDef != NULL))
457 xmlFreeNsList(cur->nsDef);
460 * we don't free names here they are interned now
462 if ((cur->type != XML_TEXT_NODE) &&
463 (cur->type != XML_COMMENT_NODE))
464 DICT_FREE(cur->name);
466 if (((cur->type == XML_ELEMENT_NODE) ||
467 (cur->type == XML_TEXT_NODE)) &&
468 (reader != NULL) && (reader->ctxt != NULL) &&
469 (reader->ctxt->freeElemsNr < 100)) {
470 cur->next = reader->ctxt->freeElems;
471 reader->ctxt->freeElems = cur;
472 reader->ctxt->freeElemsNr++;
473 } else {
474 xmlFree(cur);
479 * xmlTextReaderFreeIDTable:
480 * @table: An id table
482 * Deallocate the memory used by an ID hash table.
484 static void
485 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
486 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
490 * xmlTextReaderFreeDoc:
491 * @reader: the xmlTextReaderPtr used
492 * @cur: pointer to the document
494 * Free up all the structures used by a document, tree included.
496 static void
497 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
498 xmlDtdPtr extSubset, intSubset;
500 if (cur == NULL) return;
502 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
503 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
506 * Do this before freeing the children list to avoid ID lookups
508 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
509 cur->ids = NULL;
510 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
511 cur->refs = NULL;
512 extSubset = cur->extSubset;
513 intSubset = cur->intSubset;
514 if (intSubset == extSubset)
515 extSubset = NULL;
516 if (extSubset != NULL) {
517 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
518 cur->extSubset = NULL;
519 xmlFreeDtd(extSubset);
521 if (intSubset != NULL) {
522 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
523 cur->intSubset = NULL;
524 xmlFreeDtd(intSubset);
527 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
529 if (cur->version != NULL) xmlFree((char *) cur->version);
530 if (cur->name != NULL) xmlFree((char *) cur->name);
531 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
532 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
533 if (cur->URL != NULL) xmlFree((char *) cur->URL);
534 if (cur->dict != NULL) xmlDictFree(cur->dict);
536 xmlFree(cur);
539 /************************************************************************
541 * The reader core parser *
543 ************************************************************************/
544 #ifdef DEBUG_READER
545 static void
546 xmlTextReaderDebug(xmlTextReaderPtr reader) {
547 if ((reader == NULL) || (reader->ctxt == NULL)) {
548 fprintf(stderr, "xmlTextReader NULL\n");
549 return;
551 fprintf(stderr, "xmlTextReader: state %d depth %d ",
552 reader->state, reader->depth);
553 if (reader->node == NULL) {
554 fprintf(stderr, "node = NULL\n");
555 } else {
556 fprintf(stderr, "node %s\n", reader->node->name);
558 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
559 reader->base, reader->cur, reader->ctxt->nodeNr);
560 if (reader->input->buffer == NULL) {
561 fprintf(stderr, "buffer is NULL\n");
562 } else {
563 #ifdef LIBXML_DEBUG_ENABLED
564 xmlDebugDumpString(stderr,
565 &reader->input->buffer->content[reader->cur]);
566 #endif
567 fprintf(stderr, "\n");
570 #endif
573 * xmlTextReaderEntPush:
574 * @reader: the xmlTextReaderPtr used
575 * @value: the entity reference node
577 * Pushes a new entity reference node on top of the entities stack
579 * Returns 0 in case of error, the index in the stack otherwise
581 static int
582 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
584 if (reader->entMax <= 0) {
585 reader->entMax = 10;
586 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
587 sizeof(reader->entTab[0]));
588 if (reader->entTab == NULL) {
589 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
590 return (0);
593 if (reader->entNr >= reader->entMax) {
594 reader->entMax *= 2;
595 reader->entTab =
596 (xmlNodePtr *) xmlRealloc(reader->entTab,
597 reader->entMax *
598 sizeof(reader->entTab[0]));
599 if (reader->entTab == NULL) {
600 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
601 return (0);
604 reader->entTab[reader->entNr] = value;
605 reader->ent = value;
606 return (reader->entNr++);
610 * xmlTextReaderEntPop:
611 * @reader: the xmlTextReaderPtr used
613 * Pops the top element entity from the entities stack
615 * Returns the entity just removed
617 static xmlNodePtr
618 xmlTextReaderEntPop(xmlTextReaderPtr reader)
620 xmlNodePtr ret;
622 if (reader->entNr <= 0)
623 return (NULL);
624 reader->entNr--;
625 if (reader->entNr > 0)
626 reader->ent = reader->entTab[reader->entNr - 1];
627 else
628 reader->ent = NULL;
629 ret = reader->entTab[reader->entNr];
630 reader->entTab[reader->entNr] = NULL;
631 return (ret);
635 * xmlTextReaderStartElement:
636 * @ctx: the user data (XML parser context)
637 * @fullname: The element name, including namespace prefix
638 * @atts: An array of name/value attributes pairs, NULL terminated
640 * called when an opening tag has been processed.
642 static void
643 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
644 const xmlChar **atts) {
645 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
646 xmlTextReaderPtr reader = ctxt->_private;
648 #ifdef DEBUG_CALLBACKS
649 printf("xmlTextReaderStartElement(%s)\n", fullname);
650 #endif
651 if ((reader != NULL) && (reader->startElement != NULL)) {
652 reader->startElement(ctx, fullname, atts);
653 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
654 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
655 (ctxt->input->cur[1] == '>'))
656 ctxt->node->extra = NODE_IS_EMPTY;
658 if (reader != NULL)
659 reader->state = XML_TEXTREADER_ELEMENT;
663 * xmlTextReaderEndElement:
664 * @ctx: the user data (XML parser context)
665 * @fullname: The element name, including namespace prefix
667 * called when an ending tag has been processed.
669 static void
670 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
671 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
672 xmlTextReaderPtr reader = ctxt->_private;
674 #ifdef DEBUG_CALLBACKS
675 printf("xmlTextReaderEndElement(%s)\n", fullname);
676 #endif
677 if ((reader != NULL) && (reader->endElement != NULL)) {
678 reader->endElement(ctx, fullname);
683 * xmlTextReaderStartElementNs:
684 * @ctx: the user data (XML parser context)
685 * @localname: the local name of the element
686 * @prefix: the element namespace prefix if available
687 * @URI: the element namespace name if available
688 * @nb_namespaces: number of namespace definitions on that node
689 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
690 * @nb_attributes: the number of attributes on that node
691 * nb_defaulted: the number of defaulted attributes.
692 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
693 * attribute values.
695 * called when an opening tag has been processed.
697 static void
698 xmlTextReaderStartElementNs(void *ctx,
699 const xmlChar *localname,
700 const xmlChar *prefix,
701 const xmlChar *URI,
702 int nb_namespaces,
703 const xmlChar **namespaces,
704 int nb_attributes,
705 int nb_defaulted,
706 const xmlChar **attributes)
708 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
709 xmlTextReaderPtr reader = ctxt->_private;
711 #ifdef DEBUG_CALLBACKS
712 printf("xmlTextReaderStartElementNs(%s)\n", localname);
713 #endif
714 if ((reader != NULL) && (reader->startElementNs != NULL)) {
715 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
716 namespaces, nb_attributes, nb_defaulted,
717 attributes);
718 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
719 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
720 (ctxt->input->cur[1] == '>'))
721 ctxt->node->extra = NODE_IS_EMPTY;
723 if (reader != NULL)
724 reader->state = XML_TEXTREADER_ELEMENT;
728 * xmlTextReaderEndElementNs:
729 * @ctx: the user data (XML parser context)
730 * @localname: the local name of the element
731 * @prefix: the element namespace prefix if available
732 * @URI: the element namespace name if available
734 * called when an ending tag has been processed.
736 static void
737 xmlTextReaderEndElementNs(void *ctx,
738 const xmlChar * localname,
739 const xmlChar * prefix,
740 const xmlChar * URI)
742 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
743 xmlTextReaderPtr reader = ctxt->_private;
745 #ifdef DEBUG_CALLBACKS
746 printf("xmlTextReaderEndElementNs(%s)\n", localname);
747 #endif
748 if ((reader != NULL) && (reader->endElementNs != NULL)) {
749 reader->endElementNs(ctx, localname, prefix, URI);
755 * xmlTextReaderCharacters:
756 * @ctx: the user data (XML parser context)
757 * @ch: a xmlChar string
758 * @len: the number of xmlChar
760 * receiving some chars from the parser.
762 static void
763 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
765 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
766 xmlTextReaderPtr reader = ctxt->_private;
768 #ifdef DEBUG_CALLBACKS
769 printf("xmlTextReaderCharacters()\n");
770 #endif
771 if ((reader != NULL) && (reader->characters != NULL)) {
772 reader->characters(ctx, ch, len);
777 * xmlTextReaderCDataBlock:
778 * @ctx: the user data (XML parser context)
779 * @value: The pcdata content
780 * @len: the block length
782 * called when a pcdata block has been parsed
784 static void
785 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
787 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
788 xmlTextReaderPtr reader = ctxt->_private;
790 #ifdef DEBUG_CALLBACKS
791 printf("xmlTextReaderCDataBlock()\n");
792 #endif
793 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
794 reader->cdataBlock(ctx, ch, len);
799 * xmlTextReaderPushData:
800 * @reader: the xmlTextReaderPtr used
802 * Push data down the progressive parser until a significant callback
803 * got raised.
805 * Returns -1 in case of failure, 0 otherwise
807 static int
808 xmlTextReaderPushData(xmlTextReaderPtr reader) {
809 xmlBufferPtr inbuf;
810 int val, s;
811 xmlTextReaderState oldstate;
813 if ((reader->input == NULL) || (reader->input->buffer == NULL))
814 return(-1);
816 oldstate = reader->state;
817 reader->state = XML_TEXTREADER_NONE;
818 inbuf = reader->input->buffer;
820 while (reader->state == XML_TEXTREADER_NONE) {
821 if (inbuf->use < reader->cur + CHUNK_SIZE) {
823 * Refill the buffer unless we are at the end of the stream
825 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
826 val = xmlParserInputBufferRead(reader->input, 4096);
827 if ((val == 0) &&
828 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
829 if (inbuf->use == reader->cur) {
830 reader->mode = XML_TEXTREADER_MODE_EOF;
831 reader->state = oldstate;
833 } else if (val < 0) {
834 reader->mode = XML_TEXTREADER_MODE_EOF;
835 reader->state = oldstate;
836 if ((oldstate != XML_TEXTREADER_START) ||
837 (reader->ctxt->myDoc != NULL))
838 return(val);
839 } else if (val == 0) {
840 /* mark the end of the stream and process the remains */
841 reader->mode = XML_TEXTREADER_MODE_EOF;
842 break;
845 } else
846 break;
849 * parse by block of CHUNK_SIZE bytes, various tests show that
850 * it's the best tradeoff at least on a 1.2GH Duron
852 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
853 val = xmlParseChunk(reader->ctxt,
854 (const char *) &inbuf->content[reader->cur],
855 CHUNK_SIZE, 0);
856 reader->cur += CHUNK_SIZE;
857 if ((val != 0) || (reader->ctxt->wellFormed == 0))
858 return(-1);
859 } else {
860 s = inbuf->use - reader->cur;
861 val = xmlParseChunk(reader->ctxt,
862 (const char *) &inbuf->content[reader->cur],
863 s, 0);
864 reader->cur += s;
865 if ((val != 0) || (reader->ctxt->wellFormed == 0))
866 return(-1);
867 break;
872 * Discard the consumed input when needed and possible
874 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
875 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
876 if ((reader->cur >= 4096) &&
877 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
878 val = xmlBufferShrink(inbuf, reader->cur);
879 if (val >= 0) {
880 reader->cur -= val;
887 * At the end of the stream signal that the work is done to the Push
888 * parser.
890 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
891 if (reader->state != XML_TEXTREADER_DONE) {
892 s = inbuf->use - reader->cur;
893 val = xmlParseChunk(reader->ctxt,
894 (const char *) &inbuf->content[reader->cur],
895 s, 1);
896 reader->cur = inbuf->use;
897 reader->state = XML_TEXTREADER_DONE;
898 if ((val != 0) || (reader->ctxt->wellFormed == 0))
899 return(-1);
902 reader->state = oldstate;
903 return(0);
906 #ifdef LIBXML_REGEXP_ENABLED
908 * xmlTextReaderValidatePush:
909 * @reader: the xmlTextReaderPtr used
911 * Push the current node for validation
913 static void
914 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
915 xmlNodePtr node = reader->node;
917 #ifdef LIBXML_VALID_ENABLED
918 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
919 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
920 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
921 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
922 reader->ctxt->myDoc, node, node->name);
923 } else {
924 /* TODO use the BuildQName interface */
925 xmlChar *qname;
927 qname = xmlStrdup(node->ns->prefix);
928 qname = xmlStrcat(qname, BAD_CAST ":");
929 qname = xmlStrcat(qname, node->name);
930 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
931 reader->ctxt->myDoc, node, qname);
932 if (qname != NULL)
933 xmlFree(qname);
936 #endif /* LIBXML_VALID_ENABLED */
937 #ifdef LIBXML_SCHEMAS_ENABLED
938 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
939 (reader->rngValidCtxt != NULL)) {
940 int ret;
942 if (reader->rngFullNode != NULL) return;
943 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
944 reader->ctxt->myDoc,
945 node);
946 if (ret == 0) {
948 * this element requires a full tree
950 node = xmlTextReaderExpand(reader);
951 if (node == NULL) {
952 printf("Expand failed !\n");
953 ret = -1;
954 } else {
955 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
956 reader->ctxt->myDoc,
957 node);
958 reader->rngFullNode = node;
961 if (ret != 1)
962 reader->rngValidErrors++;
964 #endif
968 * xmlTextReaderValidateCData:
969 * @reader: the xmlTextReaderPtr used
970 * @data: pointer to the CData
971 * @len: lenght of the CData block in bytes.
973 * Push some CData for validation
975 static void
976 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
977 const xmlChar *data, int len) {
978 #ifdef LIBXML_VALID_ENABLED
979 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
980 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
981 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
982 data, len);
984 #endif /* LIBXML_VALID_ENABLED */
985 #ifdef LIBXML_SCHEMAS_ENABLED
986 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
987 (reader->rngValidCtxt != NULL)) {
988 int ret;
990 if (reader->rngFullNode != NULL) return;
991 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
992 if (ret != 1)
993 reader->rngValidErrors++;
995 #endif
999 * xmlTextReaderValidatePop:
1000 * @reader: the xmlTextReaderPtr used
1002 * Pop the current node from validation
1004 static void
1005 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1006 xmlNodePtr node = reader->node;
1008 #ifdef LIBXML_VALID_ENABLED
1009 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1010 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1011 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1012 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1013 reader->ctxt->myDoc, node, node->name);
1014 } else {
1015 /* TODO use the BuildQName interface */
1016 xmlChar *qname;
1018 qname = xmlStrdup(node->ns->prefix);
1019 qname = xmlStrcat(qname, BAD_CAST ":");
1020 qname = xmlStrcat(qname, node->name);
1021 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1022 reader->ctxt->myDoc, node, qname);
1023 if (qname != NULL)
1024 xmlFree(qname);
1027 #endif /* LIBXML_VALID_ENABLED */
1028 #ifdef LIBXML_SCHEMAS_ENABLED
1029 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1030 (reader->rngValidCtxt != NULL)) {
1031 int ret;
1033 if (reader->rngFullNode != NULL) {
1034 if (node == reader->rngFullNode)
1035 reader->rngFullNode = NULL;
1036 return;
1038 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1039 reader->ctxt->myDoc,
1040 node);
1041 if (ret != 1)
1042 reader->rngValidErrors++;
1044 #endif
1048 * xmlTextReaderValidateEntity:
1049 * @reader: the xmlTextReaderPtr used
1051 * Handle the validation when an entity reference is encountered and
1052 * entity substitution is not activated. As a result the parser interface
1053 * must walk through the entity and do the validation calls
1055 static void
1056 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1057 xmlNodePtr oldnode = reader->node;
1058 xmlNodePtr node = reader->node;
1059 xmlParserCtxtPtr ctxt = reader->ctxt;
1061 do {
1062 if (node->type == XML_ENTITY_REF_NODE) {
1064 * Case where the underlying tree is not availble, lookup the entity
1065 * and walk it.
1067 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1068 (ctxt->sax->getEntity != NULL)) {
1069 node->children = (xmlNodePtr)
1070 ctxt->sax->getEntity(ctxt, node->name);
1073 if ((node->children != NULL) &&
1074 (node->children->type == XML_ENTITY_DECL) &&
1075 (node->children->children != NULL)) {
1076 xmlTextReaderEntPush(reader, node);
1077 node = node->children->children;
1078 continue;
1079 } else {
1081 * The error has probably be raised already.
1083 if (node == oldnode)
1084 break;
1085 node = node->next;
1087 #ifdef LIBXML_REGEXP_ENABLED
1088 } else if (node->type == XML_ELEMENT_NODE) {
1089 reader->node = node;
1090 xmlTextReaderValidatePush(reader);
1091 } else if ((node->type == XML_TEXT_NODE) ||
1092 (node->type == XML_CDATA_SECTION_NODE)) {
1093 xmlTextReaderValidateCData(reader, node->content,
1094 xmlStrlen(node->content));
1095 #endif
1099 * go to next node
1101 if (node->children != NULL) {
1102 node = node->children;
1103 continue;
1104 } else if (node->type == XML_ELEMENT_NODE) {
1105 xmlTextReaderValidatePop(reader);
1107 if (node->next != NULL) {
1108 node = node->next;
1109 continue;
1111 do {
1112 node = node->parent;
1113 if (node->type == XML_ELEMENT_NODE) {
1114 xmlNodePtr tmp;
1115 if (reader->entNr == 0) {
1116 while ((tmp = node->last) != NULL) {
1117 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1118 xmlUnlinkNode(tmp);
1119 xmlTextReaderFreeNode(reader, tmp);
1120 } else
1121 break;
1124 reader->node = node;
1125 xmlTextReaderValidatePop(reader);
1127 if ((node->type == XML_ENTITY_DECL) &&
1128 (reader->ent != NULL) && (reader->ent->children == node)) {
1129 node = xmlTextReaderEntPop(reader);
1131 if (node == oldnode)
1132 break;
1133 if (node->next != NULL) {
1134 node = node->next;
1135 break;
1137 } while ((node != NULL) && (node != oldnode));
1138 } while ((node != NULL) && (node != oldnode));
1139 reader->node = oldnode;
1141 #endif /* LIBXML_REGEXP_ENABLED */
1145 * xmlTextReaderGetSuccessor:
1146 * @cur: the current node
1148 * Get the successor of a node if available.
1150 * Returns the successor node or NULL
1152 static xmlNodePtr
1153 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1154 if (cur == NULL) return(NULL) ; /* ERROR */
1155 if (cur->next != NULL) return(cur->next) ;
1156 do {
1157 cur = cur->parent;
1158 if (cur == NULL) break;
1159 if (cur->next != NULL) return(cur->next);
1160 } while (cur != NULL);
1161 return(cur);
1165 * xmlTextReaderDoExpand:
1166 * @reader: the xmlTextReaderPtr used
1168 * Makes sure that the current node is fully read as well as all its
1169 * descendant. It means the full DOM subtree must be available at the
1170 * end of the call.
1172 * Returns 1 if the node was expanded successfully, 0 if there is no more
1173 * nodes to read, or -1 in case of error
1175 static int
1176 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1177 int val;
1179 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1180 return(-1);
1181 do {
1182 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1184 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1185 return(1);
1186 if (reader->ctxt->nodeNr < reader->depth)
1187 return(1);
1188 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1189 return(1);
1190 val = xmlTextReaderPushData(reader);
1191 if (val < 0){
1192 reader->mode = XML_TEXTREADER_MODE_ERROR;
1193 return(-1);
1195 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1196 return(1);
1200 * xmlTextReaderCollectSiblings:
1201 * @node: the first child
1203 * Traverse depth-first through all sibling nodes and their children
1204 * nodes and concatenate their content. This is an auxiliary function
1205 * to xmlTextReaderReadString.
1207 * Returns a string containing the content, or NULL in case of error.
1209 static xmlChar *
1210 xmlTextReaderCollectSiblings(xmlNodePtr node)
1212 xmlBufferPtr buffer;
1213 xmlChar *ret;
1215 buffer = xmlBufferCreate();
1216 if (buffer == NULL)
1217 return NULL;
1219 for ( ; node != NULL; node = node->next) {
1220 switch (node->type) {
1221 case XML_TEXT_NODE:
1222 case XML_CDATA_SECTION_NODE:
1223 xmlBufferCat(buffer, node->content);
1224 break;
1225 case XML_ELEMENT_NODE: {
1226 xmlChar *tmp;
1228 tmp = xmlTextReaderCollectSiblings(node->children);
1229 xmlBufferCat(buffer, tmp);
1230 xmlFree(tmp);
1231 break;
1233 default:
1234 break;
1237 ret = buffer->content;
1238 buffer->content = NULL;
1239 xmlBufferFree(buffer);
1240 return(ret);
1244 * xmlTextReaderRead:
1245 * @reader: the xmlTextReaderPtr used
1247 * Moves the position of the current instance to the next node in
1248 * the stream, exposing its properties.
1250 * Returns 1 if the node was read successfully, 0 if there is no more
1251 * nodes to read, or -1 in case of error
1254 xmlTextReaderRead(xmlTextReaderPtr reader) {
1255 int val, olddepth = 0;
1256 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1257 xmlNodePtr oldnode = NULL;
1260 if (reader == NULL)
1261 return(-1);
1262 reader->curnode = NULL;
1263 if (reader->doc != NULL)
1264 return(xmlTextReaderReadTree(reader));
1265 if (reader->ctxt == NULL)
1266 return(-1);
1267 if (reader->ctxt->wellFormed != 1)
1268 return(-1);
1270 #ifdef DEBUG_READER
1271 fprintf(stderr, "\nREAD ");
1272 DUMP_READER
1273 #endif
1274 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1275 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1277 * Initial state
1279 do {
1280 val = xmlTextReaderPushData(reader);
1281 if (val < 0){
1282 reader->mode = XML_TEXTREADER_MODE_ERROR;
1283 reader->state = XML_TEXTREADER_ERROR;
1284 return(-1);
1286 } while ((reader->ctxt->node == NULL) &&
1287 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1288 (reader->state != XML_TEXTREADER_DONE)));
1289 if (reader->ctxt->node == NULL) {
1290 if (reader->ctxt->myDoc != NULL) {
1291 reader->node = reader->ctxt->myDoc->children;
1293 if (reader->node == NULL){
1294 reader->mode = XML_TEXTREADER_MODE_ERROR;
1295 reader->state = XML_TEXTREADER_ERROR;
1296 return(-1);
1298 reader->state = XML_TEXTREADER_ELEMENT;
1299 } else {
1300 if (reader->ctxt->myDoc != NULL) {
1301 reader->node = reader->ctxt->myDoc->children;
1303 if (reader->node == NULL)
1304 reader->node = reader->ctxt->nodeTab[0];
1305 reader->state = XML_TEXTREADER_ELEMENT;
1307 reader->depth = 0;
1308 reader->ctxt->parseMode = XML_PARSE_READER;
1309 goto node_found;
1311 oldstate = reader->state;
1312 olddepth = reader->ctxt->nodeNr;
1313 oldnode = reader->node;
1315 get_next_node:
1316 if (reader->node == NULL) {
1317 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1318 return(0);
1319 else
1320 return(-1);
1324 * If we are not backtracking on ancestors or examined nodes,
1325 * that the parser didn't finished or that we arent at the end
1326 * of stream, continue processing.
1328 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1329 (reader->ctxt->nodeNr == olddepth) &&
1330 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1331 (reader->node->children == NULL) ||
1332 (reader->node->type == XML_ENTITY_REF_NODE) ||
1333 ((reader->node->children != NULL) &&
1334 (reader->node->children->type == XML_TEXT_NODE) &&
1335 (reader->node->children->next == NULL)) ||
1336 (reader->node->type == XML_DTD_NODE) ||
1337 (reader->node->type == XML_DOCUMENT_NODE) ||
1338 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1339 ((reader->ctxt->node == NULL) ||
1340 (reader->ctxt->node == reader->node) ||
1341 (reader->ctxt->node == reader->node->parent)) &&
1342 (reader->ctxt->instate != XML_PARSER_EOF)) {
1343 val = xmlTextReaderPushData(reader);
1344 if (val < 0){
1345 reader->mode = XML_TEXTREADER_MODE_ERROR;
1346 reader->state = XML_TEXTREADER_ERROR;
1347 return(-1);
1349 if (reader->node == NULL)
1350 goto node_end;
1352 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1353 if ((reader->node->children != NULL) &&
1354 (reader->node->type != XML_ENTITY_REF_NODE) &&
1355 (reader->node->type != XML_XINCLUDE_START) &&
1356 (reader->node->type != XML_DTD_NODE)) {
1357 reader->node = reader->node->children;
1358 reader->depth++;
1359 reader->state = XML_TEXTREADER_ELEMENT;
1360 goto node_found;
1363 if (reader->node->next != NULL) {
1364 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1365 (reader->node->type == XML_ELEMENT_NODE) &&
1366 (reader->node->children == NULL) &&
1367 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1368 #ifdef LIBXML_XINCLUDE_ENABLED
1369 && (reader->in_xinclude <= 0)
1370 #endif
1372 reader->state = XML_TEXTREADER_END;
1373 goto node_found;
1375 #ifdef LIBXML_REGEXP_ENABLED
1376 if ((reader->validate) &&
1377 (reader->node->type == XML_ELEMENT_NODE))
1378 xmlTextReaderValidatePop(reader);
1379 #endif /* LIBXML_REGEXP_ENABLED */
1380 if ((reader->preserves > 0) &&
1381 (reader->node->extra & NODE_IS_SPRESERVED))
1382 reader->preserves--;
1383 reader->node = reader->node->next;
1384 reader->state = XML_TEXTREADER_ELEMENT;
1387 * Cleanup of the old node
1389 if ((reader->preserves == 0) &&
1390 #ifdef LIBXML_XINCLUDE_ENABLED
1391 (reader->in_xinclude == 0) &&
1392 #endif
1393 (reader->entNr == 0) &&
1394 (reader->node->prev != NULL) &&
1395 (reader->node->prev->type != XML_DTD_NODE)) {
1396 xmlNodePtr tmp = reader->node->prev;
1397 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1398 xmlUnlinkNode(tmp);
1399 xmlTextReaderFreeNode(reader, tmp);
1403 goto node_found;
1405 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1406 (reader->node->type == XML_ELEMENT_NODE) &&
1407 (reader->node->children == NULL) &&
1408 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1409 reader->state = XML_TEXTREADER_END;
1410 goto node_found;
1412 #ifdef LIBXML_REGEXP_ENABLED
1413 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
1414 xmlTextReaderValidatePop(reader);
1415 #endif /* LIBXML_REGEXP_ENABLED */
1416 if ((reader->preserves > 0) &&
1417 (reader->node->extra & NODE_IS_SPRESERVED))
1418 reader->preserves--;
1419 reader->node = reader->node->parent;
1420 if ((reader->node == NULL) ||
1421 (reader->node->type == XML_DOCUMENT_NODE) ||
1422 #ifdef LIBXML_DOCB_ENABLED
1423 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1424 #endif
1425 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1426 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1427 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1428 reader->state = XML_TEXTREADER_DONE;
1429 if (val != 0)
1430 return(-1);
1432 reader->node = NULL;
1433 reader->depth = -1;
1436 * Cleanup of the old node
1438 if ((oldnode != NULL) && (reader->preserves == 0) &&
1439 #ifdef LIBXML_XINCLUDE_ENABLED
1440 (reader->in_xinclude == 0) &&
1441 #endif
1442 (reader->entNr == 0) &&
1443 (oldnode->type != XML_DTD_NODE) &&
1444 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1445 xmlUnlinkNode(oldnode);
1446 xmlTextReaderFreeNode(reader, oldnode);
1449 goto node_end;
1451 if ((reader->preserves == 0) &&
1452 #ifdef LIBXML_XINCLUDE_ENABLED
1453 (reader->in_xinclude == 0) &&
1454 #endif
1455 (reader->entNr == 0) &&
1456 (reader->node->last != NULL) &&
1457 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1458 xmlNodePtr tmp = reader->node->last;
1459 xmlUnlinkNode(tmp);
1460 xmlTextReaderFreeNode(reader, tmp);
1462 reader->depth--;
1463 reader->state = XML_TEXTREADER_BACKTRACK;
1465 node_found:
1466 DUMP_READER
1469 * If we are in the middle of a piece of CDATA make sure it's finished
1471 if ((reader->node != NULL) &&
1472 (reader->node->next == NULL) &&
1473 ((reader->node->type == XML_TEXT_NODE) ||
1474 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1475 if (xmlTextReaderExpand(reader) == NULL)
1476 return -1;
1479 #ifdef LIBXML_XINCLUDE_ENABLED
1481 * Handle XInclude if asked for
1483 if ((reader->xinclude) && (reader->node != NULL) &&
1484 (reader->node->type == XML_ELEMENT_NODE) &&
1485 (reader->node->ns != NULL) &&
1486 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1487 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1488 if (reader->xincctxt == NULL) {
1489 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1490 xmlXIncludeSetFlags(reader->xincctxt,
1491 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1494 * expand that node and process it
1496 if (xmlTextReaderExpand(reader) == NULL)
1497 return -1;
1498 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1500 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1501 reader->in_xinclude++;
1502 goto get_next_node;
1504 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1505 reader->in_xinclude--;
1506 goto get_next_node;
1508 #endif
1510 * Handle entities enter and exit when in entity replacement mode
1512 if ((reader->node != NULL) &&
1513 (reader->node->type == XML_ENTITY_REF_NODE) &&
1514 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1516 * Case where the underlying tree is not availble, lookup the entity
1517 * and walk it.
1519 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1520 (reader->ctxt->sax->getEntity != NULL)) {
1521 reader->node->children = (xmlNodePtr)
1522 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1525 if ((reader->node->children != NULL) &&
1526 (reader->node->children->type == XML_ENTITY_DECL) &&
1527 (reader->node->children->children != NULL)) {
1528 xmlTextReaderEntPush(reader, reader->node);
1529 reader->node = reader->node->children->children;
1531 #ifdef LIBXML_REGEXP_ENABLED
1532 } else if ((reader->node != NULL) &&
1533 (reader->node->type == XML_ENTITY_REF_NODE) &&
1534 (reader->ctxt != NULL) && (reader->validate)) {
1535 xmlTextReaderValidateEntity(reader);
1536 #endif /* LIBXML_REGEXP_ENABLED */
1538 if ((reader->node != NULL) &&
1539 (reader->node->type == XML_ENTITY_DECL) &&
1540 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1541 reader->node = xmlTextReaderEntPop(reader);
1542 reader->depth++;
1543 goto get_next_node;
1545 #ifdef LIBXML_REGEXP_ENABLED
1546 if ((reader->validate) && (reader->node != NULL)) {
1547 xmlNodePtr node = reader->node;
1549 if ((node->type == XML_ELEMENT_NODE) &&
1550 ((reader->state != XML_TEXTREADER_END) &&
1551 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1552 xmlTextReaderValidatePush(reader);
1553 } else if ((node->type == XML_TEXT_NODE) ||
1554 (node->type == XML_CDATA_SECTION_NODE)) {
1555 xmlTextReaderValidateCData(reader, node->content,
1556 xmlStrlen(node->content));
1559 #endif /* LIBXML_REGEXP_ENABLED */
1560 #ifdef LIBXML_PATTERN_ENABLED
1561 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1562 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1563 int i;
1564 for (i = 0;i < reader->patternNr;i++) {
1565 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1566 xmlTextReaderPreserve(reader);
1567 break;
1571 #endif /* LIBXML_PATTERN_ENABLED */
1572 #ifdef LIBXML_SCHEMAS_ENABLED
1573 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1574 (reader->xsdValidErrors == 0) &&
1575 (reader->xsdValidCtxt != NULL)) {
1576 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1578 #endif /* LIBXML_PATTERN_ENABLED */
1579 return(1);
1580 node_end:
1581 reader->state = XML_TEXTREADER_DONE;
1582 return(0);
1586 * xmlTextReaderReadState:
1587 * @reader: the xmlTextReaderPtr used
1589 * Gets the read state of the reader.
1591 * Returns the state value, or -1 in case of error
1594 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1595 if (reader == NULL)
1596 return(-1);
1597 return(reader->mode);
1601 * xmlTextReaderExpand:
1602 * @reader: the xmlTextReaderPtr used
1604 * Reads the contents of the current node and the full subtree. It then makes
1605 * the subtree available until the next xmlTextReaderRead() call
1607 * Returns a node pointer valid until the next xmlTextReaderRead() call
1608 * or NULL in case of error.
1610 xmlNodePtr
1611 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1612 if ((reader == NULL) || (reader->node == NULL))
1613 return(NULL);
1614 if (reader->doc != NULL)
1615 return(reader->node);
1616 if (reader->ctxt == NULL)
1617 return(NULL);
1618 if (xmlTextReaderDoExpand(reader) < 0)
1619 return(NULL);
1620 return(reader->node);
1624 * xmlTextReaderNext:
1625 * @reader: the xmlTextReaderPtr used
1627 * Skip to the node following the current one in document order while
1628 * avoiding the subtree if any.
1630 * Returns 1 if the node was read successfully, 0 if there is no more
1631 * nodes to read, or -1 in case of error
1634 xmlTextReaderNext(xmlTextReaderPtr reader) {
1635 int ret;
1636 xmlNodePtr cur;
1638 if (reader == NULL)
1639 return(-1);
1640 if (reader->doc != NULL)
1641 return(xmlTextReaderNextTree(reader));
1642 cur = reader->node;
1643 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1644 return(xmlTextReaderRead(reader));
1645 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1646 return(xmlTextReaderRead(reader));
1647 if (cur->extra & NODE_IS_EMPTY)
1648 return(xmlTextReaderRead(reader));
1649 do {
1650 ret = xmlTextReaderRead(reader);
1651 if (ret != 1)
1652 return(ret);
1653 } while (reader->node != cur);
1654 return(xmlTextReaderRead(reader));
1657 #ifdef LIBXML_WRITER_ENABLED
1659 * xmlTextReaderReadInnerXml:
1660 * @reader: the xmlTextReaderPtr used
1662 * Reads the contents of the current node, including child nodes and markup.
1664 * Returns a string containing the XML content, or NULL if the current node
1665 * is neither an element nor attribute, or has no child nodes. The
1666 * string must be deallocated by the caller.
1668 xmlChar *
1669 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1671 xmlChar *resbuf;
1672 xmlNodePtr node, cur_node;
1673 xmlBufferPtr buff, buff2;
1674 xmlDocPtr doc;
1676 if (xmlTextReaderExpand(reader) == NULL) {
1677 return NULL;
1679 doc = reader->doc;
1680 buff = xmlBufferCreate();
1681 for (cur_node = reader->node->children; cur_node != NULL;
1682 cur_node = cur_node->next) {
1683 node = xmlDocCopyNode(cur_node, doc, 1);
1684 buff2 = xmlBufferCreate();
1685 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1686 xmlFreeNode(node);
1687 xmlBufferFree(buff2);
1688 xmlBufferFree(buff);
1689 return NULL;
1691 xmlBufferCat(buff, buff2->content);
1692 xmlFreeNode(node);
1693 xmlBufferFree(buff2);
1695 resbuf = buff->content;
1696 buff->content = NULL;
1698 xmlBufferFree(buff);
1699 return resbuf;
1701 #endif
1703 #ifdef LIBXML_WRITER_ENABLED
1705 * xmlTextReaderReadOuterXml:
1706 * @reader: the xmlTextReaderPtr used
1708 * Reads the contents of the current node, including child nodes and markup.
1710 * Returns a string containing the XML content, or NULL if the current node
1711 * is neither an element nor attribute, or has no child nodes. The
1712 * string must be deallocated by the caller.
1714 xmlChar *
1715 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1717 xmlChar *resbuf;
1718 xmlNodePtr node;
1719 xmlBufferPtr buff;
1720 xmlDocPtr doc;
1722 node = reader->node;
1723 doc = reader->doc;
1724 if (xmlTextReaderExpand(reader) == NULL) {
1725 return NULL;
1727 node = xmlDocCopyNode(node, doc, 1);
1728 buff = xmlBufferCreate();
1729 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1730 xmlFreeNode(node);
1731 xmlBufferFree(buff);
1732 return NULL;
1735 resbuf = buff->content;
1736 buff->content = NULL;
1738 xmlFreeNode(node);
1739 xmlBufferFree(buff);
1740 return resbuf;
1742 #endif
1745 * xmlTextReaderReadString:
1746 * @reader: the xmlTextReaderPtr used
1748 * Reads the contents of an element or a text node as a string.
1750 * Returns a string containing the contents of the Element or Text node,
1751 * or NULL if the reader is positioned on any other type of node.
1752 * The string must be deallocated by the caller.
1754 xmlChar *
1755 xmlTextReaderReadString(xmlTextReaderPtr reader)
1757 xmlNodePtr node;
1759 if ((reader == NULL) || (reader->node == NULL))
1760 return(NULL);
1762 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1763 switch (node->type) {
1764 case XML_TEXT_NODE:
1765 if (node->content != NULL)
1766 return(xmlStrdup(node->content));
1767 break;
1768 case XML_ELEMENT_NODE:
1769 if (xmlTextReaderDoExpand(reader) != -1) {
1770 return xmlTextReaderCollectSiblings(node->children);
1772 case XML_ATTRIBUTE_NODE:
1773 TODO
1774 break;
1775 default:
1776 break;
1778 return(NULL);
1781 #if 0
1783 * xmlTextReaderReadBase64:
1784 * @reader: the xmlTextReaderPtr used
1785 * @array: a byte array to store the content.
1786 * @offset: the zero-based index into array where the method should
1787 * begin to write.
1788 * @len: the number of bytes to write.
1790 * Reads and decodes the Base64 encoded contents of an element and
1791 * stores the result in a byte buffer.
1793 * Returns the number of bytes written to array, or zero if the current
1794 * instance is not positioned on an element or -1 in case of error.
1797 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1798 unsigned char *array ATTRIBUTE_UNUSED,
1799 int offset ATTRIBUTE_UNUSED,
1800 int len ATTRIBUTE_UNUSED) {
1801 if ((reader == NULL) || (reader->ctxt == NULL))
1802 return(-1);
1803 if (reader->ctxt->wellFormed != 1)
1804 return(-1);
1806 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1807 return(0);
1808 TODO
1809 return(0);
1813 * xmlTextReaderReadBinHex:
1814 * @reader: the xmlTextReaderPtr used
1815 * @array: a byte array to store the content.
1816 * @offset: the zero-based index into array where the method should
1817 * begin to write.
1818 * @len: the number of bytes to write.
1820 * Reads and decodes the BinHex encoded contents of an element and
1821 * stores the result in a byte buffer.
1823 * Returns the number of bytes written to array, or zero if the current
1824 * instance is not positioned on an element or -1 in case of error.
1827 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1828 unsigned char *array ATTRIBUTE_UNUSED,
1829 int offset ATTRIBUTE_UNUSED,
1830 int len ATTRIBUTE_UNUSED) {
1831 if ((reader == NULL) || (reader->ctxt == NULL))
1832 return(-1);
1833 if (reader->ctxt->wellFormed != 1)
1834 return(-1);
1836 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1837 return(0);
1838 TODO
1839 return(0);
1841 #endif
1843 /************************************************************************
1845 * Operating on a preparsed tree *
1847 ************************************************************************/
1848 static int
1849 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1851 if (reader == NULL)
1852 return(-1);
1854 if (reader->state == XML_TEXTREADER_END)
1855 return(0);
1857 if (reader->node == NULL) {
1858 if (reader->doc->children == NULL) {
1859 reader->state = XML_TEXTREADER_END;
1860 return(0);
1863 reader->node = reader->doc->children;
1864 reader->state = XML_TEXTREADER_START;
1865 return(1);
1868 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1869 /* Here removed traversal to child, because we want to skip the subtree,
1870 replace with traversal to sibling to skip subtree */
1871 if (reader->node->next != 0) {
1872 /* Move to sibling if present,skipping sub-tree */
1873 reader->node = reader->node->next;
1874 reader->state = XML_TEXTREADER_START;
1875 return(1);
1878 /* if reader->node->next is NULL mean no subtree for current node,
1879 so need to move to sibling of parent node if present */
1880 if ((reader->node->type == XML_ELEMENT_NODE) ||
1881 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1882 reader->state = XML_TEXTREADER_BACKTRACK;
1883 /* This will move to parent if present */
1884 xmlTextReaderRead(reader);
1888 if (reader->node->next != 0) {
1889 reader->node = reader->node->next;
1890 reader->state = XML_TEXTREADER_START;
1891 return(1);
1894 if (reader->node->parent != 0) {
1895 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1896 reader->state = XML_TEXTREADER_END;
1897 return(0);
1900 reader->node = reader->node->parent;
1901 reader->depth--;
1902 reader->state = XML_TEXTREADER_BACKTRACK;
1903 /* Repeat process to move to sibling of parent node if present */
1904 xmlTextReaderNextTree(reader);
1907 reader->state = XML_TEXTREADER_END;
1909 return(1);
1913 * xmlTextReaderReadTree:
1914 * @reader: the xmlTextReaderPtr used
1916 * Moves the position of the current instance to the next node in
1917 * the stream, exposing its properties.
1919 * Returns 1 if the node was read successfully, 0 if there is no more
1920 * nodes to read, or -1 in case of error
1922 static int
1923 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1924 if (reader->state == XML_TEXTREADER_END)
1925 return(0);
1927 next_node:
1928 if (reader->node == NULL) {
1929 if (reader->doc->children == NULL) {
1930 reader->state = XML_TEXTREADER_END;
1931 return(0);
1934 reader->node = reader->doc->children;
1935 reader->state = XML_TEXTREADER_START;
1936 goto found_node;
1939 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1940 (reader->node->type != XML_DTD_NODE) &&
1941 (reader->node->type != XML_XINCLUDE_START) &&
1942 (reader->node->type != XML_ENTITY_REF_NODE)) {
1943 if (reader->node->children != NULL) {
1944 reader->node = reader->node->children;
1945 reader->depth++;
1946 reader->state = XML_TEXTREADER_START;
1947 goto found_node;
1950 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1951 reader->state = XML_TEXTREADER_BACKTRACK;
1952 goto found_node;
1956 if (reader->node->next != NULL) {
1957 reader->node = reader->node->next;
1958 reader->state = XML_TEXTREADER_START;
1959 goto found_node;
1962 if (reader->node->parent != NULL) {
1963 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1964 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1965 reader->state = XML_TEXTREADER_END;
1966 return(0);
1969 reader->node = reader->node->parent;
1970 reader->depth--;
1971 reader->state = XML_TEXTREADER_BACKTRACK;
1972 goto found_node;
1975 reader->state = XML_TEXTREADER_END;
1977 found_node:
1978 if ((reader->node->type == XML_XINCLUDE_START) ||
1979 (reader->node->type == XML_XINCLUDE_END))
1980 goto next_node;
1982 return(1);
1986 * xmlTextReaderNextSibling:
1987 * @reader: the xmlTextReaderPtr used
1989 * Skip to the node following the current one in document order while
1990 * avoiding the subtree if any.
1991 * Currently implemented only for Readers built on a document
1993 * Returns 1 if the node was read successfully, 0 if there is no more
1994 * nodes to read, or -1 in case of error
1997 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1998 if (reader == NULL)
1999 return(-1);
2000 if (reader->doc == NULL) {
2001 /* TODO */
2002 return(-1);
2005 if (reader->state == XML_TEXTREADER_END)
2006 return(0);
2008 if (reader->node == NULL)
2009 return(xmlTextReaderNextTree(reader));
2011 if (reader->node->next != NULL) {
2012 reader->node = reader->node->next;
2013 reader->state = XML_TEXTREADER_START;
2014 return(1);
2017 return(0);
2020 /************************************************************************
2022 * Constructor and destructors *
2024 ************************************************************************/
2026 * xmlNewTextReader:
2027 * @input: the xmlParserInputBufferPtr used to read data
2028 * @URI: the URI information for the source if available
2030 * Create an xmlTextReader structure fed with @input
2032 * Returns the new xmlTextReaderPtr or NULL in case of error
2034 xmlTextReaderPtr
2035 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2036 xmlTextReaderPtr ret;
2038 if (input == NULL)
2039 return(NULL);
2040 ret = xmlMalloc(sizeof(xmlTextReader));
2041 if (ret == NULL) {
2042 xmlGenericError(xmlGenericErrorContext,
2043 "xmlNewTextReader : malloc failed\n");
2044 return(NULL);
2046 memset(ret, 0, sizeof(xmlTextReader));
2047 ret->doc = NULL;
2048 ret->entTab = NULL;
2049 ret->entMax = 0;
2050 ret->entNr = 0;
2051 ret->input = input;
2052 ret->buffer = xmlBufferCreateSize(100);
2053 if (ret->buffer == NULL) {
2054 xmlFree(ret);
2055 xmlGenericError(xmlGenericErrorContext,
2056 "xmlNewTextReader : malloc failed\n");
2057 return(NULL);
2059 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2060 if (ret->sax == NULL) {
2061 xmlBufferFree(ret->buffer);
2062 xmlFree(ret);
2063 xmlGenericError(xmlGenericErrorContext,
2064 "xmlNewTextReader : malloc failed\n");
2065 return(NULL);
2067 xmlSAXVersion(ret->sax, 2);
2068 ret->startElement = ret->sax->startElement;
2069 ret->sax->startElement = xmlTextReaderStartElement;
2070 ret->endElement = ret->sax->endElement;
2071 ret->sax->endElement = xmlTextReaderEndElement;
2072 #ifdef LIBXML_SAX1_ENABLED
2073 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2074 #endif /* LIBXML_SAX1_ENABLED */
2075 ret->startElementNs = ret->sax->startElementNs;
2076 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2077 ret->endElementNs = ret->sax->endElementNs;
2078 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2079 #ifdef LIBXML_SAX1_ENABLED
2080 } else {
2081 ret->startElementNs = NULL;
2082 ret->endElementNs = NULL;
2084 #endif /* LIBXML_SAX1_ENABLED */
2085 ret->characters = ret->sax->characters;
2086 ret->sax->characters = xmlTextReaderCharacters;
2087 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2088 ret->cdataBlock = ret->sax->cdataBlock;
2089 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2091 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2092 ret->node = NULL;
2093 ret->curnode = NULL;
2094 if (ret->input->buffer->use < 4) {
2095 xmlParserInputBufferRead(input, 4);
2097 if (ret->input->buffer->use >= 4) {
2098 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2099 (const char *) ret->input->buffer->content, 4, URI);
2100 ret->base = 0;
2101 ret->cur = 4;
2102 } else {
2103 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2104 ret->base = 0;
2105 ret->cur = 0;
2108 if (ret->ctxt == NULL) {
2109 xmlGenericError(xmlGenericErrorContext,
2110 "xmlNewTextReader : malloc failed\n");
2111 xmlBufferFree(ret->buffer);
2112 xmlFree(ret->sax);
2113 xmlFree(ret);
2114 return(NULL);
2116 ret->ctxt->parseMode = XML_PARSE_READER;
2117 ret->ctxt->_private = ret;
2118 ret->ctxt->linenumbers = 1;
2119 ret->ctxt->dictNames = 1;
2120 ret->allocs = XML_TEXTREADER_CTXT;
2122 * use the parser dictionnary to allocate all elements and attributes names
2124 ret->ctxt->docdict = 1;
2125 ret->dict = ret->ctxt->dict;
2126 #ifdef LIBXML_XINCLUDE_ENABLED
2127 ret->xinclude = 0;
2128 #endif
2129 #ifdef LIBXML_PATTERN_ENABLED
2130 ret->patternMax = 0;
2131 ret->patternTab = NULL;
2132 #endif
2133 return(ret);
2137 * xmlNewTextReaderFilename:
2138 * @URI: the URI of the resource to process
2140 * Create an xmlTextReader structure fed with the resource at @URI
2142 * Returns the new xmlTextReaderPtr or NULL in case of error
2144 xmlTextReaderPtr
2145 xmlNewTextReaderFilename(const char *URI) {
2146 xmlParserInputBufferPtr input;
2147 xmlTextReaderPtr ret;
2148 char *directory = NULL;
2150 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2151 if (input == NULL)
2152 return(NULL);
2153 ret = xmlNewTextReader(input, URI);
2154 if (ret == NULL) {
2155 xmlFreeParserInputBuffer(input);
2156 return(NULL);
2158 ret->allocs |= XML_TEXTREADER_INPUT;
2159 if (ret->ctxt->directory == NULL)
2160 directory = xmlParserGetDirectory(URI);
2161 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2162 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2163 if (directory != NULL)
2164 xmlFree(directory);
2165 return(ret);
2169 * xmlFreeTextReader:
2170 * @reader: the xmlTextReaderPtr
2172 * Deallocate all the resources associated to the reader
2174 void
2175 xmlFreeTextReader(xmlTextReaderPtr reader) {
2176 if (reader == NULL)
2177 return;
2178 #ifdef LIBXML_SCHEMAS_ENABLED
2179 if (reader->rngSchemas != NULL) {
2180 xmlRelaxNGFree(reader->rngSchemas);
2181 reader->rngSchemas = NULL;
2183 if (reader->rngValidCtxt != NULL) {
2184 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2185 reader->rngValidCtxt = NULL;
2187 if (reader->xsdPlug != NULL) {
2188 xmlSchemaSAXUnplug(reader->xsdPlug);
2189 reader->xsdPlug = NULL;
2191 if (reader->xsdValidCtxt != NULL) {
2192 if (! reader->xsdPreserveCtxt)
2193 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2194 reader->xsdValidCtxt = NULL;
2196 if (reader->xsdSchemas != NULL) {
2197 xmlSchemaFree(reader->xsdSchemas);
2198 reader->xsdSchemas = NULL;
2200 #endif
2201 #ifdef LIBXML_XINCLUDE_ENABLED
2202 if (reader->xincctxt != NULL)
2203 xmlXIncludeFreeContext(reader->xincctxt);
2204 #endif
2205 #ifdef LIBXML_PATTERN_ENABLED
2206 if (reader->patternTab != NULL) {
2207 int i;
2208 for (i = 0;i < reader->patternNr;i++) {
2209 if (reader->patternTab[i] != NULL)
2210 xmlFreePattern(reader->patternTab[i]);
2212 xmlFree(reader->patternTab);
2214 #endif
2215 if (reader->faketext != NULL) {
2216 xmlFreeNode(reader->faketext);
2218 if (reader->ctxt != NULL) {
2219 if (reader->dict == reader->ctxt->dict)
2220 reader->dict = NULL;
2221 if (reader->ctxt->myDoc != NULL) {
2222 if (reader->preserve == 0)
2223 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2224 reader->ctxt->myDoc = NULL;
2226 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2227 (reader->ctxt->vctxt.vstateMax > 0)){
2228 xmlFree(reader->ctxt->vctxt.vstateTab);
2229 reader->ctxt->vctxt.vstateTab = NULL;
2230 reader->ctxt->vctxt.vstateMax = 0;
2232 if (reader->allocs & XML_TEXTREADER_CTXT)
2233 xmlFreeParserCtxt(reader->ctxt);
2235 if (reader->sax != NULL)
2236 xmlFree(reader->sax);
2237 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2238 xmlFreeParserInputBuffer(reader->input);
2239 if (reader->buffer != NULL)
2240 xmlBufferFree(reader->buffer);
2241 if (reader->entTab != NULL)
2242 xmlFree(reader->entTab);
2243 if (reader->dict != NULL)
2244 xmlDictFree(reader->dict);
2245 xmlFree(reader);
2248 /************************************************************************
2250 * Methods for XmlTextReader *
2252 ************************************************************************/
2254 * xmlTextReaderClose:
2255 * @reader: the xmlTextReaderPtr used
2257 * This method releases any resources allocated by the current instance
2258 * changes the state to Closed and close any underlying input.
2260 * Returns 0 or -1 in case of error
2263 xmlTextReaderClose(xmlTextReaderPtr reader) {
2264 if (reader == NULL)
2265 return(-1);
2266 reader->node = NULL;
2267 reader->curnode = NULL;
2268 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2269 if (reader->ctxt != NULL) {
2270 xmlStopParser(reader->ctxt);
2271 if (reader->ctxt->myDoc != NULL) {
2272 if (reader->preserve == 0)
2273 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2274 reader->ctxt->myDoc = NULL;
2277 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2278 xmlFreeParserInputBuffer(reader->input);
2279 reader->allocs -= XML_TEXTREADER_INPUT;
2281 return(0);
2285 * xmlTextReaderGetAttributeNo:
2286 * @reader: the xmlTextReaderPtr used
2287 * @no: the zero-based index of the attribute relative to the containing element
2289 * Provides the value of the attribute with the specified index relative
2290 * to the containing element.
2292 * Returns a string containing the value of the specified attribute, or NULL
2293 * in case of error. The string must be deallocated by the caller.
2295 xmlChar *
2296 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2297 xmlChar *ret;
2298 int i;
2299 xmlAttrPtr cur;
2300 xmlNsPtr ns;
2302 if (reader == NULL)
2303 return(NULL);
2304 if (reader->node == NULL)
2305 return(NULL);
2306 if (reader->curnode != NULL)
2307 return(NULL);
2308 /* TODO: handle the xmlDecl */
2309 if (reader->node->type != XML_ELEMENT_NODE)
2310 return(NULL);
2312 ns = reader->node->nsDef;
2313 for (i = 0;(i < no) && (ns != NULL);i++) {
2314 ns = ns->next;
2316 if (ns != NULL)
2317 return(xmlStrdup(ns->href));
2319 cur = reader->node->properties;
2320 if (cur == NULL)
2321 return(NULL);
2322 for (;i < no;i++) {
2323 cur = cur->next;
2324 if (cur == NULL)
2325 return(NULL);
2327 /* TODO walk the DTD if present */
2329 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2330 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2331 return(ret);
2335 * xmlTextReaderGetAttribute:
2336 * @reader: the xmlTextReaderPtr used
2337 * @name: the qualified name of the attribute.
2339 * Provides the value of the attribute with the specified qualified name.
2341 * Returns a string containing the value of the specified attribute, or NULL
2342 * in case of error. The string must be deallocated by the caller.
2344 xmlChar *
2345 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2346 xmlChar *prefix = NULL;
2347 xmlChar *localname;
2348 xmlNsPtr ns;
2349 xmlChar *ret = NULL;
2351 if ((reader == NULL) || (name == NULL))
2352 return(NULL);
2353 if (reader->node == NULL)
2354 return(NULL);
2355 if (reader->curnode != NULL)
2356 return(NULL);
2358 /* TODO: handle the xmlDecl */
2359 if (reader->node->type != XML_ELEMENT_NODE)
2360 return(NULL);
2362 localname = xmlSplitQName2(name, &prefix);
2363 if (localname == NULL) {
2365 * Namespace default decl
2367 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2368 ns = reader->node->nsDef;
2369 while (ns != NULL) {
2370 if (ns->prefix == NULL) {
2371 return(xmlStrdup(ns->href));
2373 ns = ns->next;
2375 return NULL;
2377 return(xmlGetNoNsProp(reader->node, name));
2381 * Namespace default decl
2383 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2384 ns = reader->node->nsDef;
2385 while (ns != NULL) {
2386 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2387 ret = xmlStrdup(ns->href);
2388 break;
2390 ns = ns->next;
2392 } else {
2393 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2394 if (ns != NULL)
2395 ret = xmlGetNsProp(reader->node, localname, ns->href);
2398 xmlFree(localname);
2399 if (prefix != NULL)
2400 xmlFree(prefix);
2401 return(ret);
2406 * xmlTextReaderGetAttributeNs:
2407 * @reader: the xmlTextReaderPtr used
2408 * @localName: the local name of the attribute.
2409 * @namespaceURI: the namespace URI of the attribute.
2411 * Provides the value of the specified attribute
2413 * Returns a string containing the value of the specified attribute, or NULL
2414 * in case of error. The string must be deallocated by the caller.
2416 xmlChar *
2417 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2418 const xmlChar *namespaceURI) {
2419 xmlChar *prefix = NULL;
2420 xmlNsPtr ns;
2422 if ((reader == NULL) || (localName == NULL))
2423 return(NULL);
2424 if (reader->node == NULL)
2425 return(NULL);
2426 if (reader->curnode != NULL)
2427 return(NULL);
2429 /* TODO: handle the xmlDecl */
2430 if (reader->node->type != XML_ELEMENT_NODE)
2431 return(NULL);
2433 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2434 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2435 prefix = BAD_CAST localName;
2437 ns = reader->node->nsDef;
2438 while (ns != NULL) {
2439 if ((prefix == NULL && ns->prefix == NULL) ||
2440 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2441 return xmlStrdup(ns->href);
2443 ns = ns->next;
2445 return NULL;
2448 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2452 * xmlTextReaderGetRemainder:
2453 * @reader: the xmlTextReaderPtr used
2455 * Method to get the remainder of the buffered XML. this method stops the
2456 * parser, set its state to End Of File and return the input stream with
2457 * what is left that the parser did not use.
2459 * The implementation is not good, the parser certainly procgressed past
2460 * what's left in reader->input, and there is an allocation problem. Best
2461 * would be to rewrite it differently.
2463 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2464 * in case of error.
2466 xmlParserInputBufferPtr
2467 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2468 xmlParserInputBufferPtr ret = NULL;
2470 if (reader == NULL)
2471 return(NULL);
2472 if (reader->node == NULL)
2473 return(NULL);
2475 reader->node = NULL;
2476 reader->curnode = NULL;
2477 reader->mode = XML_TEXTREADER_MODE_EOF;
2478 if (reader->ctxt != NULL) {
2479 xmlStopParser(reader->ctxt);
2480 if (reader->ctxt->myDoc != NULL) {
2481 if (reader->preserve == 0)
2482 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2483 reader->ctxt->myDoc = NULL;
2486 if (reader->allocs & XML_TEXTREADER_INPUT) {
2487 ret = reader->input;
2488 reader->input = NULL;
2489 reader->allocs -= XML_TEXTREADER_INPUT;
2490 } else {
2492 * Hum, one may need to duplicate the data structure because
2493 * without reference counting the input may be freed twice:
2494 * - by the layer which allocated it.
2495 * - by the layer to which would have been returned to.
2497 TODO
2498 return(NULL);
2500 return(ret);
2504 * xmlTextReaderLookupNamespace:
2505 * @reader: the xmlTextReaderPtr used
2506 * @prefix: the prefix whose namespace URI is to be resolved. To return
2507 * the default namespace, specify NULL
2509 * Resolves a namespace prefix in the scope of the current element.
2511 * Returns a string containing the namespace URI to which the prefix maps
2512 * or NULL in case of error. The string must be deallocated by the caller.
2514 xmlChar *
2515 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2516 xmlNsPtr ns;
2518 if (reader == NULL)
2519 return(NULL);
2520 if (reader->node == NULL)
2521 return(NULL);
2523 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2524 if (ns == NULL)
2525 return(NULL);
2526 return(xmlStrdup(ns->href));
2530 * xmlTextReaderMoveToAttributeNo:
2531 * @reader: the xmlTextReaderPtr used
2532 * @no: the zero-based index of the attribute relative to the containing
2533 * element.
2535 * Moves the position of the current instance to the attribute with
2536 * the specified index relative to the containing element.
2538 * Returns 1 in case of success, -1 in case of error, 0 if not found
2541 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2542 int i;
2543 xmlAttrPtr cur;
2544 xmlNsPtr ns;
2546 if (reader == NULL)
2547 return(-1);
2548 if (reader->node == NULL)
2549 return(-1);
2550 /* TODO: handle the xmlDecl */
2551 if (reader->node->type != XML_ELEMENT_NODE)
2552 return(-1);
2554 reader->curnode = NULL;
2556 ns = reader->node->nsDef;
2557 for (i = 0;(i < no) && (ns != NULL);i++) {
2558 ns = ns->next;
2560 if (ns != NULL) {
2561 reader->curnode = (xmlNodePtr) ns;
2562 return(1);
2565 cur = reader->node->properties;
2566 if (cur == NULL)
2567 return(0);
2568 for (;i < no;i++) {
2569 cur = cur->next;
2570 if (cur == NULL)
2571 return(0);
2573 /* TODO walk the DTD if present */
2575 reader->curnode = (xmlNodePtr) cur;
2576 return(1);
2580 * xmlTextReaderMoveToAttribute:
2581 * @reader: the xmlTextReaderPtr used
2582 * @name: the qualified name of the attribute.
2584 * Moves the position of the current instance to the attribute with
2585 * the specified qualified name.
2587 * Returns 1 in case of success, -1 in case of error, 0 if not found
2590 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2591 xmlChar *prefix = NULL;
2592 xmlChar *localname;
2593 xmlNsPtr ns;
2594 xmlAttrPtr prop;
2596 if ((reader == NULL) || (name == NULL))
2597 return(-1);
2598 if (reader->node == NULL)
2599 return(-1);
2601 /* TODO: handle the xmlDecl */
2602 if (reader->node->type != XML_ELEMENT_NODE)
2603 return(0);
2605 localname = xmlSplitQName2(name, &prefix);
2606 if (localname == NULL) {
2608 * Namespace default decl
2610 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2611 ns = reader->node->nsDef;
2612 while (ns != NULL) {
2613 if (ns->prefix == NULL) {
2614 reader->curnode = (xmlNodePtr) ns;
2615 return(1);
2617 ns = ns->next;
2619 return(0);
2622 prop = reader->node->properties;
2623 while (prop != NULL) {
2625 * One need to have
2626 * - same attribute names
2627 * - and the attribute carrying that namespace
2629 if ((xmlStrEqual(prop->name, name)) &&
2630 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2631 reader->curnode = (xmlNodePtr) prop;
2632 return(1);
2634 prop = prop->next;
2636 return(0);
2640 * Namespace default decl
2642 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2643 ns = reader->node->nsDef;
2644 while (ns != NULL) {
2645 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2646 reader->curnode = (xmlNodePtr) ns;
2647 goto found;
2649 ns = ns->next;
2651 goto not_found;
2653 prop = reader->node->properties;
2654 while (prop != NULL) {
2656 * One need to have
2657 * - same attribute names
2658 * - and the attribute carrying that namespace
2660 if ((xmlStrEqual(prop->name, localname)) &&
2661 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2662 reader->curnode = (xmlNodePtr) prop;
2663 goto found;
2665 prop = prop->next;
2667 not_found:
2668 if (localname != NULL)
2669 xmlFree(localname);
2670 if (prefix != NULL)
2671 xmlFree(prefix);
2672 return(0);
2674 found:
2675 if (localname != NULL)
2676 xmlFree(localname);
2677 if (prefix != NULL)
2678 xmlFree(prefix);
2679 return(1);
2683 * xmlTextReaderMoveToAttributeNs:
2684 * @reader: the xmlTextReaderPtr used
2685 * @localName: the local name of the attribute.
2686 * @namespaceURI: the namespace URI of the attribute.
2688 * Moves the position of the current instance to the attribute with the
2689 * specified local name and namespace URI.
2691 * Returns 1 in case of success, -1 in case of error, 0 if not found
2694 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2695 const xmlChar *localName, const xmlChar *namespaceURI) {
2696 xmlAttrPtr prop;
2697 xmlNodePtr node;
2698 xmlNsPtr ns;
2699 xmlChar *prefix = NULL;
2701 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2702 return(-1);
2703 if (reader->node == NULL)
2704 return(-1);
2705 if (reader->node->type != XML_ELEMENT_NODE)
2706 return(0);
2707 node = reader->node;
2709 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2710 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2711 prefix = BAD_CAST localName;
2713 ns = reader->node->nsDef;
2714 while (ns != NULL) {
2715 if ((prefix == NULL && ns->prefix == NULL) ||
2716 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2717 reader->curnode = (xmlNodePtr) ns;
2718 return(1);
2720 ns = ns->next;
2722 return(0);
2725 prop = node->properties;
2726 while (prop != NULL) {
2728 * One need to have
2729 * - same attribute names
2730 * - and the attribute carrying that namespace
2732 if (xmlStrEqual(prop->name, localName) &&
2733 ((prop->ns != NULL) &&
2734 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2735 reader->curnode = (xmlNodePtr) prop;
2736 return(1);
2738 prop = prop->next;
2740 return(0);
2744 * xmlTextReaderMoveToFirstAttribute:
2745 * @reader: the xmlTextReaderPtr used
2747 * Moves the position of the current instance to the first attribute
2748 * associated with the current node.
2750 * Returns 1 in case of success, -1 in case of error, 0 if not found
2753 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2754 if (reader == NULL)
2755 return(-1);
2756 if (reader->node == NULL)
2757 return(-1);
2758 if (reader->node->type != XML_ELEMENT_NODE)
2759 return(0);
2761 if (reader->node->nsDef != NULL) {
2762 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2763 return(1);
2765 if (reader->node->properties != NULL) {
2766 reader->curnode = (xmlNodePtr) reader->node->properties;
2767 return(1);
2769 return(0);
2773 * xmlTextReaderMoveToNextAttribute:
2774 * @reader: the xmlTextReaderPtr used
2776 * Moves the position of the current instance to the next attribute
2777 * associated with the current node.
2779 * Returns 1 in case of success, -1 in case of error, 0 if not found
2782 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2783 if (reader == NULL)
2784 return(-1);
2785 if (reader->node == NULL)
2786 return(-1);
2787 if (reader->node->type != XML_ELEMENT_NODE)
2788 return(0);
2789 if (reader->curnode == NULL)
2790 return(xmlTextReaderMoveToFirstAttribute(reader));
2792 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2793 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2794 if (ns->next != NULL) {
2795 reader->curnode = (xmlNodePtr) ns->next;
2796 return(1);
2798 if (reader->node->properties != NULL) {
2799 reader->curnode = (xmlNodePtr) reader->node->properties;
2800 return(1);
2802 return(0);
2803 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2804 (reader->curnode->next != NULL)) {
2805 reader->curnode = reader->curnode->next;
2806 return(1);
2808 return(0);
2812 * xmlTextReaderMoveToElement:
2813 * @reader: the xmlTextReaderPtr used
2815 * Moves the position of the current instance to the node that
2816 * contains the current Attribute node.
2818 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2821 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2822 if (reader == NULL)
2823 return(-1);
2824 if (reader->node == NULL)
2825 return(-1);
2826 if (reader->node->type != XML_ELEMENT_NODE)
2827 return(0);
2828 if (reader->curnode != NULL) {
2829 reader->curnode = NULL;
2830 return(1);
2832 return(0);
2836 * xmlTextReaderReadAttributeValue:
2837 * @reader: the xmlTextReaderPtr used
2839 * Parses an attribute value into one or more Text and EntityReference nodes.
2841 * Returns 1 in case of success, 0 if the reader was not positionned on an
2842 * ttribute node or all the attribute values have been read, or -1
2843 * in case of error.
2846 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2847 if (reader == NULL)
2848 return(-1);
2849 if (reader->node == NULL)
2850 return(-1);
2851 if (reader->curnode == NULL)
2852 return(0);
2853 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2854 if (reader->curnode->children == NULL)
2855 return(0);
2856 reader->curnode = reader->curnode->children;
2857 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2858 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2860 if (reader->faketext == NULL) {
2861 reader->faketext = xmlNewDocText(reader->node->doc,
2862 ns->href);
2863 } else {
2864 if ((reader->faketext->content != NULL) &&
2865 (reader->faketext->content !=
2866 (xmlChar *) &(reader->faketext->properties)))
2867 xmlFree(reader->faketext->content);
2868 reader->faketext->content = xmlStrdup(ns->href);
2870 reader->curnode = reader->faketext;
2871 } else {
2872 if (reader->curnode->next == NULL)
2873 return(0);
2874 reader->curnode = reader->curnode->next;
2876 return(1);
2880 * xmlTextReaderConstEncoding:
2881 * @reader: the xmlTextReaderPtr used
2883 * Determine the encoding of the document being read.
2885 * Returns a string containing the encoding of the document or NULL in
2886 * case of error. The string is deallocated with the reader.
2888 const xmlChar *
2889 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2890 xmlDocPtr doc = NULL;
2891 if (reader == NULL)
2892 return(NULL);
2893 if (reader->doc != NULL)
2894 doc = reader->doc;
2895 else if (reader->ctxt != NULL)
2896 doc = reader->ctxt->myDoc;
2897 if (doc == NULL)
2898 return(NULL);
2900 if (doc->encoding == NULL)
2901 return(NULL);
2902 else
2903 return(CONSTSTR(doc->encoding));
2907 /************************************************************************
2909 * Acces API to the current node *
2911 ************************************************************************/
2913 * xmlTextReaderAttributeCount:
2914 * @reader: the xmlTextReaderPtr used
2916 * Provides the number of attributes of the current node
2918 * Returns 0 i no attributes, -1 in case of error or the attribute count
2921 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2922 int ret;
2923 xmlAttrPtr attr;
2924 xmlNsPtr ns;
2925 xmlNodePtr node;
2927 if (reader == NULL)
2928 return(-1);
2929 if (reader->node == NULL)
2930 return(0);
2932 if (reader->curnode != NULL)
2933 node = reader->curnode;
2934 else
2935 node = reader->node;
2937 if (node->type != XML_ELEMENT_NODE)
2938 return(0);
2939 if ((reader->state == XML_TEXTREADER_END) ||
2940 (reader->state == XML_TEXTREADER_BACKTRACK))
2941 return(0);
2942 ret = 0;
2943 attr = node->properties;
2944 while (attr != NULL) {
2945 ret++;
2946 attr = attr->next;
2948 ns = node->nsDef;
2949 while (ns != NULL) {
2950 ret++;
2951 ns = ns->next;
2953 return(ret);
2957 * xmlTextReaderNodeType:
2958 * @reader: the xmlTextReaderPtr used
2960 * Get the node type of the current node
2961 * Reference:
2962 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
2964 * Returns the xmlNodeType of the current node or -1 in case of error
2967 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2968 xmlNodePtr node;
2970 if (reader == NULL)
2971 return(-1);
2972 if (reader->node == NULL)
2973 return(XML_READER_TYPE_NONE);
2974 if (reader->curnode != NULL)
2975 node = reader->curnode;
2976 else
2977 node = reader->node;
2978 switch (node->type) {
2979 case XML_ELEMENT_NODE:
2980 if ((reader->state == XML_TEXTREADER_END) ||
2981 (reader->state == XML_TEXTREADER_BACKTRACK))
2982 return(XML_READER_TYPE_END_ELEMENT);
2983 return(XML_READER_TYPE_ELEMENT);
2984 case XML_NAMESPACE_DECL:
2985 case XML_ATTRIBUTE_NODE:
2986 return(XML_READER_TYPE_ATTRIBUTE);
2987 case XML_TEXT_NODE:
2988 if (xmlIsBlankNode(reader->node)) {
2989 if (xmlNodeGetSpacePreserve(reader->node))
2990 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2991 else
2992 return(XML_READER_TYPE_WHITESPACE);
2993 } else {
2994 return(XML_READER_TYPE_TEXT);
2996 case XML_CDATA_SECTION_NODE:
2997 return(XML_READER_TYPE_CDATA);
2998 case XML_ENTITY_REF_NODE:
2999 return(XML_READER_TYPE_ENTITY_REFERENCE);
3000 case XML_ENTITY_NODE:
3001 return(XML_READER_TYPE_ENTITY);
3002 case XML_PI_NODE:
3003 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3004 case XML_COMMENT_NODE:
3005 return(XML_READER_TYPE_COMMENT);
3006 case XML_DOCUMENT_NODE:
3007 case XML_HTML_DOCUMENT_NODE:
3008 #ifdef LIBXML_DOCB_ENABLED
3009 case XML_DOCB_DOCUMENT_NODE:
3010 #endif
3011 return(XML_READER_TYPE_DOCUMENT);
3012 case XML_DOCUMENT_FRAG_NODE:
3013 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3014 case XML_NOTATION_NODE:
3015 return(XML_READER_TYPE_NOTATION);
3016 case XML_DOCUMENT_TYPE_NODE:
3017 case XML_DTD_NODE:
3018 return(XML_READER_TYPE_DOCUMENT_TYPE);
3020 case XML_ELEMENT_DECL:
3021 case XML_ATTRIBUTE_DECL:
3022 case XML_ENTITY_DECL:
3023 case XML_XINCLUDE_START:
3024 case XML_XINCLUDE_END:
3025 return(XML_READER_TYPE_NONE);
3027 return(-1);
3031 * xmlTextReaderIsEmptyElement:
3032 * @reader: the xmlTextReaderPtr used
3034 * Check if the current node is empty
3036 * Returns 1 if empty, 0 if not and -1 in case of error
3039 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3040 if ((reader == NULL) || (reader->node == NULL))
3041 return(-1);
3042 if (reader->node->type != XML_ELEMENT_NODE)
3043 return(0);
3044 if (reader->curnode != NULL)
3045 return(0);
3046 if (reader->node->children != NULL)
3047 return(0);
3048 if (reader->state == XML_TEXTREADER_END)
3049 return(0);
3050 if (reader->doc != NULL)
3051 return(1);
3052 #ifdef LIBXML_XINCLUDE_ENABLED
3053 if (reader->in_xinclude > 0)
3054 return(1);
3055 #endif
3056 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3060 * xmlTextReaderLocalName:
3061 * @reader: the xmlTextReaderPtr used
3063 * The local name of the node.
3065 * Returns the local name or NULL if not available,
3066 * if non NULL it need to be freed by the caller.
3068 xmlChar *
3069 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3070 xmlNodePtr node;
3071 if ((reader == NULL) || (reader->node == NULL))
3072 return(NULL);
3073 if (reader->curnode != NULL)
3074 node = reader->curnode;
3075 else
3076 node = reader->node;
3077 if (node->type == XML_NAMESPACE_DECL) {
3078 xmlNsPtr ns = (xmlNsPtr) node;
3079 if (ns->prefix == NULL)
3080 return(xmlStrdup(BAD_CAST "xmlns"));
3081 else
3082 return(xmlStrdup(ns->prefix));
3084 if ((node->type != XML_ELEMENT_NODE) &&
3085 (node->type != XML_ATTRIBUTE_NODE))
3086 return(xmlTextReaderName(reader));
3087 return(xmlStrdup(node->name));
3091 * xmlTextReaderConstLocalName:
3092 * @reader: the xmlTextReaderPtr used
3094 * The local name of the node.
3096 * Returns the local name or NULL if not available, the
3097 * string will be deallocated with the reader.
3099 const xmlChar *
3100 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3101 xmlNodePtr node;
3102 if ((reader == NULL) || (reader->node == NULL))
3103 return(NULL);
3104 if (reader->curnode != NULL)
3105 node = reader->curnode;
3106 else
3107 node = reader->node;
3108 if (node->type == XML_NAMESPACE_DECL) {
3109 xmlNsPtr ns = (xmlNsPtr) node;
3110 if (ns->prefix == NULL)
3111 return(CONSTSTR(BAD_CAST "xmlns"));
3112 else
3113 return(ns->prefix);
3115 if ((node->type != XML_ELEMENT_NODE) &&
3116 (node->type != XML_ATTRIBUTE_NODE))
3117 return(xmlTextReaderConstName(reader));
3118 return(node->name);
3122 * xmlTextReaderName:
3123 * @reader: the xmlTextReaderPtr used
3125 * The qualified name of the node, equal to Prefix :LocalName.
3127 * Returns the local name or NULL if not available,
3128 * if non NULL it need to be freed by the caller.
3130 xmlChar *
3131 xmlTextReaderName(xmlTextReaderPtr reader) {
3132 xmlNodePtr node;
3133 xmlChar *ret;
3135 if ((reader == NULL) || (reader->node == NULL))
3136 return(NULL);
3137 if (reader->curnode != NULL)
3138 node = reader->curnode;
3139 else
3140 node = reader->node;
3141 switch (node->type) {
3142 case XML_ELEMENT_NODE:
3143 case XML_ATTRIBUTE_NODE:
3144 if ((node->ns == NULL) ||
3145 (node->ns->prefix == NULL))
3146 return(xmlStrdup(node->name));
3148 ret = xmlStrdup(node->ns->prefix);
3149 ret = xmlStrcat(ret, BAD_CAST ":");
3150 ret = xmlStrcat(ret, node->name);
3151 return(ret);
3152 case XML_TEXT_NODE:
3153 return(xmlStrdup(BAD_CAST "#text"));
3154 case XML_CDATA_SECTION_NODE:
3155 return(xmlStrdup(BAD_CAST "#cdata-section"));
3156 case XML_ENTITY_NODE:
3157 case XML_ENTITY_REF_NODE:
3158 return(xmlStrdup(node->name));
3159 case XML_PI_NODE:
3160 return(xmlStrdup(node->name));
3161 case XML_COMMENT_NODE:
3162 return(xmlStrdup(BAD_CAST "#comment"));
3163 case XML_DOCUMENT_NODE:
3164 case XML_HTML_DOCUMENT_NODE:
3165 #ifdef LIBXML_DOCB_ENABLED
3166 case XML_DOCB_DOCUMENT_NODE:
3167 #endif
3168 return(xmlStrdup(BAD_CAST "#document"));
3169 case XML_DOCUMENT_FRAG_NODE:
3170 return(xmlStrdup(BAD_CAST "#document-fragment"));
3171 case XML_NOTATION_NODE:
3172 return(xmlStrdup(node->name));
3173 case XML_DOCUMENT_TYPE_NODE:
3174 case XML_DTD_NODE:
3175 return(xmlStrdup(node->name));
3176 case XML_NAMESPACE_DECL: {
3177 xmlNsPtr ns = (xmlNsPtr) node;
3179 ret = xmlStrdup(BAD_CAST "xmlns");
3180 if (ns->prefix == NULL)
3181 return(ret);
3182 ret = xmlStrcat(ret, BAD_CAST ":");
3183 ret = xmlStrcat(ret, ns->prefix);
3184 return(ret);
3187 case XML_ELEMENT_DECL:
3188 case XML_ATTRIBUTE_DECL:
3189 case XML_ENTITY_DECL:
3190 case XML_XINCLUDE_START:
3191 case XML_XINCLUDE_END:
3192 return(NULL);
3194 return(NULL);
3198 * xmlTextReaderConstName:
3199 * @reader: the xmlTextReaderPtr used
3201 * The qualified name of the node, equal to Prefix :LocalName.
3203 * Returns the local name or NULL if not available, the string is
3204 * deallocated with the reader.
3206 const xmlChar *
3207 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3208 xmlNodePtr node;
3210 if ((reader == NULL) || (reader->node == NULL))
3211 return(NULL);
3212 if (reader->curnode != NULL)
3213 node = reader->curnode;
3214 else
3215 node = reader->node;
3216 switch (node->type) {
3217 case XML_ELEMENT_NODE:
3218 case XML_ATTRIBUTE_NODE:
3219 if ((node->ns == NULL) ||
3220 (node->ns->prefix == NULL))
3221 return(node->name);
3222 return(CONSTQSTR(node->ns->prefix, node->name));
3223 case XML_TEXT_NODE:
3224 return(CONSTSTR(BAD_CAST "#text"));
3225 case XML_CDATA_SECTION_NODE:
3226 return(CONSTSTR(BAD_CAST "#cdata-section"));
3227 case XML_ENTITY_NODE:
3228 case XML_ENTITY_REF_NODE:
3229 return(CONSTSTR(node->name));
3230 case XML_PI_NODE:
3231 return(CONSTSTR(node->name));
3232 case XML_COMMENT_NODE:
3233 return(CONSTSTR(BAD_CAST "#comment"));
3234 case XML_DOCUMENT_NODE:
3235 case XML_HTML_DOCUMENT_NODE:
3236 #ifdef LIBXML_DOCB_ENABLED
3237 case XML_DOCB_DOCUMENT_NODE:
3238 #endif
3239 return(CONSTSTR(BAD_CAST "#document"));
3240 case XML_DOCUMENT_FRAG_NODE:
3241 return(CONSTSTR(BAD_CAST "#document-fragment"));
3242 case XML_NOTATION_NODE:
3243 return(CONSTSTR(node->name));
3244 case XML_DOCUMENT_TYPE_NODE:
3245 case XML_DTD_NODE:
3246 return(CONSTSTR(node->name));
3247 case XML_NAMESPACE_DECL: {
3248 xmlNsPtr ns = (xmlNsPtr) node;
3250 if (ns->prefix == NULL)
3251 return(CONSTSTR(BAD_CAST "xmlns"));
3252 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3255 case XML_ELEMENT_DECL:
3256 case XML_ATTRIBUTE_DECL:
3257 case XML_ENTITY_DECL:
3258 case XML_XINCLUDE_START:
3259 case XML_XINCLUDE_END:
3260 return(NULL);
3262 return(NULL);
3266 * xmlTextReaderPrefix:
3267 * @reader: the xmlTextReaderPtr used
3269 * A shorthand reference to the namespace associated with the node.
3271 * Returns the prefix or NULL if not available,
3272 * if non NULL it need to be freed by the caller.
3274 xmlChar *
3275 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3276 xmlNodePtr node;
3277 if ((reader == NULL) || (reader->node == NULL))
3278 return(NULL);
3279 if (reader->curnode != NULL)
3280 node = reader->curnode;
3281 else
3282 node = reader->node;
3283 if (node->type == XML_NAMESPACE_DECL) {
3284 xmlNsPtr ns = (xmlNsPtr) node;
3285 if (ns->prefix == NULL)
3286 return(NULL);
3287 return(xmlStrdup(BAD_CAST "xmlns"));
3289 if ((node->type != XML_ELEMENT_NODE) &&
3290 (node->type != XML_ATTRIBUTE_NODE))
3291 return(NULL);
3292 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3293 return(xmlStrdup(node->ns->prefix));
3294 return(NULL);
3298 * xmlTextReaderConstPrefix:
3299 * @reader: the xmlTextReaderPtr used
3301 * A shorthand reference to the namespace associated with the node.
3303 * Returns the prefix or NULL if not available, the string is deallocated
3304 * with the reader.
3306 const xmlChar *
3307 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3308 xmlNodePtr node;
3309 if ((reader == NULL) || (reader->node == NULL))
3310 return(NULL);
3311 if (reader->curnode != NULL)
3312 node = reader->curnode;
3313 else
3314 node = reader->node;
3315 if (node->type == XML_NAMESPACE_DECL) {
3316 xmlNsPtr ns = (xmlNsPtr) node;
3317 if (ns->prefix == NULL)
3318 return(NULL);
3319 return(CONSTSTR(BAD_CAST "xmlns"));
3321 if ((node->type != XML_ELEMENT_NODE) &&
3322 (node->type != XML_ATTRIBUTE_NODE))
3323 return(NULL);
3324 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3325 return(CONSTSTR(node->ns->prefix));
3326 return(NULL);
3330 * xmlTextReaderNamespaceUri:
3331 * @reader: the xmlTextReaderPtr used
3333 * The URI defining the namespace associated with the node.
3335 * Returns the namespace URI or NULL if not available,
3336 * if non NULL it need to be freed by the caller.
3338 xmlChar *
3339 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3340 xmlNodePtr node;
3341 if ((reader == NULL) || (reader->node == NULL))
3342 return(NULL);
3343 if (reader->curnode != NULL)
3344 node = reader->curnode;
3345 else
3346 node = reader->node;
3347 if (node->type == XML_NAMESPACE_DECL)
3348 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3349 if ((node->type != XML_ELEMENT_NODE) &&
3350 (node->type != XML_ATTRIBUTE_NODE))
3351 return(NULL);
3352 if (node->ns != NULL)
3353 return(xmlStrdup(node->ns->href));
3354 return(NULL);
3358 * xmlTextReaderConstNamespaceUri:
3359 * @reader: the xmlTextReaderPtr used
3361 * The URI defining the namespace associated with the node.
3363 * Returns the namespace URI or NULL if not available, the string
3364 * will be deallocated with the reader
3366 const xmlChar *
3367 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3368 xmlNodePtr node;
3369 if ((reader == NULL) || (reader->node == NULL))
3370 return(NULL);
3371 if (reader->curnode != NULL)
3372 node = reader->curnode;
3373 else
3374 node = reader->node;
3375 if (node->type == XML_NAMESPACE_DECL)
3376 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3377 if ((node->type != XML_ELEMENT_NODE) &&
3378 (node->type != XML_ATTRIBUTE_NODE))
3379 return(NULL);
3380 if (node->ns != NULL)
3381 return(CONSTSTR(node->ns->href));
3382 return(NULL);
3386 * xmlTextReaderBaseUri:
3387 * @reader: the xmlTextReaderPtr used
3389 * The base URI of the node.
3391 * Returns the base URI or NULL if not available,
3392 * if non NULL it need to be freed by the caller.
3394 xmlChar *
3395 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3396 if ((reader == NULL) || (reader->node == NULL))
3397 return(NULL);
3398 return(xmlNodeGetBase(NULL, reader->node));
3402 * xmlTextReaderConstBaseUri:
3403 * @reader: the xmlTextReaderPtr used
3405 * The base URI of the node.
3407 * Returns the base URI or NULL if not available, the string
3408 * will be deallocated with the reader
3410 const xmlChar *
3411 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3412 xmlChar *tmp;
3413 const xmlChar *ret;
3415 if ((reader == NULL) || (reader->node == NULL))
3416 return(NULL);
3417 tmp = xmlNodeGetBase(NULL, reader->node);
3418 if (tmp == NULL)
3419 return(NULL);
3420 ret = CONSTSTR(tmp);
3421 xmlFree(tmp);
3422 return(ret);
3426 * xmlTextReaderDepth:
3427 * @reader: the xmlTextReaderPtr used
3429 * The depth of the node in the tree.
3431 * Returns the depth or -1 in case of error
3434 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3435 if (reader == NULL)
3436 return(-1);
3437 if (reader->node == NULL)
3438 return(0);
3440 if (reader->curnode != NULL) {
3441 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3442 (reader->curnode->type == XML_NAMESPACE_DECL))
3443 return(reader->depth + 1);
3444 return(reader->depth + 2);
3446 return(reader->depth);
3450 * xmlTextReaderHasAttributes:
3451 * @reader: the xmlTextReaderPtr used
3453 * Whether the node has attributes.
3455 * Returns 1 if true, 0 if false, and -1 in case or error
3458 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3459 xmlNodePtr node;
3460 if (reader == NULL)
3461 return(-1);
3462 if (reader->node == NULL)
3463 return(0);
3464 if (reader->curnode != NULL)
3465 node = reader->curnode;
3466 else
3467 node = reader->node;
3469 if ((node->type == XML_ELEMENT_NODE) &&
3470 ((node->properties != NULL) || (node->nsDef != NULL)))
3471 return(1);
3472 /* TODO: handle the xmlDecl */
3473 return(0);
3477 * xmlTextReaderHasValue:
3478 * @reader: the xmlTextReaderPtr used
3480 * Whether the node can have a text value.
3482 * Returns 1 if true, 0 if false, and -1 in case or error
3485 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3486 xmlNodePtr node;
3487 if (reader == NULL)
3488 return(-1);
3489 if (reader->node == NULL)
3490 return(0);
3491 if (reader->curnode != NULL)
3492 node = reader->curnode;
3493 else
3494 node = reader->node;
3496 switch (node->type) {
3497 case XML_ATTRIBUTE_NODE:
3498 case XML_TEXT_NODE:
3499 case XML_CDATA_SECTION_NODE:
3500 case XML_PI_NODE:
3501 case XML_COMMENT_NODE:
3502 case XML_NAMESPACE_DECL:
3503 return(1);
3504 default:
3505 break;
3507 return(0);
3511 * xmlTextReaderValue:
3512 * @reader: the xmlTextReaderPtr used
3514 * Provides the text value of the node if present
3516 * Returns the string or NULL if not available. The result must be deallocated
3517 * with xmlFree()
3519 xmlChar *
3520 xmlTextReaderValue(xmlTextReaderPtr reader) {
3521 xmlNodePtr node;
3522 if (reader == NULL)
3523 return(NULL);
3524 if (reader->node == NULL)
3525 return(NULL);
3526 if (reader->curnode != NULL)
3527 node = reader->curnode;
3528 else
3529 node = reader->node;
3531 switch (node->type) {
3532 case XML_NAMESPACE_DECL:
3533 return(xmlStrdup(((xmlNsPtr) node)->href));
3534 case XML_ATTRIBUTE_NODE:{
3535 xmlAttrPtr attr = (xmlAttrPtr) node;
3537 if (attr->parent != NULL)
3538 return (xmlNodeListGetString
3539 (attr->parent->doc, attr->children, 1));
3540 else
3541 return (xmlNodeListGetString(NULL, attr->children, 1));
3542 break;
3544 case XML_TEXT_NODE:
3545 case XML_CDATA_SECTION_NODE:
3546 case XML_PI_NODE:
3547 case XML_COMMENT_NODE:
3548 if (node->content != NULL)
3549 return (xmlStrdup(node->content));
3550 default:
3551 break;
3553 return(NULL);
3557 * xmlTextReaderConstValue:
3558 * @reader: the xmlTextReaderPtr used
3560 * Provides the text value of the node if present
3562 * Returns the string or NULL if not available. The result will be
3563 * deallocated on the next Read() operation.
3565 const xmlChar *
3566 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3567 xmlNodePtr node;
3568 if (reader == NULL)
3569 return(NULL);
3570 if (reader->node == NULL)
3571 return(NULL);
3572 if (reader->curnode != NULL)
3573 node = reader->curnode;
3574 else
3575 node = reader->node;
3577 switch (node->type) {
3578 case XML_NAMESPACE_DECL:
3579 return(((xmlNsPtr) node)->href);
3580 case XML_ATTRIBUTE_NODE:{
3581 xmlAttrPtr attr = (xmlAttrPtr) node;
3583 if ((attr->children != NULL) &&
3584 (attr->children->type == XML_TEXT_NODE) &&
3585 (attr->children->next == NULL))
3586 return(attr->children->content);
3587 else {
3588 if (reader->buffer == NULL)
3589 reader->buffer = xmlBufferCreateSize(100);
3590 if (reader->buffer == NULL) {
3591 xmlGenericError(xmlGenericErrorContext,
3592 "xmlTextReaderSetup : malloc failed\n");
3593 return (NULL);
3595 reader->buffer->use = 0;
3596 xmlNodeBufGetContent(reader->buffer, node);
3597 return(reader->buffer->content);
3599 break;
3601 case XML_TEXT_NODE:
3602 case XML_CDATA_SECTION_NODE:
3603 case XML_PI_NODE:
3604 case XML_COMMENT_NODE:
3605 return(node->content);
3606 default:
3607 break;
3609 return(NULL);
3613 * xmlTextReaderIsDefault:
3614 * @reader: the xmlTextReaderPtr used
3616 * Whether an Attribute node was generated from the default value
3617 * defined in the DTD or schema.
3619 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3622 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3623 if (reader == NULL)
3624 return(-1);
3625 return(0);
3629 * xmlTextReaderQuoteChar:
3630 * @reader: the xmlTextReaderPtr used
3632 * The quotation mark character used to enclose the value of an attribute.
3634 * Returns " or ' and -1 in case of error
3637 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3638 if (reader == NULL)
3639 return(-1);
3640 /* TODO maybe lookup the attribute value for " first */
3641 return((int) '"');
3645 * xmlTextReaderXmlLang:
3646 * @reader: the xmlTextReaderPtr used
3648 * The xml:lang scope within which the node resides.
3650 * Returns the xml:lang value or NULL if none exists.,
3651 * if non NULL it need to be freed by the caller.
3653 xmlChar *
3654 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3655 if (reader == NULL)
3656 return(NULL);
3657 if (reader->node == NULL)
3658 return(NULL);
3659 return(xmlNodeGetLang(reader->node));
3663 * xmlTextReaderConstXmlLang:
3664 * @reader: the xmlTextReaderPtr used
3666 * The xml:lang scope within which the node resides.
3668 * Returns the xml:lang value or NULL if none exists.
3670 const xmlChar *
3671 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3672 xmlChar *tmp;
3673 const xmlChar *ret;
3675 if (reader == NULL)
3676 return(NULL);
3677 if (reader->node == NULL)
3678 return(NULL);
3679 tmp = xmlNodeGetLang(reader->node);
3680 if (tmp == NULL)
3681 return(NULL);
3682 ret = CONSTSTR(tmp);
3683 xmlFree(tmp);
3684 return(ret);
3688 * xmlTextReaderConstString:
3689 * @reader: the xmlTextReaderPtr used
3690 * @str: the string to intern.
3692 * Get an interned string from the reader, allows for example to
3693 * speedup string name comparisons
3695 * Returns an interned copy of the string or NULL in case of error. The
3696 * string will be deallocated with the reader.
3698 const xmlChar *
3699 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3700 if (reader == NULL)
3701 return(NULL);
3702 return(CONSTSTR(str));
3706 * xmlTextReaderNormalization:
3707 * @reader: the xmlTextReaderPtr used
3709 * The value indicating whether to normalize white space and attribute values.
3710 * Since attribute value and end of line normalizations are a MUST in the XML
3711 * specification only the value true is accepted. The broken bahaviour of
3712 * accepting out of range character entities like &#0; is of course not
3713 * supported either.
3715 * Returns 1 or -1 in case of error.
3718 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3719 if (reader == NULL)
3720 return(-1);
3721 return(1);
3724 /************************************************************************
3726 * Extensions to the base APIs *
3728 ************************************************************************/
3731 * xmlTextReaderSetParserProp:
3732 * @reader: the xmlTextReaderPtr used
3733 * @prop: the xmlParserProperties to set
3734 * @value: usually 0 or 1 to (de)activate it
3736 * Change the parser processing behaviour by changing some of its internal
3737 * properties. Note that some properties can only be changed before any
3738 * read has been done.
3740 * Returns 0 if the call was successful, or -1 in case of error
3743 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3744 xmlParserProperties p = (xmlParserProperties) prop;
3745 xmlParserCtxtPtr ctxt;
3747 if ((reader == NULL) || (reader->ctxt == NULL))
3748 return(-1);
3749 ctxt = reader->ctxt;
3751 switch (p) {
3752 case XML_PARSER_LOADDTD:
3753 if (value != 0) {
3754 if (ctxt->loadsubset == 0) {
3755 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3756 return(-1);
3757 ctxt->loadsubset = XML_DETECT_IDS;
3759 } else {
3760 ctxt->loadsubset = 0;
3762 return(0);
3763 case XML_PARSER_DEFAULTATTRS:
3764 if (value != 0) {
3765 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3766 } else {
3767 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3768 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3770 return(0);
3771 case XML_PARSER_VALIDATE:
3772 if (value != 0) {
3773 ctxt->validate = 1;
3774 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3775 } else {
3776 ctxt->validate = 0;
3778 return(0);
3779 case XML_PARSER_SUBST_ENTITIES:
3780 if (value != 0) {
3781 ctxt->replaceEntities = 1;
3782 } else {
3783 ctxt->replaceEntities = 0;
3785 return(0);
3787 return(-1);
3791 * xmlTextReaderGetParserProp:
3792 * @reader: the xmlTextReaderPtr used
3793 * @prop: the xmlParserProperties to get
3795 * Read the parser internal property.
3797 * Returns the value, usually 0 or 1, or -1 in case of error.
3800 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3801 xmlParserProperties p = (xmlParserProperties) prop;
3802 xmlParserCtxtPtr ctxt;
3804 if ((reader == NULL) || (reader->ctxt == NULL))
3805 return(-1);
3806 ctxt = reader->ctxt;
3808 switch (p) {
3809 case XML_PARSER_LOADDTD:
3810 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3811 return(1);
3812 return(0);
3813 case XML_PARSER_DEFAULTATTRS:
3814 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3815 return(1);
3816 return(0);
3817 case XML_PARSER_VALIDATE:
3818 return(reader->validate);
3819 case XML_PARSER_SUBST_ENTITIES:
3820 return(ctxt->replaceEntities);
3822 return(-1);
3827 * xmlTextReaderGetParserLineNumber:
3828 * @reader: the user data (XML reader context)
3830 * Provide the line number of the current parsing point.
3832 * Returns an int or 0 if not available
3835 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3837 if ((reader == NULL) || (reader->ctxt == NULL) ||
3838 (reader->ctxt->input == NULL)) {
3839 return (0);
3841 return (reader->ctxt->input->line);
3845 * xmlTextReaderGetParserColumnNumber:
3846 * @reader: the user data (XML reader context)
3848 * Provide the column number of the current parsing point.
3850 * Returns an int or 0 if not available
3853 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3855 if ((reader == NULL) || (reader->ctxt == NULL) ||
3856 (reader->ctxt->input == NULL)) {
3857 return (0);
3859 return (reader->ctxt->input->col);
3863 * xmlTextReaderCurrentNode:
3864 * @reader: the xmlTextReaderPtr used
3866 * Hacking interface allowing to get the xmlNodePtr correponding to the
3867 * current node being accessed by the xmlTextReader. This is dangerous
3868 * because the underlying node may be destroyed on the next Reads.
3870 * Returns the xmlNodePtr or NULL in case of error.
3872 xmlNodePtr
3873 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3874 if (reader == NULL)
3875 return(NULL);
3877 if (reader->curnode != NULL)
3878 return(reader->curnode);
3879 return(reader->node);
3883 * xmlTextReaderPreserve:
3884 * @reader: the xmlTextReaderPtr used
3886 * This tells the XML Reader to preserve the current node.
3887 * The caller must also use xmlTextReaderCurrentDoc() to
3888 * keep an handle on the resulting document once parsing has finished
3890 * Returns the xmlNodePtr or NULL in case of error.
3892 xmlNodePtr
3893 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3894 xmlNodePtr cur, parent;
3896 if (reader == NULL)
3897 return(NULL);
3899 if (reader->curnode != NULL)
3900 cur = reader->curnode;
3901 else
3902 cur = reader->node;
3903 if (cur == NULL)
3904 return(NULL);
3906 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3907 cur->extra |= NODE_IS_PRESERVED;
3908 cur->extra |= NODE_IS_SPRESERVED;
3910 reader->preserves++;
3912 parent = cur->parent;;
3913 while (parent != NULL) {
3914 if (parent->type == XML_ELEMENT_NODE)
3915 parent->extra |= NODE_IS_PRESERVED;
3916 parent = parent->parent;
3918 return(cur);
3921 #ifdef LIBXML_PATTERN_ENABLED
3923 * xmlTextReaderPreservePattern:
3924 * @reader: the xmlTextReaderPtr used
3925 * @pattern: an XPath subset pattern
3926 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3928 * This tells the XML Reader to preserve all nodes matched by the
3929 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3930 * keep an handle on the resulting document once parsing has finished
3932 * Returns a positive number in case of success and -1 in case of error
3935 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3936 const xmlChar **namespaces)
3938 xmlPatternPtr comp;
3940 if ((reader == NULL) || (pattern == NULL))
3941 return(-1);
3943 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3944 if (comp == NULL)
3945 return(-1);
3947 if (reader->patternMax <= 0) {
3948 reader->patternMax = 4;
3949 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3950 sizeof(reader->patternTab[0]));
3951 if (reader->patternTab == NULL) {
3952 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3953 return (-1);
3956 if (reader->patternNr >= reader->patternMax) {
3957 xmlPatternPtr *tmp;
3958 reader->patternMax *= 2;
3959 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3960 reader->patternMax *
3961 sizeof(reader->patternTab[0]));
3962 if (tmp == NULL) {
3963 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3964 reader->patternMax /= 2;
3965 return (-1);
3967 reader->patternTab = tmp;
3969 reader->patternTab[reader->patternNr] = comp;
3970 return(reader->patternNr++);
3972 #endif
3975 * xmlTextReaderCurrentDoc:
3976 * @reader: the xmlTextReaderPtr used
3978 * Hacking interface allowing to get the xmlDocPtr correponding to the
3979 * current document being accessed by the xmlTextReader.
3980 * NOTE: as a result of this call, the reader will not destroy the
3981 * associated XML document and calling xmlFreeDoc() on the result
3982 * is needed once the reader parsing has finished.
3984 * Returns the xmlDocPtr or NULL in case of error.
3986 xmlDocPtr
3987 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
3988 if (reader == NULL)
3989 return(NULL);
3990 if (reader->doc != NULL)
3991 return(reader->doc);
3992 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
3993 return(NULL);
3995 reader->preserve = 1;
3996 return(reader->ctxt->myDoc);
3999 #ifdef LIBXML_SCHEMAS_ENABLED
4000 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
4002 static void XMLCDECL
4003 xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4005 static void XMLCDECL
4006 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4008 static void XMLCDECL
4009 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4011 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4013 char *str;
4015 va_list ap;
4017 va_start(ap, msg);
4018 str = xmlTextReaderBuildMessage(msg, ap);
4019 if (!reader->errorFunc) {
4020 xmlTextReaderValidityError(ctx, "%s", str);
4021 } else {
4022 reader->errorFunc(reader->errorFuncArg, str,
4023 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4024 NULL /* locator */ );
4026 if (str != NULL)
4027 xmlFree(str);
4028 va_end(ap);
4031 static void XMLCDECL
4032 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4034 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4036 char *str;
4038 va_list ap;
4040 va_start(ap, msg);
4041 str = xmlTextReaderBuildMessage(msg, ap);
4042 if (!reader->errorFunc) {
4043 xmlTextReaderValidityWarning(ctx, "%s", str);
4044 } else {
4045 reader->errorFunc(reader->errorFuncArg, str,
4046 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4047 NULL /* locator */ );
4049 if (str != NULL)
4050 xmlFree(str);
4051 va_end(ap);
4054 static void
4055 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4057 static void
4058 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4060 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4062 if (reader->sErrorFunc) {
4063 reader->sErrorFunc(reader->errorFuncArg, error);
4064 } else {
4065 xmlTextReaderStructuredError(reader, error);
4069 * xmlTextReaderRelaxNGSetSchema:
4070 * @reader: the xmlTextReaderPtr used
4071 * @schema: a precompiled RelaxNG schema
4073 * Use RelaxNG to validate the document as it is processed.
4074 * Activation is only possible before the first Read().
4075 * if @schema is NULL, then RelaxNG validation is desactivated.
4076 @ The @schema should not be freed until the reader is deallocated
4077 * or its use has been deactivated.
4079 * Returns 0 in case the RelaxNG validation could be (des)activated and
4080 * -1 in case of error.
4083 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4084 if (reader == NULL)
4085 return(-1);
4086 if (schema == NULL) {
4087 if (reader->rngSchemas != NULL) {
4088 xmlRelaxNGFree(reader->rngSchemas);
4089 reader->rngSchemas = NULL;
4091 if (reader->rngValidCtxt != NULL) {
4092 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4093 reader->rngValidCtxt = NULL;
4095 return(0);
4097 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4098 return(-1);
4099 if (reader->rngSchemas != NULL) {
4100 xmlRelaxNGFree(reader->rngSchemas);
4101 reader->rngSchemas = NULL;
4103 if (reader->rngValidCtxt != NULL) {
4104 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4105 reader->rngValidCtxt = NULL;
4107 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4108 if (reader->rngValidCtxt == NULL)
4109 return(-1);
4110 if (reader->errorFunc != NULL) {
4111 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4112 xmlTextReaderValidityErrorRelay,
4113 xmlTextReaderValidityWarningRelay,
4114 reader);
4116 if (reader->sErrorFunc != NULL) {
4117 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4118 xmlTextReaderValidityStructuredRelay,
4119 reader);
4121 reader->rngValidErrors = 0;
4122 reader->rngFullNode = NULL;
4123 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4124 return(0);
4128 * xmlTextReaderSetSchema:
4129 * @reader: the xmlTextReaderPtr used
4130 * @schema: a precompiled Schema schema
4132 * Use XSD Schema to validate the document as it is processed.
4133 * Activation is only possible before the first Read().
4134 * if @schema is NULL, then Schema validation is desactivated.
4135 @ The @schema should not be freed until the reader is deallocated
4136 * or its use has been deactivated.
4138 * Returns 0 in case the Schema validation could be (des)activated and
4139 * -1 in case of error.
4142 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4143 if (reader == NULL)
4144 return(-1);
4145 if (schema == NULL) {
4146 if (reader->xsdPlug != NULL) {
4147 xmlSchemaSAXUnplug(reader->xsdPlug);
4148 reader->xsdPlug = NULL;
4150 if (reader->xsdValidCtxt != NULL) {
4151 if (! reader->xsdPreserveCtxt)
4152 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4153 reader->xsdValidCtxt = NULL;
4155 reader->xsdPreserveCtxt = 0;
4156 if (reader->xsdSchemas != NULL) {
4157 xmlSchemaFree(reader->xsdSchemas);
4158 reader->xsdSchemas = NULL;
4160 return(0);
4162 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4163 return(-1);
4164 if (reader->xsdPlug != NULL) {
4165 xmlSchemaSAXUnplug(reader->xsdPlug);
4166 reader->xsdPlug = NULL;
4168 if (reader->xsdValidCtxt != NULL) {
4169 if (! reader->xsdPreserveCtxt)
4170 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4171 reader->xsdValidCtxt = NULL;
4173 reader->xsdPreserveCtxt = 0;
4174 if (reader->xsdSchemas != NULL) {
4175 xmlSchemaFree(reader->xsdSchemas);
4176 reader->xsdSchemas = NULL;
4178 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4179 if (reader->xsdValidCtxt == NULL) {
4180 xmlSchemaFree(reader->xsdSchemas);
4181 reader->xsdSchemas = NULL;
4182 return(-1);
4184 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4185 &(reader->ctxt->sax),
4186 &(reader->ctxt->userData));
4187 if (reader->xsdPlug == NULL) {
4188 xmlSchemaFree(reader->xsdSchemas);
4189 reader->xsdSchemas = NULL;
4190 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4191 reader->xsdValidCtxt = NULL;
4192 return(-1);
4194 if (reader->errorFunc != NULL) {
4195 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4196 xmlTextReaderValidityErrorRelay,
4197 xmlTextReaderValidityWarningRelay,
4198 reader);
4200 if (reader->sErrorFunc != NULL) {
4201 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4202 xmlTextReaderValidityStructuredRelay,
4203 reader);
4205 reader->xsdValidErrors = 0;
4206 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4207 return(0);
4211 * xmlTextReaderRelaxNGValidate:
4212 * @reader: the xmlTextReaderPtr used
4213 * @rng: the path to a RelaxNG schema or NULL
4215 * Use RelaxNG to validate the document as it is processed.
4216 * Activation is only possible before the first Read().
4217 * if @rng is NULL, then RelaxNG validation is deactivated.
4219 * Returns 0 in case the RelaxNG validation could be (de)activated and
4220 * -1 in case of error.
4223 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4224 xmlRelaxNGParserCtxtPtr ctxt;
4226 if (reader == NULL)
4227 return(-1);
4229 if (rng == NULL) {
4230 if (reader->rngValidCtxt != NULL) {
4231 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4232 reader->rngValidCtxt = NULL;
4234 if (reader->rngSchemas != NULL) {
4235 xmlRelaxNGFree(reader->rngSchemas);
4236 reader->rngSchemas = NULL;
4238 return(0);
4240 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4241 return(-1);
4242 if (reader->rngSchemas != NULL) {
4243 xmlRelaxNGFree(reader->rngSchemas);
4244 reader->rngSchemas = NULL;
4246 if (reader->rngValidCtxt != NULL) {
4247 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4248 reader->rngValidCtxt = NULL;
4250 ctxt = xmlRelaxNGNewParserCtxt(rng);
4251 if (reader->errorFunc != NULL) {
4252 xmlRelaxNGSetParserErrors(ctxt,
4253 xmlTextReaderValidityErrorRelay,
4254 xmlTextReaderValidityWarningRelay,
4255 reader);
4257 if (reader->sErrorFunc != NULL) {
4258 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4259 xmlTextReaderValidityStructuredRelay,
4260 reader);
4262 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4263 xmlRelaxNGFreeParserCtxt(ctxt);
4264 if (reader->rngSchemas == NULL)
4265 return(-1);
4266 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4267 if (reader->rngValidCtxt == NULL) {
4268 xmlRelaxNGFree(reader->rngSchemas);
4269 reader->rngSchemas = NULL;
4270 return(-1);
4272 if (reader->errorFunc != NULL) {
4273 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4274 xmlTextReaderValidityErrorRelay,
4275 xmlTextReaderValidityWarningRelay,
4276 reader);
4278 if (reader->sErrorFunc != NULL) {
4279 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4280 xmlTextReaderValidityStructuredRelay,
4281 reader);
4283 reader->rngValidErrors = 0;
4284 reader->rngFullNode = NULL;
4285 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4286 return(0);
4290 * xmlTextReaderSchemaValidateInternal:
4291 * @reader: the xmlTextReaderPtr used
4292 * @xsd: the path to a W3C XSD schema or NULL
4293 * @ctxt: the XML Schema validation context or NULL
4294 * @options: options (not used yet)
4296 * Validate the document as it is processed using XML Schema.
4297 * Activation is only possible before the first Read().
4298 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4300 * Returns 0 in case the schemas validation could be (de)activated and
4301 * -1 in case of error.
4303 static int
4304 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4305 const char *xsd,
4306 xmlSchemaValidCtxtPtr ctxt,
4307 int options ATTRIBUTE_UNUSED)
4309 if (reader == NULL)
4310 return(-1);
4312 if ((xsd != NULL) && (ctxt != NULL))
4313 return(-1);
4315 if (((xsd != NULL) || (ctxt != NULL)) &&
4316 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4317 (reader->ctxt == NULL)))
4318 return(-1);
4320 /* Cleanup previous validation stuff. */
4321 if (reader->xsdPlug != NULL) {
4322 xmlSchemaSAXUnplug(reader->xsdPlug);
4323 reader->xsdPlug = NULL;
4325 if (reader->xsdValidCtxt != NULL) {
4326 if (! reader->xsdPreserveCtxt)
4327 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4328 reader->xsdValidCtxt = NULL;
4330 reader->xsdPreserveCtxt = 0;
4331 if (reader->xsdSchemas != NULL) {
4332 xmlSchemaFree(reader->xsdSchemas);
4333 reader->xsdSchemas = NULL;
4336 if ((xsd == NULL) && (ctxt == NULL)) {
4337 /* We just want to deactivate the validation, so get out. */
4338 return(0);
4341 if (xsd != NULL) {
4342 xmlSchemaParserCtxtPtr pctxt;
4343 /* Parse the schema and create validation environment. */
4344 pctxt = xmlSchemaNewParserCtxt(xsd);
4345 if (reader->errorFunc != NULL) {
4346 xmlSchemaSetParserErrors(pctxt,
4347 xmlTextReaderValidityErrorRelay,
4348 xmlTextReaderValidityWarningRelay,
4349 reader);
4351 reader->xsdSchemas = xmlSchemaParse(pctxt);
4352 xmlSchemaFreeParserCtxt(pctxt);
4353 if (reader->xsdSchemas == NULL)
4354 return(-1);
4355 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4356 if (reader->xsdValidCtxt == NULL) {
4357 xmlSchemaFree(reader->xsdSchemas);
4358 reader->xsdSchemas = NULL;
4359 return(-1);
4361 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4362 &(reader->ctxt->sax),
4363 &(reader->ctxt->userData));
4364 if (reader->xsdPlug == NULL) {
4365 xmlSchemaFree(reader->xsdSchemas);
4366 reader->xsdSchemas = NULL;
4367 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4368 reader->xsdValidCtxt = NULL;
4369 return(-1);
4371 } else {
4372 /* Use the given validation context. */
4373 reader->xsdValidCtxt = ctxt;
4374 reader->xsdPreserveCtxt = 1;
4375 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4376 &(reader->ctxt->sax),
4377 &(reader->ctxt->userData));
4378 if (reader->xsdPlug == NULL) {
4379 reader->xsdValidCtxt = NULL;
4380 reader->xsdPreserveCtxt = 0;
4381 return(-1);
4385 * Redirect the validation context's error channels to use
4386 * the reader channels.
4387 * TODO: In case the user provides the validation context we
4388 * could make this redirection optional.
4390 if (reader->errorFunc != NULL) {
4391 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4392 xmlTextReaderValidityErrorRelay,
4393 xmlTextReaderValidityWarningRelay,
4394 reader);
4396 if (reader->sErrorFunc != NULL) {
4397 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4398 xmlTextReaderValidityStructuredRelay,
4399 reader);
4401 reader->xsdValidErrors = 0;
4402 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4403 return(0);
4407 * xmlTextReaderSchemaValidateCtxt:
4408 * @reader: the xmlTextReaderPtr used
4409 * @ctxt: the XML Schema validation context or NULL
4410 * @options: options (not used yet)
4412 * Use W3C XSD schema context to validate the document as it is processed.
4413 * Activation is only possible before the first Read().
4414 * If @ctxt is NULL, then XML Schema validation is deactivated.
4416 * Returns 0 in case the schemas validation could be (de)activated and
4417 * -1 in case of error.
4420 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4421 xmlSchemaValidCtxtPtr ctxt,
4422 int options)
4424 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4428 * xmlTextReaderSchemaValidate:
4429 * @reader: the xmlTextReaderPtr used
4430 * @xsd: the path to a W3C XSD schema or NULL
4432 * Use W3C XSD schema to validate the document as it is processed.
4433 * Activation is only possible before the first Read().
4434 * If @xsd is NULL, then XML Schema validation is deactivated.
4436 * Returns 0 in case the schemas validation could be (de)activated and
4437 * -1 in case of error.
4440 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4442 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4444 #endif
4447 * xmlTextReaderIsNamespaceDecl:
4448 * @reader: the xmlTextReaderPtr used
4450 * Determine whether the current node is a namespace declaration
4451 * rather than a regular attribute.
4453 * Returns 1 if the current node is a namespace declaration, 0 if it
4454 * is a regular attribute or other type of node, or -1 in case of
4455 * error.
4458 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4459 xmlNodePtr node;
4460 if (reader == NULL)
4461 return(-1);
4462 if (reader->node == NULL)
4463 return(-1);
4464 if (reader->curnode != NULL)
4465 node = reader->curnode;
4466 else
4467 node = reader->node;
4469 if (XML_NAMESPACE_DECL == node->type)
4470 return(1);
4471 else
4472 return(0);
4476 * xmlTextReaderConstXmlVersion:
4477 * @reader: the xmlTextReaderPtr used
4479 * Determine the XML version of the document being read.
4481 * Returns a string containing the XML version of the document or NULL
4482 * in case of error. The string is deallocated with the reader.
4484 const xmlChar *
4485 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4486 xmlDocPtr doc = NULL;
4487 if (reader == NULL)
4488 return(NULL);
4489 if (reader->doc != NULL)
4490 doc = reader->doc;
4491 else if (reader->ctxt != NULL)
4492 doc = reader->ctxt->myDoc;
4493 if (doc == NULL)
4494 return(NULL);
4496 if (doc->version == NULL)
4497 return(NULL);
4498 else
4499 return(CONSTSTR(doc->version));
4503 * xmlTextReaderStandalone:
4504 * @reader: the xmlTextReaderPtr used
4506 * Determine the standalone status of the document being read.
4508 * Returns 1 if the document was declared to be standalone, 0 if it
4509 * was declared to be not standalone, or -1 if the document did not
4510 * specify its standalone status or in case of error.
4513 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4514 xmlDocPtr doc = NULL;
4515 if (reader == NULL)
4516 return(-1);
4517 if (reader->doc != NULL)
4518 doc = reader->doc;
4519 else if (reader->ctxt != NULL)
4520 doc = reader->ctxt->myDoc;
4521 if (doc == NULL)
4522 return(-1);
4524 return(doc->standalone);
4527 /************************************************************************
4529 * Error Handling Extensions *
4531 ************************************************************************/
4533 /* helper to build a xmlMalloc'ed string from a format and va_list */
4534 static char *
4535 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4536 int size = 0;
4537 int chars;
4538 char *larger;
4539 char *str = NULL;
4540 va_list aq;
4542 while (1) {
4543 VA_COPY(aq, ap);
4544 chars = vsnprintf(str, size, msg, aq);
4545 va_end(aq);
4546 if (chars < 0) {
4547 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4548 if (str)
4549 xmlFree(str);
4550 return NULL;
4552 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4553 break;
4554 if (chars < MAX_ERR_MSG_SIZE)
4555 size = chars + 1;
4556 else
4557 size = MAX_ERR_MSG_SIZE;
4558 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4559 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4560 if (str)
4561 xmlFree(str);
4562 return NULL;
4564 str = larger;
4567 return str;
4571 * xmlTextReaderLocatorLineNumber:
4572 * @locator: the xmlTextReaderLocatorPtr used
4574 * Obtain the line number for the given locator.
4576 * Returns the line number or -1 in case of error.
4579 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4580 /* we know that locator is a xmlParserCtxtPtr */
4581 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4582 int ret = -1;
4584 if (locator == NULL)
4585 return(-1);
4586 if (ctx->node != NULL) {
4587 ret = xmlGetLineNo(ctx->node);
4589 else {
4590 /* inspired from error.c */
4591 xmlParserInputPtr input;
4592 input = ctx->input;
4593 if ((input->filename == NULL) && (ctx->inputNr > 1))
4594 input = ctx->inputTab[ctx->inputNr - 2];
4595 if (input != NULL) {
4596 ret = input->line;
4598 else {
4599 ret = -1;
4603 return ret;
4607 * xmlTextReaderLocatorBaseURI:
4608 * @locator: the xmlTextReaderLocatorPtr used
4610 * Obtain the base URI for the given locator.
4612 * Returns the base URI or NULL in case of error,
4613 * if non NULL it need to be freed by the caller.
4615 xmlChar *
4616 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4617 /* we know that locator is a xmlParserCtxtPtr */
4618 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4619 xmlChar *ret = NULL;
4621 if (locator == NULL)
4622 return(NULL);
4623 if (ctx->node != NULL) {
4624 ret = xmlNodeGetBase(NULL,ctx->node);
4626 else {
4627 /* inspired from error.c */
4628 xmlParserInputPtr input;
4629 input = ctx->input;
4630 if ((input->filename == NULL) && (ctx->inputNr > 1))
4631 input = ctx->inputTab[ctx->inputNr - 2];
4632 if (input != NULL) {
4633 ret = xmlStrdup(BAD_CAST input->filename);
4635 else {
4636 ret = NULL;
4640 return ret;
4643 static void
4644 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4645 char *str)
4647 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4649 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4651 if (str != NULL) {
4652 if (reader->errorFunc)
4653 reader->errorFunc(reader->errorFuncArg, str, severity,
4654 (xmlTextReaderLocatorPtr) ctx);
4655 xmlFree(str);
4659 static void
4660 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4662 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4664 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4666 if (error && reader->sErrorFunc) {
4667 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4671 static void XMLCDECL
4672 xmlTextReaderError(void *ctxt, const char *msg, ...)
4674 va_list ap;
4676 va_start(ap, msg);
4677 xmlTextReaderGenericError(ctxt,
4678 XML_PARSER_SEVERITY_ERROR,
4679 xmlTextReaderBuildMessage(msg, ap));
4680 va_end(ap);
4684 static void XMLCDECL
4685 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4687 va_list ap;
4689 va_start(ap, msg);
4690 xmlTextReaderGenericError(ctxt,
4691 XML_PARSER_SEVERITY_WARNING,
4692 xmlTextReaderBuildMessage(msg, ap));
4693 va_end(ap);
4696 static void XMLCDECL
4697 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4699 va_list ap;
4701 int len = xmlStrlen((const xmlChar *) msg);
4703 if ((len > 1) && (msg[len - 2] != ':')) {
4705 * some callbacks only report locator information:
4706 * skip them (mimicking behaviour in error.c)
4708 va_start(ap, msg);
4709 xmlTextReaderGenericError(ctxt,
4710 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4711 xmlTextReaderBuildMessage(msg, ap));
4712 va_end(ap);
4716 static void XMLCDECL
4717 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4719 va_list ap;
4721 int len = xmlStrlen((const xmlChar *) msg);
4723 if ((len != 0) && (msg[len - 1] != ':')) {
4725 * some callbacks only report locator information:
4726 * skip them (mimicking behaviour in error.c)
4728 va_start(ap, msg);
4729 xmlTextReaderGenericError(ctxt,
4730 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4731 xmlTextReaderBuildMessage(msg, ap));
4732 va_end(ap);
4737 * xmlTextReaderSetErrorHandler:
4738 * @reader: the xmlTextReaderPtr used
4739 * @f: the callback function to call on error and warnings
4740 * @arg: a user argument to pass to the callback function
4742 * Register a callback function that will be called on error and warnings.
4744 * If @f is NULL, the default error and warning handlers are restored.
4746 void
4747 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4748 xmlTextReaderErrorFunc f, void *arg)
4750 if (f != NULL) {
4751 reader->ctxt->sax->error = xmlTextReaderError;
4752 reader->ctxt->sax->serror = NULL;
4753 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4754 reader->ctxt->sax->warning = xmlTextReaderWarning;
4755 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4756 reader->errorFunc = f;
4757 reader->sErrorFunc = NULL;
4758 reader->errorFuncArg = arg;
4759 #ifdef LIBXML_SCHEMAS_ENABLED
4760 if (reader->rngValidCtxt) {
4761 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4762 xmlTextReaderValidityErrorRelay,
4763 xmlTextReaderValidityWarningRelay,
4764 reader);
4765 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4766 reader);
4768 if (reader->xsdValidCtxt) {
4769 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4770 xmlTextReaderValidityErrorRelay,
4771 xmlTextReaderValidityWarningRelay,
4772 reader);
4773 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4774 reader);
4776 #endif
4777 } else {
4778 /* restore defaults */
4779 reader->ctxt->sax->error = xmlParserError;
4780 reader->ctxt->vctxt.error = xmlParserValidityError;
4781 reader->ctxt->sax->warning = xmlParserWarning;
4782 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4783 reader->errorFunc = NULL;
4784 reader->sErrorFunc = NULL;
4785 reader->errorFuncArg = NULL;
4786 #ifdef LIBXML_SCHEMAS_ENABLED
4787 if (reader->rngValidCtxt) {
4788 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4789 reader);
4790 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4791 reader);
4793 if (reader->xsdValidCtxt) {
4794 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4795 reader);
4796 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4797 reader);
4799 #endif
4804 * xmlTextReaderSetStructuredErrorHandler:
4805 * @reader: the xmlTextReaderPtr used
4806 * @f: the callback function to call on error and warnings
4807 * @arg: a user argument to pass to the callback function
4809 * Register a callback function that will be called on error and warnings.
4811 * If @f is NULL, the default error and warning handlers are restored.
4813 void
4814 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4815 xmlStructuredErrorFunc f, void *arg)
4817 if (f != NULL) {
4818 reader->ctxt->sax->error = NULL;
4819 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4820 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4821 reader->ctxt->sax->warning = xmlTextReaderWarning;
4822 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4823 reader->sErrorFunc = f;
4824 reader->errorFunc = NULL;
4825 reader->errorFuncArg = arg;
4826 #ifdef LIBXML_SCHEMAS_ENABLED
4827 if (reader->rngValidCtxt) {
4828 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4829 reader);
4830 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4831 xmlTextReaderValidityStructuredRelay,
4832 reader);
4834 if (reader->xsdValidCtxt) {
4835 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4836 reader);
4837 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4838 xmlTextReaderValidityStructuredRelay,
4839 reader);
4841 #endif
4842 } else {
4843 /* restore defaults */
4844 reader->ctxt->sax->error = xmlParserError;
4845 reader->ctxt->sax->serror = NULL;
4846 reader->ctxt->vctxt.error = xmlParserValidityError;
4847 reader->ctxt->sax->warning = xmlParserWarning;
4848 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4849 reader->errorFunc = NULL;
4850 reader->sErrorFunc = NULL;
4851 reader->errorFuncArg = NULL;
4852 #ifdef LIBXML_SCHEMAS_ENABLED
4853 if (reader->rngValidCtxt) {
4854 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4855 reader);
4856 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4857 reader);
4859 if (reader->xsdValidCtxt) {
4860 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4861 reader);
4862 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4863 reader);
4865 #endif
4870 * xmlTextReaderIsValid:
4871 * @reader: the xmlTextReaderPtr used
4873 * Retrieve the validity status from the parser context
4875 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4878 xmlTextReaderIsValid(xmlTextReaderPtr reader)
4880 if (reader == NULL)
4881 return (-1);
4882 #ifdef LIBXML_SCHEMAS_ENABLED
4883 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4884 return (reader->rngValidErrors == 0);
4885 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4886 return (reader->xsdValidErrors == 0);
4887 #endif
4888 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
4889 return (reader->ctxt->valid);
4890 return (0);
4894 * xmlTextReaderGetErrorHandler:
4895 * @reader: the xmlTextReaderPtr used
4896 * @f: the callback function or NULL is no callback has been registered
4897 * @arg: a user argument
4899 * Retrieve the error callback function and user argument.
4901 void
4902 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4903 xmlTextReaderErrorFunc * f, void **arg)
4905 if (f != NULL)
4906 *f = reader->errorFunc;
4907 if (arg != NULL)
4908 *arg = reader->errorFuncArg;
4910 /************************************************************************
4912 * New set (2.6.0) of simpler and more flexible APIs *
4914 ************************************************************************/
4917 * xmlTextReaderSetup:
4918 * @reader: an XML reader
4919 * @input: xmlParserInputBufferPtr used to feed the reader, will
4920 * be destroyed with it.
4921 * @URL: the base URL to use for the document
4922 * @encoding: the document encoding, or NULL
4923 * @options: a combination of xmlParserOption
4925 * Setup an XML reader with new options
4927 * Returns 0 in case of success and -1 in case of error.
4930 xmlTextReaderSetup(xmlTextReaderPtr reader,
4931 xmlParserInputBufferPtr input, const char *URL,
4932 const char *encoding, int options)
4934 if (reader == NULL) {
4935 if (input != NULL)
4936 xmlFreeParserInputBuffer(input);
4937 return (-1);
4941 * we force the generation of compact text nodes on the reader
4942 * since usr applications should never modify the tree
4944 options |= XML_PARSE_COMPACT;
4946 reader->doc = NULL;
4947 reader->entNr = 0;
4948 reader->parserFlags = options;
4949 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
4950 if ((input != NULL) && (reader->input != NULL) &&
4951 (reader->allocs & XML_TEXTREADER_INPUT)) {
4952 xmlFreeParserInputBuffer(reader->input);
4953 reader->input = NULL;
4954 reader->allocs -= XML_TEXTREADER_INPUT;
4956 if (input != NULL) {
4957 reader->input = input;
4958 reader->allocs |= XML_TEXTREADER_INPUT;
4960 if (reader->buffer == NULL)
4961 reader->buffer = xmlBufferCreateSize(100);
4962 if (reader->buffer == NULL) {
4963 xmlGenericError(xmlGenericErrorContext,
4964 "xmlTextReaderSetup : malloc failed\n");
4965 return (-1);
4967 if (reader->sax == NULL)
4968 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4969 if (reader->sax == NULL) {
4970 xmlGenericError(xmlGenericErrorContext,
4971 "xmlTextReaderSetup : malloc failed\n");
4972 return (-1);
4974 xmlSAXVersion(reader->sax, 2);
4975 reader->startElement = reader->sax->startElement;
4976 reader->sax->startElement = xmlTextReaderStartElement;
4977 reader->endElement = reader->sax->endElement;
4978 reader->sax->endElement = xmlTextReaderEndElement;
4979 #ifdef LIBXML_SAX1_ENABLED
4980 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4981 #endif /* LIBXML_SAX1_ENABLED */
4982 reader->startElementNs = reader->sax->startElementNs;
4983 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4984 reader->endElementNs = reader->sax->endElementNs;
4985 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4986 #ifdef LIBXML_SAX1_ENABLED
4987 } else {
4988 reader->startElementNs = NULL;
4989 reader->endElementNs = NULL;
4991 #endif /* LIBXML_SAX1_ENABLED */
4992 reader->characters = reader->sax->characters;
4993 reader->sax->characters = xmlTextReaderCharacters;
4994 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4995 reader->cdataBlock = reader->sax->cdataBlock;
4996 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4998 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4999 reader->node = NULL;
5000 reader->curnode = NULL;
5001 if (input != NULL) {
5002 if (reader->input->buffer->use < 4) {
5003 xmlParserInputBufferRead(input, 4);
5005 if (reader->ctxt == NULL) {
5006 if (reader->input->buffer->use >= 4) {
5007 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5008 (const char *) reader->input->buffer->content, 4, URL);
5009 reader->base = 0;
5010 reader->cur = 4;
5011 } else {
5012 reader->ctxt =
5013 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5014 reader->base = 0;
5015 reader->cur = 0;
5017 } else {
5018 xmlParserInputPtr inputStream;
5019 xmlParserInputBufferPtr buf;
5020 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5022 xmlCtxtReset(reader->ctxt);
5023 buf = xmlAllocParserInputBuffer(enc);
5024 if (buf == NULL) return(-1);
5025 inputStream = xmlNewInputStream(reader->ctxt);
5026 if (inputStream == NULL) {
5027 xmlFreeParserInputBuffer(buf);
5028 return(-1);
5031 if (URL == NULL)
5032 inputStream->filename = NULL;
5033 else
5034 inputStream->filename = (char *)
5035 xmlCanonicPath((const xmlChar *) URL);
5036 inputStream->buf = buf;
5037 inputStream->base = inputStream->buf->buffer->content;
5038 inputStream->cur = inputStream->buf->buffer->content;
5039 inputStream->end =
5040 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
5042 inputPush(reader->ctxt, inputStream);
5043 reader->cur = 0;
5045 if (reader->ctxt == NULL) {
5046 xmlGenericError(xmlGenericErrorContext,
5047 "xmlTextReaderSetup : malloc failed\n");
5048 return (-1);
5051 if (reader->dict != NULL) {
5052 if (reader->ctxt->dict != NULL) {
5053 if (reader->dict != reader->ctxt->dict) {
5054 xmlDictFree(reader->dict);
5055 reader->dict = reader->ctxt->dict;
5057 } else {
5058 reader->ctxt->dict = reader->dict;
5060 } else {
5061 if (reader->ctxt->dict == NULL)
5062 reader->ctxt->dict = xmlDictCreate();
5063 reader->dict = reader->ctxt->dict;
5065 reader->ctxt->_private = reader;
5066 reader->ctxt->linenumbers = 1;
5067 reader->ctxt->dictNames = 1;
5069 * use the parser dictionnary to allocate all elements and attributes names
5071 reader->ctxt->docdict = 1;
5072 reader->ctxt->parseMode = XML_PARSE_READER;
5074 #ifdef LIBXML_XINCLUDE_ENABLED
5075 if (reader->xincctxt != NULL) {
5076 xmlXIncludeFreeContext(reader->xincctxt);
5077 reader->xincctxt = NULL;
5079 if (options & XML_PARSE_XINCLUDE) {
5080 reader->xinclude = 1;
5081 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5082 options -= XML_PARSE_XINCLUDE;
5083 } else
5084 reader->xinclude = 0;
5085 reader->in_xinclude = 0;
5086 #endif
5087 #ifdef LIBXML_PATTERN_ENABLED
5088 if (reader->patternTab == NULL) {
5089 reader->patternNr = 0;
5090 reader->patternMax = 0;
5092 while (reader->patternNr > 0) {
5093 reader->patternNr--;
5094 if (reader->patternTab[reader->patternNr] != NULL) {
5095 xmlFreePattern(reader->patternTab[reader->patternNr]);
5096 reader->patternTab[reader->patternNr] = NULL;
5099 #endif
5101 if (options & XML_PARSE_DTDVALID)
5102 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5104 xmlCtxtUseOptions(reader->ctxt, options);
5105 if (encoding != NULL) {
5106 xmlCharEncodingHandlerPtr hdlr;
5108 hdlr = xmlFindCharEncodingHandler(encoding);
5109 if (hdlr != NULL)
5110 xmlSwitchToEncoding(reader->ctxt, hdlr);
5112 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5113 (reader->ctxt->input->filename == NULL))
5114 reader->ctxt->input->filename = (char *)
5115 xmlStrdup((const xmlChar *) URL);
5117 reader->doc = NULL;
5119 return (0);
5123 * xmlTextReaderByteConsumed:
5124 * @reader: an XML reader
5126 * This function provides the current index of the parser used
5127 * by the reader, relative to the start of the current entity.
5128 * This function actually just wraps a call to xmlBytesConsumed()
5129 * for the parser context associated with the reader.
5130 * See xmlBytesConsumed() for more information.
5132 * Returns the index in bytes from the beginning of the entity or -1
5133 * in case the index could not be computed.
5135 long
5136 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5137 if ((reader == NULL) || (reader->ctxt == NULL))
5138 return(-1);
5139 return(xmlByteConsumed(reader->ctxt));
5144 * xmlReaderWalker:
5145 * @doc: a preparsed document
5147 * Create an xmltextReader for a preparsed document.
5149 * Returns the new reader or NULL in case of error.
5151 xmlTextReaderPtr
5152 xmlReaderWalker(xmlDocPtr doc)
5154 xmlTextReaderPtr ret;
5156 if (doc == NULL)
5157 return(NULL);
5159 ret = xmlMalloc(sizeof(xmlTextReader));
5160 if (ret == NULL) {
5161 xmlGenericError(xmlGenericErrorContext,
5162 "xmlNewTextReader : malloc failed\n");
5163 return(NULL);
5165 memset(ret, 0, sizeof(xmlTextReader));
5166 ret->entNr = 0;
5167 ret->input = NULL;
5168 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5169 ret->node = NULL;
5170 ret->curnode = NULL;
5171 ret->base = 0;
5172 ret->cur = 0;
5173 ret->allocs = XML_TEXTREADER_CTXT;
5174 ret->doc = doc;
5175 ret->state = XML_TEXTREADER_START;
5176 ret->dict = xmlDictCreate();
5177 return(ret);
5181 * xmlReaderForDoc:
5182 * @cur: a pointer to a zero terminated string
5183 * @URL: the base URL to use for the document
5184 * @encoding: the document encoding, or NULL
5185 * @options: a combination of xmlParserOption
5187 * Create an xmltextReader for an XML in-memory document.
5188 * The parsing flags @options are a combination of xmlParserOption.
5190 * Returns the new reader or NULL in case of error.
5192 xmlTextReaderPtr
5193 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5194 int options)
5196 int len;
5198 if (cur == NULL)
5199 return (NULL);
5200 len = xmlStrlen(cur);
5202 return (xmlReaderForMemory
5203 ((const char *) cur, len, URL, encoding, options));
5207 * xmlReaderForFile:
5208 * @filename: a file or URL
5209 * @encoding: the document encoding, or NULL
5210 * @options: a combination of xmlParserOption
5212 * parse an XML file from the filesystem or the network.
5213 * The parsing flags @options are a combination of xmlParserOption.
5215 * Returns the new reader or NULL in case of error.
5217 xmlTextReaderPtr
5218 xmlReaderForFile(const char *filename, const char *encoding, int options)
5220 xmlTextReaderPtr reader;
5222 reader = xmlNewTextReaderFilename(filename);
5223 if (reader == NULL)
5224 return (NULL);
5225 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5226 return (reader);
5230 * xmlReaderForMemory:
5231 * @buffer: a pointer to a char array
5232 * @size: the size of the array
5233 * @URL: the base URL to use for the document
5234 * @encoding: the document encoding, or NULL
5235 * @options: a combination of xmlParserOption
5237 * Create an xmltextReader for an XML in-memory document.
5238 * The parsing flags @options are a combination of xmlParserOption.
5240 * Returns the new reader or NULL in case of error.
5242 xmlTextReaderPtr
5243 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5244 const char *encoding, int options)
5246 xmlTextReaderPtr reader;
5247 xmlParserInputBufferPtr buf;
5249 buf = xmlParserInputBufferCreateStatic(buffer, size,
5250 XML_CHAR_ENCODING_NONE);
5251 if (buf == NULL) {
5252 return (NULL);
5254 reader = xmlNewTextReader(buf, URL);
5255 if (reader == NULL) {
5256 xmlFreeParserInputBuffer(buf);
5257 return (NULL);
5259 reader->allocs |= XML_TEXTREADER_INPUT;
5260 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5261 return (reader);
5265 * xmlReaderForFd:
5266 * @fd: an open file descriptor
5267 * @URL: the base URL to use for the document
5268 * @encoding: the document encoding, or NULL
5269 * @options: a combination of xmlParserOption
5271 * Create an xmltextReader for an XML from a file descriptor.
5272 * The parsing flags @options are a combination of xmlParserOption.
5273 * NOTE that the file descriptor will not be closed when the
5274 * reader is closed or reset.
5276 * Returns the new reader or NULL in case of error.
5278 xmlTextReaderPtr
5279 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5281 xmlTextReaderPtr reader;
5282 xmlParserInputBufferPtr input;
5284 if (fd < 0)
5285 return (NULL);
5287 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5288 if (input == NULL)
5289 return (NULL);
5290 input->closecallback = NULL;
5291 reader = xmlNewTextReader(input, URL);
5292 if (reader == NULL) {
5293 xmlFreeParserInputBuffer(input);
5294 return (NULL);
5296 reader->allocs |= XML_TEXTREADER_INPUT;
5297 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5298 return (reader);
5302 * xmlReaderForIO:
5303 * @ioread: an I/O read function
5304 * @ioclose: an I/O close function
5305 * @ioctx: an I/O handler
5306 * @URL: the base URL to use for the document
5307 * @encoding: the document encoding, or NULL
5308 * @options: a combination of xmlParserOption
5310 * Create an xmltextReader for an XML document from I/O functions and source.
5311 * The parsing flags @options are a combination of xmlParserOption.
5313 * Returns the new reader or NULL in case of error.
5315 xmlTextReaderPtr
5316 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5317 void *ioctx, const char *URL, const char *encoding,
5318 int options)
5320 xmlTextReaderPtr reader;
5321 xmlParserInputBufferPtr input;
5323 if (ioread == NULL)
5324 return (NULL);
5326 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5327 XML_CHAR_ENCODING_NONE);
5328 if (input == NULL)
5329 return (NULL);
5330 reader = xmlNewTextReader(input, URL);
5331 if (reader == NULL) {
5332 xmlFreeParserInputBuffer(input);
5333 return (NULL);
5335 reader->allocs |= XML_TEXTREADER_INPUT;
5336 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5337 return (reader);
5341 * xmlReaderNewWalker:
5342 * @reader: an XML reader
5343 * @doc: a preparsed document
5345 * Setup an xmltextReader to parse a preparsed XML document.
5346 * This reuses the existing @reader xmlTextReader.
5348 * Returns 0 in case of success and -1 in case of error
5351 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5353 if (doc == NULL)
5354 return (-1);
5355 if (reader == NULL)
5356 return (-1);
5358 if (reader->input != NULL) {
5359 xmlFreeParserInputBuffer(reader->input);
5361 if (reader->ctxt != NULL) {
5362 xmlCtxtReset(reader->ctxt);
5365 reader->entNr = 0;
5366 reader->input = NULL;
5367 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5368 reader->node = NULL;
5369 reader->curnode = NULL;
5370 reader->base = 0;
5371 reader->cur = 0;
5372 reader->allocs = XML_TEXTREADER_CTXT;
5373 reader->doc = doc;
5374 reader->state = XML_TEXTREADER_START;
5375 if (reader->dict == NULL) {
5376 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5377 reader->dict = reader->ctxt->dict;
5378 else
5379 reader->dict = xmlDictCreate();
5381 return(0);
5385 * xmlReaderNewDoc:
5386 * @reader: an XML reader
5387 * @cur: a pointer to a zero terminated string
5388 * @URL: the base URL to use for the document
5389 * @encoding: the document encoding, or NULL
5390 * @options: a combination of xmlParserOption
5392 * Setup an xmltextReader to parse an XML in-memory document.
5393 * The parsing flags @options are a combination of xmlParserOption.
5394 * This reuses the existing @reader xmlTextReader.
5396 * Returns 0 in case of success and -1 in case of error
5399 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5400 const char *URL, const char *encoding, int options)
5403 int len;
5405 if (cur == NULL)
5406 return (-1);
5407 if (reader == NULL)
5408 return (-1);
5410 len = xmlStrlen(cur);
5411 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5412 URL, encoding, options));
5416 * xmlReaderNewFile:
5417 * @reader: an XML reader
5418 * @filename: a file or URL
5419 * @encoding: the document encoding, or NULL
5420 * @options: a combination of xmlParserOption
5422 * parse an XML file from the filesystem or the network.
5423 * The parsing flags @options are a combination of xmlParserOption.
5424 * This reuses the existing @reader xmlTextReader.
5426 * Returns 0 in case of success and -1 in case of error
5429 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5430 const char *encoding, int options)
5432 xmlParserInputBufferPtr input;
5434 if (filename == NULL)
5435 return (-1);
5436 if (reader == NULL)
5437 return (-1);
5439 input =
5440 xmlParserInputBufferCreateFilename(filename,
5441 XML_CHAR_ENCODING_NONE);
5442 if (input == NULL)
5443 return (-1);
5444 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5448 * xmlReaderNewMemory:
5449 * @reader: an XML reader
5450 * @buffer: a pointer to a char array
5451 * @size: the size of the array
5452 * @URL: the base URL to use for the document
5453 * @encoding: the document encoding, or NULL
5454 * @options: a combination of xmlParserOption
5456 * Setup an xmltextReader to parse an XML in-memory document.
5457 * The parsing flags @options are a combination of xmlParserOption.
5458 * This reuses the existing @reader xmlTextReader.
5460 * Returns 0 in case of success and -1 in case of error
5463 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5464 const char *URL, const char *encoding, int options)
5466 xmlParserInputBufferPtr input;
5468 if (reader == NULL)
5469 return (-1);
5470 if (buffer == NULL)
5471 return (-1);
5473 input = xmlParserInputBufferCreateStatic(buffer, size,
5474 XML_CHAR_ENCODING_NONE);
5475 if (input == NULL) {
5476 return (-1);
5478 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5482 * xmlReaderNewFd:
5483 * @reader: an XML reader
5484 * @fd: an open file descriptor
5485 * @URL: the base URL to use for the document
5486 * @encoding: the document encoding, or NULL
5487 * @options: a combination of xmlParserOption
5489 * Setup an xmltextReader to parse an XML from a file descriptor.
5490 * NOTE that the file descriptor will not be closed when the
5491 * reader is closed or reset.
5492 * The parsing flags @options are a combination of xmlParserOption.
5493 * This reuses the existing @reader xmlTextReader.
5495 * Returns 0 in case of success and -1 in case of error
5498 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5499 const char *URL, const char *encoding, int options)
5501 xmlParserInputBufferPtr input;
5503 if (fd < 0)
5504 return (-1);
5505 if (reader == NULL)
5506 return (-1);
5508 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5509 if (input == NULL)
5510 return (-1);
5511 input->closecallback = NULL;
5512 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5516 * xmlReaderNewIO:
5517 * @reader: an XML reader
5518 * @ioread: an I/O read function
5519 * @ioclose: an I/O close function
5520 * @ioctx: an I/O handler
5521 * @URL: the base URL to use for the document
5522 * @encoding: the document encoding, or NULL
5523 * @options: a combination of xmlParserOption
5525 * Setup an xmltextReader to parse an XML document from I/O functions
5526 * and source.
5527 * The parsing flags @options are a combination of xmlParserOption.
5528 * This reuses the existing @reader xmlTextReader.
5530 * Returns 0 in case of success and -1 in case of error
5533 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5534 xmlInputCloseCallback ioclose, void *ioctx,
5535 const char *URL, const char *encoding, int options)
5537 xmlParserInputBufferPtr input;
5539 if (ioread == NULL)
5540 return (-1);
5541 if (reader == NULL)
5542 return (-1);
5544 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5545 XML_CHAR_ENCODING_NONE);
5546 if (input == NULL)
5547 return (-1);
5548 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5550 /************************************************************************
5552 * Utilities *
5554 ************************************************************************/
5555 #ifdef NOT_USED_YET
5558 * xmlBase64Decode:
5559 * @in: the input buffer
5560 * @inlen: the size of the input (in), the size read from it (out)
5561 * @to: the output buffer
5562 * @tolen: the size of the output (in), the size written to (out)
5564 * Base64 decoder, reads from @in and save in @to
5565 * TODO: tell jody when this is actually exported
5567 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5568 * 2 if there wasn't enough space on the output or -1 in case of error.
5570 static int
5571 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5572 unsigned char *to, unsigned long *tolen)
5574 unsigned long incur; /* current index in in[] */
5576 unsigned long inblk; /* last block index in in[] */
5578 unsigned long outcur; /* current index in out[] */
5580 unsigned long inmax; /* size of in[] */
5582 unsigned long outmax; /* size of out[] */
5584 unsigned char cur; /* the current value read from in[] */
5586 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5588 int nbintmp; /* number of byte in intmp[] */
5590 int is_ignore; /* cur should be ignored */
5592 int is_end = 0; /* the end of the base64 was found */
5594 int retval = 1;
5596 int i;
5598 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5599 return (-1);
5601 incur = 0;
5602 inblk = 0;
5603 outcur = 0;
5604 inmax = *inlen;
5605 outmax = *tolen;
5606 nbintmp = 0;
5608 while (1) {
5609 if (incur >= inmax)
5610 break;
5611 cur = in[incur++];
5612 is_ignore = 0;
5613 if ((cur >= 'A') && (cur <= 'Z'))
5614 cur = cur - 'A';
5615 else if ((cur >= 'a') && (cur <= 'z'))
5616 cur = cur - 'a' + 26;
5617 else if ((cur >= '0') && (cur <= '9'))
5618 cur = cur - '0' + 52;
5619 else if (cur == '+')
5620 cur = 62;
5621 else if (cur == '/')
5622 cur = 63;
5623 else if (cur == '.')
5624 cur = 0;
5625 else if (cur == '=') /*no op , end of the base64 stream */
5626 is_end = 1;
5627 else {
5628 is_ignore = 1;
5629 if (nbintmp == 0)
5630 inblk = incur;
5633 if (!is_ignore) {
5634 int nbouttmp = 3;
5636 int is_break = 0;
5638 if (is_end) {
5639 if (nbintmp == 0)
5640 break;
5641 if ((nbintmp == 1) || (nbintmp == 2))
5642 nbouttmp = 1;
5643 else
5644 nbouttmp = 2;
5645 nbintmp = 3;
5646 is_break = 1;
5648 intmp[nbintmp++] = cur;
5650 * if intmp is full, push the 4byte sequence as a 3 byte
5651 * sequence out
5653 if (nbintmp == 4) {
5654 nbintmp = 0;
5655 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5656 outtmp[1] =
5657 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5658 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5659 if (outcur + 3 >= outmax) {
5660 retval = 2;
5661 break;
5664 for (i = 0; i < nbouttmp; i++)
5665 to[outcur++] = outtmp[i];
5666 inblk = incur;
5669 if (is_break) {
5670 retval = 0;
5671 break;
5676 *tolen = outcur;
5677 *inlen = inblk;
5678 return (retval);
5682 * Test routine for the xmlBase64Decode function
5684 #if 0
5686 main(int argc, char **argv)
5688 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5690 char output[100];
5692 char output2[100];
5694 char output3[100];
5696 unsigned long inlen = strlen(input);
5698 unsigned long outlen = 100;
5700 int ret;
5702 unsigned long cons, tmp, tmp2, prod;
5705 * Direct
5707 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5709 output[outlen] = 0;
5710 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5711 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5715 * output chunking
5717 cons = 0;
5718 prod = 0;
5719 while (cons < inlen) {
5720 tmp = 5;
5721 tmp2 = inlen - cons;
5723 printf("%ld %ld\n", cons, prod);
5724 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5725 cons += tmp2;
5726 prod += tmp;
5727 printf("%ld %ld\n", cons, prod);
5729 output2[outlen] = 0;
5730 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5731 prod, output2);
5734 * input chunking
5736 cons = 0;
5737 prod = 0;
5738 while (cons < inlen) {
5739 tmp = 100 - prod;
5740 tmp2 = inlen - cons;
5741 if (tmp2 > 5)
5742 tmp2 = 5;
5744 printf("%ld %ld\n", cons, prod);
5745 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5746 cons += tmp2;
5747 prod += tmp;
5748 printf("%ld %ld\n", cons, prod);
5750 output3[outlen] = 0;
5751 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5752 prod, output3);
5753 return (0);
5756 #endif
5757 #endif /* NOT_USED_YET */
5758 #define bottom_xmlreader
5759 #include "elfgcchack.h"
5760 #endif /* LIBXML_READER_ENABLED */