mscms: Fix double free on error path in EnumColorProfilesA (scan-build).
[wine.git] / libs / xml2 / xmlreader.c
blobb70c1bc96cbee2e0608452095e72ed3b631ab57b
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>
23 #include <ctype.h>
24 #include <stdlib.h>
26 #include <libxml/xmlmemory.h>
27 #include <libxml/xmlIO.h>
28 #include <libxml/xmlreader.h>
29 #include <libxml/parserInternals.h>
30 #ifdef LIBXML_SCHEMAS_ENABLED
31 #include <libxml/relaxng.h>
32 #include <libxml/xmlschemas.h>
33 #endif
34 #include <libxml/uri.h>
35 #ifdef LIBXML_XINCLUDE_ENABLED
36 #include <libxml/xinclude.h>
37 #endif
38 #ifdef LIBXML_PATTERN_ENABLED
39 #include <libxml/pattern.h>
40 #endif
42 #include "private/buf.h"
43 #include "private/tree.h"
44 #ifdef LIBXML_XINCLUDE_ENABLED
45 #include "private/xinclude.h"
46 #endif
48 #define MAX_ERR_MSG_SIZE 64000
50 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
51 /* Keeping free objects can hide memory errors. */
52 #define MAX_FREE_NODES 1
53 #else
54 #define MAX_FREE_NODES 100
55 #endif
58 * The following VA_COPY was coded following an example in
59 * the Samba project. It may not be sufficient for some
60 * esoteric implementations of va_list but (hopefully) will
61 * be sufficient for libxml2.
63 #ifndef VA_COPY
64 #ifdef HAVE_VA_COPY
65 #define VA_COPY(dest, src) va_copy(dest, src)
66 #else
67 #ifdef HAVE___VA_COPY
68 #define VA_COPY(dest,src) __va_copy(dest, src)
69 #else
70 #ifndef VA_LIST_IS_ARRAY
71 #define VA_COPY(dest,src) (dest) = (src)
72 #else
73 #include <string.h>
74 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
75 #endif
76 #endif
77 #endif
78 #endif
80 /* #define DEBUG_CALLBACKS */
81 /* #define DEBUG_READER */
83 /**
84 * TODO:
86 * macro to flag unimplemented blocks
88 #define TODO \
89 xmlGenericError(xmlGenericErrorContext, \
90 "Unimplemented block at %s:%d\n", \
91 __FILE__, __LINE__);
93 #ifdef DEBUG_READER
94 #define DUMP_READER xmlTextReaderDebug(reader);
95 #else
96 #define DUMP_READER
97 #endif
99 #define CHUNK_SIZE 512
100 /************************************************************************
102 * The parser: maps the Text Reader API on top of the existing *
103 * parsing routines building a tree *
105 ************************************************************************/
107 #define XML_TEXTREADER_INPUT 1
108 #define XML_TEXTREADER_CTXT 2
110 typedef enum {
111 XML_TEXTREADER_NONE = -1,
112 XML_TEXTREADER_START= 0,
113 XML_TEXTREADER_ELEMENT= 1,
114 XML_TEXTREADER_END= 2,
115 XML_TEXTREADER_EMPTY= 3,
116 XML_TEXTREADER_BACKTRACK= 4,
117 XML_TEXTREADER_DONE= 5,
118 XML_TEXTREADER_ERROR= 6
119 } xmlTextReaderState;
121 typedef enum {
122 XML_TEXTREADER_NOT_VALIDATE = 0,
123 XML_TEXTREADER_VALIDATE_DTD = 1,
124 XML_TEXTREADER_VALIDATE_RNG = 2,
125 XML_TEXTREADER_VALIDATE_XSD = 4
126 } xmlTextReaderValidate;
128 struct _xmlTextReader {
129 int mode; /* the parsing mode */
130 xmlDocPtr doc; /* when walking an existing doc */
131 xmlTextReaderValidate validate;/* is there any validation */
132 int allocs; /* what structure were deallocated */
133 xmlTextReaderState state;
134 xmlParserCtxtPtr ctxt; /* the parser context */
135 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
136 xmlParserInputBufferPtr input; /* the input */
137 startElementSAXFunc startElement;/* initial SAX callbacks */
138 endElementSAXFunc endElement; /* idem */
139 startElementNsSAX2Func startElementNs;/* idem */
140 endElementNsSAX2Func endElementNs; /* idem */
141 charactersSAXFunc characters;
142 cdataBlockSAXFunc cdataBlock;
143 unsigned int base; /* base of the segment in the input */
144 unsigned int cur; /* current position in the input */
145 xmlNodePtr node; /* current node */
146 xmlNodePtr curnode;/* current attribute node */
147 int depth; /* depth of the current node */
148 xmlNodePtr faketext;/* fake xmlNs chld */
149 int preserve;/* preserve the resulting document */
150 xmlBufPtr buffer; /* used to return const xmlChar * */
151 xmlDictPtr dict; /* the context dictionary */
153 /* entity stack when traversing entities content */
154 xmlNodePtr ent; /* Current Entity Ref Node */
155 int entNr; /* Depth of the entities stack */
156 int entMax; /* Max depth of the entities stack */
157 xmlNodePtr *entTab; /* array of entities */
159 /* error handling */
160 xmlTextReaderErrorFunc errorFunc; /* callback function */
161 void *errorFuncArg; /* callback function user argument */
163 #ifdef LIBXML_SCHEMAS_ENABLED
164 /* Handling of RelaxNG validation */
165 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
166 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
167 int rngPreserveCtxt; /* 1 if the context was provided by the user */
168 int rngValidErrors;/* The number of errors detected */
169 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
170 /* Handling of Schemas validation */
171 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
172 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
173 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
174 int xsdValidErrors;/* The number of errors detected */
175 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
176 #endif
177 #ifdef LIBXML_XINCLUDE_ENABLED
178 /* Handling of XInclude processing */
179 int xinclude; /* is xinclude asked for */
180 const xmlChar * xinclude_name; /* the xinclude name from dict */
181 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
182 int in_xinclude; /* counts for xinclude */
183 #endif
184 #ifdef LIBXML_PATTERN_ENABLED
185 int patternNr; /* number of preserve patterns */
186 int patternMax; /* max preserve patterns */
187 xmlPatternPtr *patternTab; /* array of preserve patterns */
188 #endif
189 int preserves; /* level of preserves */
190 int parserFlags; /* the set of options set */
191 /* Structured error handling */
192 xmlStructuredErrorFunc sErrorFunc; /* callback function */
195 #define NODE_IS_EMPTY 0x1
196 #define NODE_IS_PRESERVED 0x2
197 #define NODE_IS_SPRESERVED 0x4
200 * CONSTSTR:
202 * Macro used to return an interned string
204 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
205 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
207 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
208 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
210 /************************************************************************
212 * Our own version of the freeing routines as we recycle nodes *
214 ************************************************************************/
216 * DICT_FREE:
217 * @str: a string
219 * Free a string if it is not owned by the "dict" dictionary in the
220 * current scope
222 #define DICT_FREE(str) \
223 if ((str) && ((!dict) || \
224 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
225 xmlFree((char *)(str));
227 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
228 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
231 * xmlTextReaderFreeProp:
232 * @reader: the xmlTextReaderPtr used
233 * @cur: the node
235 * Free a node.
237 static void
238 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
239 xmlDictPtr dict;
241 if ((reader != NULL) && (reader->ctxt != NULL))
242 dict = reader->ctxt->dict;
243 else
244 dict = NULL;
245 if (cur == NULL) return;
247 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
248 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
250 if (cur->children != NULL)
251 xmlTextReaderFreeNodeList(reader, cur->children);
253 DICT_FREE(cur->name);
254 if ((reader != NULL) && (reader->ctxt != NULL) &&
255 (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
256 cur->next = reader->ctxt->freeAttrs;
257 reader->ctxt->freeAttrs = cur;
258 reader->ctxt->freeAttrsNr++;
259 } else {
260 xmlFree(cur);
265 * xmlTextReaderFreePropList:
266 * @reader: the xmlTextReaderPtr used
267 * @cur: the first property in the list
269 * Free a property and all its siblings, all the children are freed too.
271 static void
272 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
273 xmlAttrPtr next;
275 while (cur != NULL) {
276 next = cur->next;
277 xmlTextReaderFreeProp(reader, cur);
278 cur = next;
283 * xmlTextReaderFreeNodeList:
284 * @reader: the xmlTextReaderPtr used
285 * @cur: the first node in the list
287 * Free a node and all its siblings, this is a recursive behaviour, all
288 * the children are freed too.
290 static void
291 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
292 xmlNodePtr next;
293 xmlNodePtr parent;
294 xmlDictPtr dict;
295 size_t depth = 0;
297 if ((reader != NULL) && (reader->ctxt != NULL))
298 dict = reader->ctxt->dict;
299 else
300 dict = NULL;
301 if (cur == NULL) return;
302 if (cur->type == XML_NAMESPACE_DECL) {
303 xmlFreeNsList((xmlNsPtr) cur);
304 return;
306 if ((cur->type == XML_DOCUMENT_NODE) ||
307 (cur->type == XML_HTML_DOCUMENT_NODE)) {
308 xmlFreeDoc((xmlDocPtr) cur);
309 return;
311 while (1) {
312 while ((cur->type != XML_DTD_NODE) &&
313 (cur->type != XML_ENTITY_REF_NODE) &&
314 (cur->children != NULL) &&
315 (cur->children->parent == cur)) {
316 cur = cur->children;
317 depth += 1;
320 next = cur->next;
321 parent = cur->parent;
323 /* unroll to speed up freeing the document */
324 if (cur->type != XML_DTD_NODE) {
326 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
327 xmlDeregisterNodeDefaultValue(cur);
329 if (((cur->type == XML_ELEMENT_NODE) ||
330 (cur->type == XML_XINCLUDE_START) ||
331 (cur->type == XML_XINCLUDE_END)) &&
332 (cur->properties != NULL))
333 xmlTextReaderFreePropList(reader, cur->properties);
334 if ((cur->content != (xmlChar *) &(cur->properties)) &&
335 (cur->type != XML_ELEMENT_NODE) &&
336 (cur->type != XML_XINCLUDE_START) &&
337 (cur->type != XML_XINCLUDE_END) &&
338 (cur->type != XML_ENTITY_REF_NODE)) {
339 DICT_FREE(cur->content);
341 if (((cur->type == XML_ELEMENT_NODE) ||
342 (cur->type == XML_XINCLUDE_START) ||
343 (cur->type == XML_XINCLUDE_END)) &&
344 (cur->nsDef != NULL))
345 xmlFreeNsList(cur->nsDef);
348 * we don't free element names here they are interned now
350 if ((cur->type != XML_TEXT_NODE) &&
351 (cur->type != XML_COMMENT_NODE))
352 DICT_FREE(cur->name);
353 if (((cur->type == XML_ELEMENT_NODE) ||
354 (cur->type == XML_TEXT_NODE)) &&
355 (reader != NULL) && (reader->ctxt != NULL) &&
356 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
357 cur->next = reader->ctxt->freeElems;
358 reader->ctxt->freeElems = cur;
359 reader->ctxt->freeElemsNr++;
360 } else {
361 xmlFree(cur);
365 if (next != NULL) {
366 cur = next;
367 } else {
368 if ((depth == 0) || (parent == NULL))
369 break;
370 depth -= 1;
371 cur = parent;
372 cur->children = NULL;
378 * xmlTextReaderFreeNode:
379 * @reader: the xmlTextReaderPtr used
380 * @cur: the node
382 * Free a node, this is a recursive behaviour, all the children are freed too.
383 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
385 static void
386 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
387 xmlDictPtr dict;
389 if ((reader != NULL) && (reader->ctxt != NULL))
390 dict = reader->ctxt->dict;
391 else
392 dict = NULL;
393 if (cur->type == XML_DTD_NODE) {
394 xmlFreeDtd((xmlDtdPtr) cur);
395 return;
397 if (cur->type == XML_NAMESPACE_DECL) {
398 xmlFreeNs((xmlNsPtr) cur);
399 return;
401 if (cur->type == XML_ATTRIBUTE_NODE) {
402 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
403 return;
406 if ((cur->children != NULL) &&
407 (cur->type != XML_ENTITY_REF_NODE)) {
408 if (cur->children->parent == cur)
409 xmlTextReaderFreeNodeList(reader, cur->children);
410 cur->children = NULL;
413 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
414 xmlDeregisterNodeDefaultValue(cur);
416 if (((cur->type == XML_ELEMENT_NODE) ||
417 (cur->type == XML_XINCLUDE_START) ||
418 (cur->type == XML_XINCLUDE_END)) &&
419 (cur->properties != NULL))
420 xmlTextReaderFreePropList(reader, cur->properties);
421 if ((cur->content != (xmlChar *) &(cur->properties)) &&
422 (cur->type != XML_ELEMENT_NODE) &&
423 (cur->type != XML_XINCLUDE_START) &&
424 (cur->type != XML_XINCLUDE_END) &&
425 (cur->type != XML_ENTITY_REF_NODE)) {
426 DICT_FREE(cur->content);
428 if (((cur->type == XML_ELEMENT_NODE) ||
429 (cur->type == XML_XINCLUDE_START) ||
430 (cur->type == XML_XINCLUDE_END)) &&
431 (cur->nsDef != NULL))
432 xmlFreeNsList(cur->nsDef);
435 * we don't free names here they are interned now
437 if ((cur->type != XML_TEXT_NODE) &&
438 (cur->type != XML_COMMENT_NODE))
439 DICT_FREE(cur->name);
441 if (((cur->type == XML_ELEMENT_NODE) ||
442 (cur->type == XML_TEXT_NODE)) &&
443 (reader != NULL) && (reader->ctxt != NULL) &&
444 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
445 cur->next = reader->ctxt->freeElems;
446 reader->ctxt->freeElems = cur;
447 reader->ctxt->freeElemsNr++;
448 } else {
449 xmlFree(cur);
454 * xmlTextReaderFreeDoc:
455 * @reader: the xmlTextReaderPtr used
456 * @cur: pointer to the document
458 * Free up all the structures used by a document, tree included.
460 static void
461 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
462 xmlDtdPtr extSubset, intSubset;
464 if (cur == NULL) return;
466 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
467 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
470 * Do this before freeing the children list to avoid ID lookups
472 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
473 cur->ids = NULL;
474 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
475 cur->refs = NULL;
476 extSubset = cur->extSubset;
477 intSubset = cur->intSubset;
478 if (intSubset == extSubset)
479 extSubset = NULL;
480 if (extSubset != NULL) {
481 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
482 cur->extSubset = NULL;
483 xmlFreeDtd(extSubset);
485 if (intSubset != NULL) {
486 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
487 cur->intSubset = NULL;
488 xmlFreeDtd(intSubset);
491 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
493 if (cur->version != NULL) xmlFree((char *) cur->version);
494 if (cur->name != NULL) xmlFree((char *) cur->name);
495 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
496 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
497 if (cur->URL != NULL) xmlFree((char *) cur->URL);
498 if (cur->dict != NULL) xmlDictFree(cur->dict);
500 xmlFree(cur);
503 /************************************************************************
505 * The reader core parser *
507 ************************************************************************/
508 #ifdef DEBUG_READER
509 static void
510 xmlTextReaderDebug(xmlTextReaderPtr reader) {
511 if ((reader == NULL) || (reader->ctxt == NULL)) {
512 fprintf(stderr, "xmlTextReader NULL\n");
513 return;
515 fprintf(stderr, "xmlTextReader: state %d depth %d ",
516 reader->state, reader->depth);
517 if (reader->node == NULL) {
518 fprintf(stderr, "node = NULL\n");
519 } else {
520 fprintf(stderr, "node %s\n", reader->node->name);
522 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
523 reader->base, reader->cur, reader->ctxt->nodeNr);
524 if (reader->input->buffer == NULL) {
525 fprintf(stderr, "buffer is NULL\n");
526 } else {
527 #ifdef LIBXML_DEBUG_ENABLED
528 xmlDebugDumpString(stderr,
529 &reader->input->buffer->content[reader->cur]);
530 #endif
531 fprintf(stderr, "\n");
534 #endif
537 * xmlTextReaderEntPush:
538 * @reader: the xmlTextReaderPtr used
539 * @value: the entity reference node
541 * Pushes a new entity reference node on top of the entities stack
543 * Returns -1 in case of error, the index in the stack otherwise
545 static int
546 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
548 if (reader->entNr >= reader->entMax) {
549 size_t newSize = reader->entMax == 0 ? 10 : reader->entMax * 2;
550 xmlNodePtr *tmp;
552 tmp = (xmlNodePtr *) xmlRealloc(reader->entTab,
553 newSize * sizeof(*tmp));
554 if (tmp == NULL) {
555 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
556 return (-1);
558 reader->entTab = tmp;
559 reader->entMax = newSize;
561 reader->entTab[reader->entNr] = value;
562 reader->ent = value;
563 return (reader->entNr++);
567 * xmlTextReaderEntPop:
568 * @reader: the xmlTextReaderPtr used
570 * Pops the top element entity from the entities stack
572 * Returns the entity just removed
574 static xmlNodePtr
575 xmlTextReaderEntPop(xmlTextReaderPtr reader)
577 xmlNodePtr ret;
579 if (reader->entNr <= 0)
580 return (NULL);
581 reader->entNr--;
582 if (reader->entNr > 0)
583 reader->ent = reader->entTab[reader->entNr - 1];
584 else
585 reader->ent = NULL;
586 ret = reader->entTab[reader->entNr];
587 reader->entTab[reader->entNr] = NULL;
588 return (ret);
592 * xmlTextReaderStartElement:
593 * @ctx: the user data (XML parser context)
594 * @fullname: The element name, including namespace prefix
595 * @atts: An array of name/value attributes pairs, NULL terminated
597 * called when an opening tag has been processed.
599 static void
600 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
601 const xmlChar **atts) {
602 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
603 xmlTextReaderPtr reader = ctxt->_private;
605 #ifdef DEBUG_CALLBACKS
606 printf("xmlTextReaderStartElement(%s)\n", fullname);
607 #endif
608 if ((reader != NULL) && (reader->startElement != NULL)) {
609 reader->startElement(ctx, fullname, atts);
610 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
611 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
612 (ctxt->input->cur[1] == '>'))
613 ctxt->node->extra = NODE_IS_EMPTY;
615 if (reader != NULL)
616 reader->state = XML_TEXTREADER_ELEMENT;
620 * xmlTextReaderEndElement:
621 * @ctx: the user data (XML parser context)
622 * @fullname: The element name, including namespace prefix
624 * called when an ending tag has been processed.
626 static void
627 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
628 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
629 xmlTextReaderPtr reader = ctxt->_private;
631 #ifdef DEBUG_CALLBACKS
632 printf("xmlTextReaderEndElement(%s)\n", fullname);
633 #endif
634 if ((reader != NULL) && (reader->endElement != NULL)) {
635 reader->endElement(ctx, fullname);
640 * xmlTextReaderStartElementNs:
641 * @ctx: the user data (XML parser context)
642 * @localname: the local name of the element
643 * @prefix: the element namespace prefix if available
644 * @URI: the element namespace name if available
645 * @nb_namespaces: number of namespace definitions on that node
646 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
647 * @nb_attributes: the number of attributes on that node
648 * nb_defaulted: the number of defaulted attributes.
649 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
650 * attribute values.
652 * called when an opening tag has been processed.
654 static void
655 xmlTextReaderStartElementNs(void *ctx,
656 const xmlChar *localname,
657 const xmlChar *prefix,
658 const xmlChar *URI,
659 int nb_namespaces,
660 const xmlChar **namespaces,
661 int nb_attributes,
662 int nb_defaulted,
663 const xmlChar **attributes)
665 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
666 xmlTextReaderPtr reader = ctxt->_private;
668 #ifdef DEBUG_CALLBACKS
669 printf("xmlTextReaderStartElementNs(%s)\n", localname);
670 #endif
671 if ((reader != NULL) && (reader->startElementNs != NULL)) {
672 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
673 namespaces, nb_attributes, nb_defaulted,
674 attributes);
675 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
676 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
677 (ctxt->input->cur[1] == '>'))
678 ctxt->node->extra = NODE_IS_EMPTY;
680 if (reader != NULL)
681 reader->state = XML_TEXTREADER_ELEMENT;
685 * xmlTextReaderEndElementNs:
686 * @ctx: the user data (XML parser context)
687 * @localname: the local name of the element
688 * @prefix: the element namespace prefix if available
689 * @URI: the element namespace name if available
691 * called when an ending tag has been processed.
693 static void
694 xmlTextReaderEndElementNs(void *ctx,
695 const xmlChar * localname,
696 const xmlChar * prefix,
697 const xmlChar * URI)
699 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
700 xmlTextReaderPtr reader = ctxt->_private;
702 #ifdef DEBUG_CALLBACKS
703 printf("xmlTextReaderEndElementNs(%s)\n", localname);
704 #endif
705 if ((reader != NULL) && (reader->endElementNs != NULL)) {
706 reader->endElementNs(ctx, localname, prefix, URI);
712 * xmlTextReaderCharacters:
713 * @ctx: the user data (XML parser context)
714 * @ch: a xmlChar string
715 * @len: the number of xmlChar
717 * receiving some chars from the parser.
719 static void
720 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
722 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
723 xmlTextReaderPtr reader = ctxt->_private;
725 #ifdef DEBUG_CALLBACKS
726 printf("xmlTextReaderCharacters()\n");
727 #endif
728 if ((reader != NULL) && (reader->characters != NULL)) {
729 reader->characters(ctx, ch, len);
734 * xmlTextReaderCDataBlock:
735 * @ctx: the user data (XML parser context)
736 * @value: The pcdata content
737 * @len: the block length
739 * called when a pcdata block has been parsed
741 static void
742 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
744 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
745 xmlTextReaderPtr reader = ctxt->_private;
747 #ifdef DEBUG_CALLBACKS
748 printf("xmlTextReaderCDataBlock()\n");
749 #endif
750 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
751 reader->cdataBlock(ctx, ch, len);
756 * xmlTextReaderPushData:
757 * @reader: the xmlTextReaderPtr used
759 * Push data down the progressive parser until a significant callback
760 * got raised.
762 * Returns -1 in case of failure, 0 otherwise
764 static int
765 xmlTextReaderPushData(xmlTextReaderPtr reader) {
766 xmlBufPtr inbuf;
767 int val, s;
768 xmlTextReaderState oldstate;
770 if ((reader->input == NULL) || (reader->input->buffer == NULL))
771 return(-1);
773 oldstate = reader->state;
774 reader->state = XML_TEXTREADER_NONE;
775 inbuf = reader->input->buffer;
777 while (reader->state == XML_TEXTREADER_NONE) {
778 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
780 * Refill the buffer unless we are at the end of the stream
782 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
783 val = xmlParserInputBufferRead(reader->input, 4096);
784 if ((val == 0) &&
785 (reader->input->readcallback == NULL)) {
786 if (xmlBufUse(inbuf) == reader->cur) {
787 reader->mode = XML_TEXTREADER_MODE_EOF;
788 reader->state = oldstate;
790 } else if (val < 0) {
791 reader->mode = XML_TEXTREADER_MODE_EOF;
792 reader->state = oldstate;
793 if ((oldstate != XML_TEXTREADER_START) ||
794 (reader->ctxt->myDoc != NULL))
795 return(val);
796 } else if (val == 0) {
797 /* mark the end of the stream and process the remains */
798 reader->mode = XML_TEXTREADER_MODE_EOF;
799 break;
802 } else
803 break;
806 * parse by block of CHUNK_SIZE bytes, various tests show that
807 * it's the best tradeoff at least on a 1.2GH Duron
809 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
810 val = xmlParseChunk(reader->ctxt,
811 (const char *) xmlBufContent(inbuf) + reader->cur,
812 CHUNK_SIZE, 0);
813 reader->cur += CHUNK_SIZE;
814 if (val != 0)
815 reader->ctxt->wellFormed = 0;
816 if (reader->ctxt->wellFormed == 0)
817 break;
818 } else {
819 s = xmlBufUse(inbuf) - reader->cur;
820 val = xmlParseChunk(reader->ctxt,
821 (const char *) xmlBufContent(inbuf) + reader->cur,
822 s, 0);
823 reader->cur += s;
824 if (val != 0)
825 reader->ctxt->wellFormed = 0;
826 break;
831 * Discard the consumed input when needed and possible
833 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
834 if (reader->input->readcallback != NULL) {
835 if ((reader->cur >= 4096) &&
836 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
837 val = xmlBufShrink(inbuf, reader->cur);
838 if (val >= 0) {
839 reader->cur -= val;
846 * At the end of the stream signal that the work is done to the Push
847 * parser.
849 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
850 if (reader->state != XML_TEXTREADER_DONE) {
851 s = xmlBufUse(inbuf) - reader->cur;
852 val = xmlParseChunk(reader->ctxt,
853 (const char *) xmlBufContent(inbuf) + reader->cur,
854 s, 1);
855 reader->cur = xmlBufUse(inbuf);
856 reader->state = XML_TEXTREADER_DONE;
857 if (val != 0) {
858 if (reader->ctxt->wellFormed)
859 reader->ctxt->wellFormed = 0;
860 else
861 return(-1);
865 reader->state = oldstate;
866 if (reader->ctxt->wellFormed == 0) {
867 reader->mode = XML_TEXTREADER_MODE_EOF;
868 return(-1);
871 return(0);
874 #ifdef LIBXML_REGEXP_ENABLED
876 * xmlTextReaderValidatePush:
877 * @reader: the xmlTextReaderPtr used
879 * Push the current node for validation
881 static void
882 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
883 xmlNodePtr node = reader->node;
885 #ifdef LIBXML_VALID_ENABLED
886 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
887 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
888 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
889 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
890 reader->ctxt->myDoc, node, node->name);
891 } else {
892 /* TODO use the BuildQName interface */
893 xmlChar *qname;
895 qname = xmlStrdup(node->ns->prefix);
896 qname = xmlStrcat(qname, BAD_CAST ":");
897 qname = xmlStrcat(qname, node->name);
898 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
899 reader->ctxt->myDoc, node, qname);
900 if (qname != NULL)
901 xmlFree(qname);
904 #endif /* LIBXML_VALID_ENABLED */
905 #ifdef LIBXML_SCHEMAS_ENABLED
906 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
907 (reader->rngValidCtxt != NULL)) {
908 int ret;
910 if (reader->rngFullNode != NULL) return;
911 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
912 reader->ctxt->myDoc,
913 node);
914 if (ret == 0) {
916 * this element requires a full tree
918 node = xmlTextReaderExpand(reader);
919 if (node == NULL) {
920 ret = -1;
921 } else {
922 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
923 reader->ctxt->myDoc,
924 node);
925 reader->rngFullNode = node;
928 if (ret != 1)
929 reader->rngValidErrors++;
931 #endif
935 * xmlTextReaderValidateCData:
936 * @reader: the xmlTextReaderPtr used
937 * @data: pointer to the CData
938 * @len: length of the CData block in bytes.
940 * Push some CData for validation
942 static void
943 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
944 const xmlChar *data, int len) {
945 #ifdef LIBXML_VALID_ENABLED
946 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
947 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
948 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
949 data, len);
951 #endif /* LIBXML_VALID_ENABLED */
952 #ifdef LIBXML_SCHEMAS_ENABLED
953 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
954 (reader->rngValidCtxt != NULL)) {
955 int ret;
957 if (reader->rngFullNode != NULL) return;
958 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
959 if (ret != 1)
960 reader->rngValidErrors++;
962 #endif
966 * xmlTextReaderValidatePop:
967 * @reader: the xmlTextReaderPtr used
969 * Pop the current node from validation
971 static void
972 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
973 xmlNodePtr node = reader->node;
975 #ifdef LIBXML_VALID_ENABLED
976 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
977 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
978 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
979 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
980 reader->ctxt->myDoc, node, node->name);
981 } else {
982 /* TODO use the BuildQName interface */
983 xmlChar *qname;
985 qname = xmlStrdup(node->ns->prefix);
986 qname = xmlStrcat(qname, BAD_CAST ":");
987 qname = xmlStrcat(qname, node->name);
988 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
989 reader->ctxt->myDoc, node, qname);
990 if (qname != NULL)
991 xmlFree(qname);
994 #endif /* LIBXML_VALID_ENABLED */
995 #ifdef LIBXML_SCHEMAS_ENABLED
996 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
997 (reader->rngValidCtxt != NULL)) {
998 int ret;
1000 if (reader->rngFullNode != NULL) {
1001 if (node == reader->rngFullNode)
1002 reader->rngFullNode = NULL;
1003 return;
1005 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1006 reader->ctxt->myDoc,
1007 node);
1008 if (ret != 1)
1009 reader->rngValidErrors++;
1011 #endif
1015 * xmlTextReaderValidateEntity:
1016 * @reader: the xmlTextReaderPtr used
1018 * Handle the validation when an entity reference is encountered and
1019 * entity substitution is not activated. As a result the parser interface
1020 * must walk through the entity and do the validation calls
1022 static void
1023 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1024 xmlNodePtr oldnode = reader->node;
1025 xmlNodePtr node = reader->node;
1027 do {
1028 if (node->type == XML_ENTITY_REF_NODE) {
1029 if ((node->children != NULL) &&
1030 (node->children->type == XML_ENTITY_DECL) &&
1031 (node->children->children != NULL)) {
1032 if (xmlTextReaderEntPush(reader, node) < 0) {
1033 if (node == oldnode)
1034 break;
1035 goto skip_children;
1037 node = node->children->children;
1038 continue;
1039 } else {
1041 * The error has probably been raised already.
1043 if (node == oldnode)
1044 break;
1045 goto skip_children;
1047 #ifdef LIBXML_REGEXP_ENABLED
1048 } else if (node->type == XML_ELEMENT_NODE) {
1049 reader->node = node;
1050 xmlTextReaderValidatePush(reader);
1051 } else if ((node->type == XML_TEXT_NODE) ||
1052 (node->type == XML_CDATA_SECTION_NODE)) {
1053 xmlTextReaderValidateCData(reader, node->content,
1054 xmlStrlen(node->content));
1055 #endif
1059 * go to next node
1061 if (node->children != NULL) {
1062 node = node->children;
1063 continue;
1064 } else if (node->type == XML_ELEMENT_NODE) {
1065 xmlTextReaderValidatePop(reader);
1067 skip_children:
1068 if (node->next != NULL) {
1069 node = node->next;
1070 continue;
1072 do {
1073 node = node->parent;
1074 if (node->type == XML_ELEMENT_NODE) {
1075 xmlNodePtr tmp;
1076 if (reader->entNr == 0) {
1077 while ((tmp = node->last) != NULL) {
1078 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1079 xmlUnlinkNode(tmp);
1080 xmlTextReaderFreeNode(reader, tmp);
1081 } else
1082 break;
1085 reader->node = node;
1086 xmlTextReaderValidatePop(reader);
1088 if ((node->type == XML_ENTITY_DECL) &&
1089 (reader->ent != NULL) && (reader->ent->children == node)) {
1090 node = xmlTextReaderEntPop(reader);
1092 if (node == oldnode)
1093 break;
1094 if (node->next != NULL) {
1095 node = node->next;
1096 break;
1098 } while ((node != NULL) && (node != oldnode));
1099 } while ((node != NULL) && (node != oldnode));
1100 reader->node = oldnode;
1102 #endif /* LIBXML_REGEXP_ENABLED */
1106 * xmlTextReaderGetSuccessor:
1107 * @cur: the current node
1109 * Get the successor of a node if available.
1111 * Returns the successor node or NULL
1113 static xmlNodePtr
1114 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1115 if (cur == NULL) return(NULL) ; /* ERROR */
1116 if (cur->next != NULL) return(cur->next) ;
1117 do {
1118 cur = cur->parent;
1119 if (cur == NULL) break;
1120 if (cur->next != NULL) return(cur->next);
1121 } while (cur != NULL);
1122 return(cur);
1126 * xmlTextReaderDoExpand:
1127 * @reader: the xmlTextReaderPtr used
1129 * Makes sure that the current node is fully read as well as all its
1130 * descendant. It means the full DOM subtree must be available at the
1131 * end of the call.
1133 * Returns 1 if the node was expanded successfully, 0 if there is no more
1134 * nodes to read, or -1 in case of error
1136 static int
1137 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1138 int val;
1140 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1141 return(-1);
1142 do {
1143 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1145 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1146 return(1);
1147 if (reader->ctxt->nodeNr < reader->depth)
1148 return(1);
1149 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1150 return(1);
1151 val = xmlTextReaderPushData(reader);
1152 if (val < 0){
1153 reader->mode = XML_TEXTREADER_MODE_ERROR;
1154 return(-1);
1156 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1157 return(1);
1161 * xmlTextReaderCollectSiblings:
1162 * @node: the first child
1164 * Traverse depth-first through all sibling nodes and their children
1165 * nodes and concatenate their content. This is an auxiliary function
1166 * to xmlTextReaderReadString.
1168 * Returns a string containing the content, or NULL in case of error.
1170 static xmlChar *
1171 xmlTextReaderCollectSiblings(xmlNodePtr node)
1173 xmlBufferPtr buffer;
1174 xmlChar *ret;
1176 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1177 return(NULL);
1179 buffer = xmlBufferCreate();
1180 if (buffer == NULL)
1181 return NULL;
1182 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
1184 for ( ; node != NULL; node = node->next) {
1185 switch (node->type) {
1186 case XML_TEXT_NODE:
1187 case XML_CDATA_SECTION_NODE:
1188 xmlBufferCat(buffer, node->content);
1189 break;
1190 case XML_ELEMENT_NODE: {
1191 xmlChar *tmp;
1193 tmp = xmlTextReaderCollectSiblings(node->children);
1194 xmlBufferCat(buffer, tmp);
1195 xmlFree(tmp);
1196 break;
1198 default:
1199 break;
1202 ret = buffer->content;
1203 buffer->content = NULL;
1204 xmlBufferFree(buffer);
1205 return(ret);
1209 * xmlTextReaderRead:
1210 * @reader: the xmlTextReaderPtr used
1212 * Moves the position of the current instance to the next node in
1213 * the stream, exposing its properties.
1215 * Returns 1 if the node was read successfully, 0 if there is no more
1216 * nodes to read, or -1 in case of error
1219 xmlTextReaderRead(xmlTextReaderPtr reader) {
1220 int val, olddepth = 0;
1221 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1222 xmlNodePtr oldnode = NULL;
1225 if (reader == NULL)
1226 return(-1);
1227 reader->curnode = NULL;
1228 if (reader->doc != NULL)
1229 return(xmlTextReaderReadTree(reader));
1230 if (reader->ctxt == NULL)
1231 return(-1);
1233 #ifdef DEBUG_READER
1234 fprintf(stderr, "\nREAD ");
1235 DUMP_READER
1236 #endif
1237 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1238 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1240 * Initial state
1242 do {
1243 val = xmlTextReaderPushData(reader);
1244 if (val < 0){
1245 reader->mode = XML_TEXTREADER_MODE_ERROR;
1246 reader->state = XML_TEXTREADER_ERROR;
1247 return(-1);
1249 } while ((reader->ctxt->node == NULL) &&
1250 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1251 (reader->state != XML_TEXTREADER_DONE)));
1252 if (reader->ctxt->node == NULL) {
1253 if (reader->ctxt->myDoc != NULL) {
1254 reader->node = reader->ctxt->myDoc->children;
1256 if (reader->node == NULL){
1257 reader->mode = XML_TEXTREADER_MODE_ERROR;
1258 reader->state = XML_TEXTREADER_ERROR;
1259 return(-1);
1261 reader->state = XML_TEXTREADER_ELEMENT;
1262 } else {
1263 if (reader->ctxt->myDoc != NULL) {
1264 reader->node = reader->ctxt->myDoc->children;
1266 if (reader->node == NULL)
1267 reader->node = reader->ctxt->nodeTab[0];
1268 reader->state = XML_TEXTREADER_ELEMENT;
1270 reader->depth = 0;
1271 reader->ctxt->parseMode = XML_PARSE_READER;
1272 goto node_found;
1274 oldstate = reader->state;
1275 olddepth = reader->ctxt->nodeNr;
1276 oldnode = reader->node;
1278 get_next_node:
1279 if (reader->node == NULL) {
1280 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1281 return(0);
1282 else
1283 return(-1);
1287 * If we are not backtracking on ancestors or examined nodes,
1288 * that the parser didn't finished or that we aren't at the end
1289 * of stream, continue processing.
1291 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1292 (reader->ctxt->nodeNr == olddepth) &&
1293 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1294 (reader->node->children == NULL) ||
1295 (reader->node->type == XML_ENTITY_REF_NODE) ||
1296 ((reader->node->children != NULL) &&
1297 (reader->node->children->type == XML_TEXT_NODE) &&
1298 (reader->node->children->next == NULL)) ||
1299 (reader->node->type == XML_DTD_NODE) ||
1300 (reader->node->type == XML_DOCUMENT_NODE) ||
1301 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1302 ((reader->ctxt->node == NULL) ||
1303 (reader->ctxt->node == reader->node) ||
1304 (reader->ctxt->node == reader->node->parent)) &&
1305 (reader->ctxt->instate != XML_PARSER_EOF)) {
1306 val = xmlTextReaderPushData(reader);
1307 if (val < 0){
1308 reader->mode = XML_TEXTREADER_MODE_ERROR;
1309 reader->state = XML_TEXTREADER_ERROR;
1310 return(-1);
1312 if (reader->node == NULL)
1313 goto node_end;
1315 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1316 if ((reader->node->children != NULL) &&
1317 (reader->node->type != XML_ENTITY_REF_NODE) &&
1318 (reader->node->type != XML_XINCLUDE_START) &&
1319 (reader->node->type != XML_DTD_NODE)) {
1320 reader->node = reader->node->children;
1321 reader->depth++;
1322 reader->state = XML_TEXTREADER_ELEMENT;
1323 goto node_found;
1326 if (reader->node->next != NULL) {
1327 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1328 (reader->node->type == XML_ELEMENT_NODE) &&
1329 (reader->node->children == NULL) &&
1330 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1331 #ifdef LIBXML_XINCLUDE_ENABLED
1332 && (reader->in_xinclude <= 0)
1333 #endif
1335 reader->state = XML_TEXTREADER_END;
1336 goto node_found;
1338 #ifdef LIBXML_REGEXP_ENABLED
1339 if ((reader->validate) &&
1340 (reader->node->type == XML_ELEMENT_NODE))
1341 xmlTextReaderValidatePop(reader);
1342 #endif /* LIBXML_REGEXP_ENABLED */
1343 if ((reader->preserves > 0) &&
1344 (reader->node->extra & NODE_IS_SPRESERVED))
1345 reader->preserves--;
1346 reader->node = reader->node->next;
1347 reader->state = XML_TEXTREADER_ELEMENT;
1350 * Cleanup of the old node
1352 if ((reader->preserves == 0) &&
1353 #ifdef LIBXML_XINCLUDE_ENABLED
1354 (reader->in_xinclude == 0) &&
1355 #endif
1356 (reader->entNr == 0) &&
1357 (reader->node->prev != NULL) &&
1358 (reader->node->prev->type != XML_DTD_NODE)) {
1359 xmlNodePtr tmp = reader->node->prev;
1360 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1361 if (oldnode == tmp)
1362 oldnode = NULL;
1363 xmlUnlinkNode(tmp);
1364 xmlTextReaderFreeNode(reader, tmp);
1368 goto node_found;
1370 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1371 (reader->node->type == XML_ELEMENT_NODE) &&
1372 (reader->node->children == NULL) &&
1373 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1374 reader->state = XML_TEXTREADER_END;
1375 goto node_found;
1377 #ifdef LIBXML_REGEXP_ENABLED
1378 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1379 xmlTextReaderValidatePop(reader);
1380 #endif /* LIBXML_REGEXP_ENABLED */
1381 if ((reader->preserves > 0) &&
1382 (reader->node->extra & NODE_IS_SPRESERVED))
1383 reader->preserves--;
1384 reader->node = reader->node->parent;
1385 if ((reader->node == NULL) ||
1386 (reader->node->type == XML_DOCUMENT_NODE) ||
1387 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1388 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1389 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1390 reader->state = XML_TEXTREADER_DONE;
1391 if (val != 0)
1392 return(-1);
1394 reader->node = NULL;
1395 reader->depth = -1;
1398 * Cleanup of the old node
1400 if ((oldnode != NULL) && (reader->preserves == 0) &&
1401 #ifdef LIBXML_XINCLUDE_ENABLED
1402 (reader->in_xinclude == 0) &&
1403 #endif
1404 (reader->entNr == 0) &&
1405 (oldnode->type != XML_DTD_NODE) &&
1406 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1407 xmlUnlinkNode(oldnode);
1408 xmlTextReaderFreeNode(reader, oldnode);
1411 goto node_end;
1413 if ((reader->preserves == 0) &&
1414 #ifdef LIBXML_XINCLUDE_ENABLED
1415 (reader->in_xinclude == 0) &&
1416 #endif
1417 (reader->entNr == 0) &&
1418 (reader->node->last != NULL) &&
1419 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1420 xmlNodePtr tmp = reader->node->last;
1421 xmlUnlinkNode(tmp);
1422 xmlTextReaderFreeNode(reader, tmp);
1424 reader->depth--;
1425 reader->state = XML_TEXTREADER_BACKTRACK;
1427 node_found:
1428 DUMP_READER
1431 * If we are in the middle of a piece of CDATA make sure it's finished
1433 if ((reader->node != NULL) &&
1434 (reader->node->next == NULL) &&
1435 ((reader->node->type == XML_TEXT_NODE) ||
1436 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1437 if (xmlTextReaderExpand(reader) == NULL)
1438 return -1;
1441 #ifdef LIBXML_XINCLUDE_ENABLED
1443 * Handle XInclude if asked for
1445 if ((reader->xinclude) && (reader->in_xinclude == 0) &&
1446 (reader->node != NULL) &&
1447 (reader->node->type == XML_ELEMENT_NODE) &&
1448 (reader->node->ns != NULL) &&
1449 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1450 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1451 if (reader->xincctxt == NULL) {
1452 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1453 xmlXIncludeSetFlags(reader->xincctxt,
1454 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1455 xmlXIncludeSetStreamingMode(reader->xincctxt, 1);
1458 * expand that node and process it
1460 if (xmlTextReaderExpand(reader) == NULL)
1461 return -1;
1462 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1464 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1465 reader->in_xinclude++;
1466 goto get_next_node;
1468 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1469 reader->in_xinclude--;
1470 goto get_next_node;
1472 #endif
1474 * Handle entities enter and exit when in entity replacement mode
1476 if ((reader->node != NULL) &&
1477 (reader->node->type == XML_ENTITY_REF_NODE) &&
1478 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1479 if ((reader->node->children != NULL) &&
1480 (reader->node->children->type == XML_ENTITY_DECL) &&
1481 (reader->node->children->children != NULL)) {
1482 if (xmlTextReaderEntPush(reader, reader->node) < 0)
1483 goto get_next_node;
1484 reader->node = reader->node->children->children;
1486 #ifdef LIBXML_REGEXP_ENABLED
1487 } else if ((reader->node != NULL) &&
1488 (reader->node->type == XML_ENTITY_REF_NODE) &&
1489 (reader->ctxt != NULL) && (reader->validate)) {
1490 xmlTextReaderValidateEntity(reader);
1491 #endif /* LIBXML_REGEXP_ENABLED */
1493 if ((reader->node != NULL) &&
1494 (reader->node->type == XML_ENTITY_DECL) &&
1495 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1496 reader->node = xmlTextReaderEntPop(reader);
1497 reader->depth++;
1498 goto get_next_node;
1500 #ifdef LIBXML_REGEXP_ENABLED
1501 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1502 xmlNodePtr node = reader->node;
1504 if ((node->type == XML_ELEMENT_NODE) &&
1505 ((reader->state != XML_TEXTREADER_END) &&
1506 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1507 xmlTextReaderValidatePush(reader);
1508 } else if ((node->type == XML_TEXT_NODE) ||
1509 (node->type == XML_CDATA_SECTION_NODE)) {
1510 xmlTextReaderValidateCData(reader, node->content,
1511 xmlStrlen(node->content));
1514 #endif /* LIBXML_REGEXP_ENABLED */
1515 #ifdef LIBXML_PATTERN_ENABLED
1516 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1517 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1518 int i;
1519 for (i = 0;i < reader->patternNr;i++) {
1520 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1521 xmlTextReaderPreserve(reader);
1522 break;
1526 #endif /* LIBXML_PATTERN_ENABLED */
1527 #ifdef LIBXML_SCHEMAS_ENABLED
1528 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1529 (reader->xsdValidErrors == 0) &&
1530 (reader->xsdValidCtxt != NULL)) {
1531 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1533 #endif /* LIBXML_PATTERN_ENABLED */
1534 return(1);
1535 node_end:
1536 reader->state = XML_TEXTREADER_DONE;
1537 return(0);
1541 * xmlTextReaderReadState:
1542 * @reader: the xmlTextReaderPtr used
1544 * Gets the read state of the reader.
1546 * Returns the state value, or -1 in case of error
1549 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1550 if (reader == NULL)
1551 return(-1);
1552 return(reader->mode);
1556 * xmlTextReaderExpand:
1557 * @reader: the xmlTextReaderPtr used
1559 * Reads the contents of the current node and the full subtree. It then makes
1560 * the subtree available until the next xmlTextReaderRead() call
1562 * Returns a node pointer valid until the next xmlTextReaderRead() call
1563 * or NULL in case of error.
1565 xmlNodePtr
1566 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1567 if ((reader == NULL) || (reader->node == NULL))
1568 return(NULL);
1569 if (reader->doc != NULL)
1570 return(reader->node);
1571 if (reader->ctxt == NULL)
1572 return(NULL);
1573 if (xmlTextReaderDoExpand(reader) < 0)
1574 return(NULL);
1575 return(reader->node);
1579 * xmlTextReaderNext:
1580 * @reader: the xmlTextReaderPtr used
1582 * Skip to the node following the current one in document order while
1583 * avoiding the subtree if any.
1585 * Returns 1 if the node was read successfully, 0 if there is no more
1586 * nodes to read, or -1 in case of error
1589 xmlTextReaderNext(xmlTextReaderPtr reader) {
1590 int ret;
1591 xmlNodePtr cur;
1593 if (reader == NULL)
1594 return(-1);
1595 if (reader->doc != NULL)
1596 return(xmlTextReaderNextTree(reader));
1597 cur = reader->node;
1598 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1599 return(xmlTextReaderRead(reader));
1600 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1601 return(xmlTextReaderRead(reader));
1602 if (cur->extra & NODE_IS_EMPTY)
1603 return(xmlTextReaderRead(reader));
1604 do {
1605 ret = xmlTextReaderRead(reader);
1606 if (ret != 1)
1607 return(ret);
1608 } while (reader->node != cur);
1609 return(xmlTextReaderRead(reader));
1612 #ifdef LIBXML_WRITER_ENABLED
1614 * xmlTextReaderReadInnerXml:
1615 * @reader: the xmlTextReaderPtr used
1617 * Reads the contents of the current node, including child nodes and markup.
1619 * Returns a string containing the XML content, or NULL if the current node
1620 * is neither an element nor attribute, or has no child nodes. The
1621 * string must be deallocated by the caller.
1623 xmlChar *
1624 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1626 xmlChar *resbuf;
1627 xmlNodePtr node, cur_node;
1628 xmlBufferPtr buff, buff2;
1629 xmlDocPtr doc;
1631 if (xmlTextReaderExpand(reader) == NULL) {
1632 return NULL;
1634 doc = reader->node->doc;
1635 buff = xmlBufferCreate();
1636 if (buff == NULL)
1637 return NULL;
1638 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1639 for (cur_node = reader->node->children; cur_node != NULL;
1640 cur_node = cur_node->next) {
1641 /* XXX: Why is the node copied? */
1642 node = xmlDocCopyNode(cur_node, doc, 1);
1643 /* XXX: Why do we need a second buffer? */
1644 buff2 = xmlBufferCreate();
1645 xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT);
1646 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1647 xmlFreeNode(node);
1648 xmlBufferFree(buff2);
1649 xmlBufferFree(buff);
1650 return NULL;
1652 xmlBufferCat(buff, buff2->content);
1653 xmlFreeNode(node);
1654 xmlBufferFree(buff2);
1656 resbuf = buff->content;
1657 buff->content = NULL;
1659 xmlBufferFree(buff);
1660 return resbuf;
1662 #endif
1664 #ifdef LIBXML_WRITER_ENABLED
1666 * xmlTextReaderReadOuterXml:
1667 * @reader: the xmlTextReaderPtr used
1669 * Reads the contents of the current node, including child nodes and markup.
1671 * Returns a string containing the node and any XML content, or NULL if the
1672 * current node cannot be serialized. The string must be deallocated
1673 * by the caller.
1675 xmlChar *
1676 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1678 xmlChar *resbuf;
1679 xmlNodePtr node;
1680 xmlBufferPtr buff;
1681 xmlDocPtr doc;
1683 if (xmlTextReaderExpand(reader) == NULL) {
1684 return NULL;
1686 node = reader->node;
1687 doc = node->doc;
1688 /* XXX: Why is the node copied? */
1689 if (node->type == XML_DTD_NODE) {
1690 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1691 } else {
1692 node = xmlDocCopyNode(node, doc, 1);
1694 buff = xmlBufferCreate();
1695 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1696 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1697 xmlFreeNode(node);
1698 xmlBufferFree(buff);
1699 return NULL;
1702 resbuf = buff->content;
1703 buff->content = NULL;
1705 xmlFreeNode(node);
1706 xmlBufferFree(buff);
1707 return resbuf;
1709 #endif
1712 * xmlTextReaderReadString:
1713 * @reader: the xmlTextReaderPtr used
1715 * Reads the contents of an element or a text node as a string.
1717 * Returns a string containing the contents of the Element or Text node,
1718 * or NULL if the reader is positioned on any other type of node.
1719 * The string must be deallocated by the caller.
1721 xmlChar *
1722 xmlTextReaderReadString(xmlTextReaderPtr reader)
1724 xmlNodePtr node;
1726 if ((reader == NULL) || (reader->node == NULL))
1727 return(NULL);
1729 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1730 switch (node->type) {
1731 case XML_TEXT_NODE:
1732 if (node->content != NULL)
1733 return(xmlStrdup(node->content));
1734 break;
1735 case XML_ELEMENT_NODE:
1736 if (xmlTextReaderDoExpand(reader) != -1) {
1737 return xmlTextReaderCollectSiblings(node->children);
1739 break;
1740 case XML_ATTRIBUTE_NODE:
1741 TODO
1742 break;
1743 default:
1744 break;
1746 return(NULL);
1749 #if 0
1751 * xmlTextReaderReadBase64:
1752 * @reader: the xmlTextReaderPtr used
1753 * @array: a byte array to store the content.
1754 * @offset: the zero-based index into array where the method should
1755 * begin to write.
1756 * @len: the number of bytes to write.
1758 * Reads and decodes the Base64 encoded contents of an element and
1759 * stores the result in a byte buffer.
1761 * Returns the number of bytes written to array, or zero if the current
1762 * instance is not positioned on an element or -1 in case of error.
1765 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1766 unsigned char *array ATTRIBUTE_UNUSED,
1767 int offset ATTRIBUTE_UNUSED,
1768 int len ATTRIBUTE_UNUSED) {
1769 if ((reader == NULL) || (reader->ctxt == NULL))
1770 return(-1);
1771 if (reader->ctxt->wellFormed != 1)
1772 return(-1);
1774 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1775 return(0);
1776 TODO
1777 return(0);
1781 * xmlTextReaderReadBinHex:
1782 * @reader: the xmlTextReaderPtr used
1783 * @array: a byte array to store the content.
1784 * @offset: the zero-based index into array where the method should
1785 * begin to write.
1786 * @len: the number of bytes to write.
1788 * Reads and decodes the BinHex encoded contents of an element and
1789 * stores the result in a byte buffer.
1791 * Returns the number of bytes written to array, or zero if the current
1792 * instance is not positioned on an element or -1 in case of error.
1795 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1796 unsigned char *array ATTRIBUTE_UNUSED,
1797 int offset ATTRIBUTE_UNUSED,
1798 int len ATTRIBUTE_UNUSED) {
1799 if ((reader == NULL) || (reader->ctxt == NULL))
1800 return(-1);
1801 if (reader->ctxt->wellFormed != 1)
1802 return(-1);
1804 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1805 return(0);
1806 TODO
1807 return(0);
1809 #endif
1811 /************************************************************************
1813 * Operating on a preparsed tree *
1815 ************************************************************************/
1816 static int
1817 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1819 if (reader == NULL)
1820 return(-1);
1822 if (reader->state == XML_TEXTREADER_END)
1823 return(0);
1825 if (reader->node == NULL) {
1826 if (reader->doc->children == NULL) {
1827 reader->state = XML_TEXTREADER_END;
1828 return(0);
1831 reader->node = reader->doc->children;
1832 reader->state = XML_TEXTREADER_START;
1833 return(1);
1836 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1837 /* Here removed traversal to child, because we want to skip the subtree,
1838 replace with traversal to sibling to skip subtree */
1839 if (reader->node->next != 0) {
1840 /* Move to sibling if present,skipping sub-tree */
1841 reader->node = reader->node->next;
1842 reader->state = XML_TEXTREADER_START;
1843 return(1);
1846 /* if reader->node->next is NULL mean no subtree for current node,
1847 so need to move to sibling of parent node if present */
1848 reader->state = XML_TEXTREADER_BACKTRACK;
1849 /* This will move to parent if present */
1850 xmlTextReaderRead(reader);
1853 if (reader->node->next != 0) {
1854 reader->node = reader->node->next;
1855 reader->state = XML_TEXTREADER_START;
1856 return(1);
1859 if (reader->node->parent != 0) {
1860 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1861 reader->state = XML_TEXTREADER_END;
1862 return(0);
1865 reader->node = reader->node->parent;
1866 reader->depth--;
1867 reader->state = XML_TEXTREADER_BACKTRACK;
1868 /* Repeat process to move to sibling of parent node if present */
1869 xmlTextReaderNextTree(reader);
1872 reader->state = XML_TEXTREADER_END;
1874 return(1);
1878 * xmlTextReaderReadTree:
1879 * @reader: the xmlTextReaderPtr used
1881 * Moves the position of the current instance to the next node in
1882 * the stream, exposing its properties.
1884 * Returns 1 if the node was read successfully, 0 if there is no more
1885 * nodes to read, or -1 in case of error
1887 static int
1888 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1889 if (reader->state == XML_TEXTREADER_END)
1890 return(0);
1892 next_node:
1893 if (reader->node == NULL) {
1894 if (reader->doc->children == NULL) {
1895 reader->state = XML_TEXTREADER_END;
1896 return(0);
1899 reader->node = reader->doc->children;
1900 reader->state = XML_TEXTREADER_START;
1901 goto found_node;
1904 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1905 (reader->node->type != XML_DTD_NODE) &&
1906 (reader->node->type != XML_XINCLUDE_START) &&
1907 (reader->node->type != XML_ENTITY_REF_NODE)) {
1908 if (reader->node->children != NULL) {
1909 reader->node = reader->node->children;
1910 reader->depth++;
1911 reader->state = XML_TEXTREADER_START;
1912 goto found_node;
1915 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1916 reader->state = XML_TEXTREADER_BACKTRACK;
1917 goto found_node;
1921 if (reader->node->next != NULL) {
1922 reader->node = reader->node->next;
1923 reader->state = XML_TEXTREADER_START;
1924 goto found_node;
1927 if (reader->node->parent != NULL) {
1928 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1929 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1930 reader->state = XML_TEXTREADER_END;
1931 return(0);
1934 reader->node = reader->node->parent;
1935 reader->depth--;
1936 reader->state = XML_TEXTREADER_BACKTRACK;
1937 goto found_node;
1940 reader->state = XML_TEXTREADER_END;
1942 found_node:
1943 if ((reader->node->type == XML_XINCLUDE_START) ||
1944 (reader->node->type == XML_XINCLUDE_END))
1945 goto next_node;
1947 return(1);
1951 * xmlTextReaderNextSibling:
1952 * @reader: the xmlTextReaderPtr used
1954 * Skip to the node following the current one in document order while
1955 * avoiding the subtree if any.
1956 * Currently implemented only for Readers built on a document
1958 * Returns 1 if the node was read successfully, 0 if there is no more
1959 * nodes to read, or -1 in case of error
1962 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1963 if (reader == NULL)
1964 return(-1);
1965 if (reader->doc == NULL) {
1966 /* TODO */
1967 return(-1);
1970 if (reader->state == XML_TEXTREADER_END)
1971 return(0);
1973 if (reader->node == NULL)
1974 return(xmlTextReaderNextTree(reader));
1976 if (reader->node->next != NULL) {
1977 reader->node = reader->node->next;
1978 reader->state = XML_TEXTREADER_START;
1979 return(1);
1982 return(0);
1985 /************************************************************************
1987 * Constructor and destructors *
1989 ************************************************************************/
1991 * xmlNewTextReader:
1992 * @input: the xmlParserInputBufferPtr used to read data
1993 * @URI: the URI information for the source if available
1995 * Create an xmlTextReader structure fed with @input
1997 * Returns the new xmlTextReaderPtr or NULL in case of error
1999 xmlTextReaderPtr
2000 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2001 xmlTextReaderPtr ret;
2003 if (input == NULL)
2004 return(NULL);
2005 ret = xmlMalloc(sizeof(xmlTextReader));
2006 if (ret == NULL) {
2007 xmlGenericError(xmlGenericErrorContext,
2008 "xmlNewTextReader : malloc failed\n");
2009 return(NULL);
2011 memset(ret, 0, sizeof(xmlTextReader));
2012 ret->doc = NULL;
2013 ret->entTab = NULL;
2014 ret->entMax = 0;
2015 ret->entNr = 0;
2016 ret->input = input;
2017 ret->buffer = xmlBufCreateSize(100);
2018 if (ret->buffer == NULL) {
2019 xmlFree(ret);
2020 xmlGenericError(xmlGenericErrorContext,
2021 "xmlNewTextReader : malloc failed\n");
2022 return(NULL);
2024 /* no operation on a reader should require a huge buffer */
2025 xmlBufSetAllocationScheme(ret->buffer,
2026 XML_BUFFER_ALLOC_DOUBLEIT);
2027 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2028 if (ret->sax == NULL) {
2029 xmlBufFree(ret->buffer);
2030 xmlFree(ret);
2031 xmlGenericError(xmlGenericErrorContext,
2032 "xmlNewTextReader : malloc failed\n");
2033 return(NULL);
2035 xmlSAXVersion(ret->sax, 2);
2036 ret->startElement = ret->sax->startElement;
2037 ret->sax->startElement = xmlTextReaderStartElement;
2038 ret->endElement = ret->sax->endElement;
2039 ret->sax->endElement = xmlTextReaderEndElement;
2040 #ifdef LIBXML_SAX1_ENABLED
2041 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2042 #endif /* LIBXML_SAX1_ENABLED */
2043 ret->startElementNs = ret->sax->startElementNs;
2044 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2045 ret->endElementNs = ret->sax->endElementNs;
2046 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2047 #ifdef LIBXML_SAX1_ENABLED
2048 } else {
2049 ret->startElementNs = NULL;
2050 ret->endElementNs = NULL;
2052 #endif /* LIBXML_SAX1_ENABLED */
2053 ret->characters = ret->sax->characters;
2054 ret->sax->characters = xmlTextReaderCharacters;
2055 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2056 ret->cdataBlock = ret->sax->cdataBlock;
2057 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2059 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2060 ret->node = NULL;
2061 ret->curnode = NULL;
2062 if (xmlBufUse(ret->input->buffer) < 4) {
2063 xmlParserInputBufferRead(input, 4);
2065 if (xmlBufUse(ret->input->buffer) >= 4) {
2066 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2067 (const char *) xmlBufContent(ret->input->buffer),
2068 4, URI);
2069 ret->base = 0;
2070 ret->cur = 4;
2071 } else {
2072 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2073 ret->base = 0;
2074 ret->cur = 0;
2077 if (ret->ctxt == NULL) {
2078 xmlGenericError(xmlGenericErrorContext,
2079 "xmlNewTextReader : malloc failed\n");
2080 xmlBufFree(ret->buffer);
2081 xmlFree(ret->sax);
2082 xmlFree(ret);
2083 return(NULL);
2085 ret->ctxt->parseMode = XML_PARSE_READER;
2086 ret->ctxt->_private = ret;
2087 ret->ctxt->linenumbers = 1;
2088 ret->ctxt->dictNames = 1;
2089 ret->allocs = XML_TEXTREADER_CTXT;
2091 * use the parser dictionary to allocate all elements and attributes names
2093 ret->ctxt->docdict = 1;
2094 ret->dict = ret->ctxt->dict;
2095 #ifdef LIBXML_XINCLUDE_ENABLED
2096 ret->xinclude = 0;
2097 #endif
2098 #ifdef LIBXML_PATTERN_ENABLED
2099 ret->patternMax = 0;
2100 ret->patternTab = NULL;
2101 #endif
2102 return(ret);
2106 * xmlNewTextReaderFilename:
2107 * @URI: the URI of the resource to process
2109 * Create an xmlTextReader structure fed with the resource at @URI
2111 * Returns the new xmlTextReaderPtr or NULL in case of error
2113 xmlTextReaderPtr
2114 xmlNewTextReaderFilename(const char *URI) {
2115 xmlParserInputBufferPtr input;
2116 xmlTextReaderPtr ret;
2117 char *directory = NULL;
2119 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2120 if (input == NULL)
2121 return(NULL);
2122 ret = xmlNewTextReader(input, URI);
2123 if (ret == NULL) {
2124 xmlFreeParserInputBuffer(input);
2125 return(NULL);
2127 ret->allocs |= XML_TEXTREADER_INPUT;
2128 if (ret->ctxt->directory == NULL)
2129 directory = xmlParserGetDirectory(URI);
2130 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2131 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2132 if (directory != NULL)
2133 xmlFree(directory);
2134 return(ret);
2138 * xmlFreeTextReader:
2139 * @reader: the xmlTextReaderPtr
2141 * Deallocate all the resources associated to the reader
2143 void
2144 xmlFreeTextReader(xmlTextReaderPtr reader) {
2145 if (reader == NULL)
2146 return;
2147 #ifdef LIBXML_SCHEMAS_ENABLED
2148 if (reader->rngSchemas != NULL) {
2149 xmlRelaxNGFree(reader->rngSchemas);
2150 reader->rngSchemas = NULL;
2152 if (reader->rngValidCtxt != NULL) {
2153 if (! reader->rngPreserveCtxt)
2154 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2155 reader->rngValidCtxt = NULL;
2157 if (reader->xsdPlug != NULL) {
2158 xmlSchemaSAXUnplug(reader->xsdPlug);
2159 reader->xsdPlug = NULL;
2161 if (reader->xsdValidCtxt != NULL) {
2162 if (! reader->xsdPreserveCtxt)
2163 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2164 reader->xsdValidCtxt = NULL;
2166 if (reader->xsdSchemas != NULL) {
2167 xmlSchemaFree(reader->xsdSchemas);
2168 reader->xsdSchemas = NULL;
2170 #endif
2171 #ifdef LIBXML_XINCLUDE_ENABLED
2172 if (reader->xincctxt != NULL)
2173 xmlXIncludeFreeContext(reader->xincctxt);
2174 #endif
2175 #ifdef LIBXML_PATTERN_ENABLED
2176 if (reader->patternTab != NULL) {
2177 int i;
2178 for (i = 0;i < reader->patternNr;i++) {
2179 if (reader->patternTab[i] != NULL)
2180 xmlFreePattern(reader->patternTab[i]);
2182 xmlFree(reader->patternTab);
2184 #endif
2185 if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
2186 xmlTextReaderClose(reader);
2187 if (reader->ctxt != NULL) {
2188 if (reader->dict == reader->ctxt->dict)
2189 reader->dict = NULL;
2190 if (reader->allocs & XML_TEXTREADER_CTXT)
2191 xmlFreeParserCtxt(reader->ctxt);
2193 if (reader->sax != NULL)
2194 xmlFree(reader->sax);
2195 if (reader->buffer != NULL)
2196 xmlBufFree(reader->buffer);
2197 if (reader->entTab != NULL)
2198 xmlFree(reader->entTab);
2199 if (reader->dict != NULL)
2200 xmlDictFree(reader->dict);
2201 xmlFree(reader);
2204 /************************************************************************
2206 * Methods for XmlTextReader *
2208 ************************************************************************/
2210 * xmlTextReaderClose:
2211 * @reader: the xmlTextReaderPtr used
2213 * This method releases any resources allocated by the current instance
2214 * changes the state to Closed and close any underlying input.
2216 * Returns 0 or -1 in case of error
2219 xmlTextReaderClose(xmlTextReaderPtr reader) {
2220 if (reader == NULL)
2221 return(-1);
2222 reader->node = NULL;
2223 reader->curnode = NULL;
2224 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2225 if (reader->faketext != NULL) {
2226 xmlFreeNode(reader->faketext);
2227 reader->faketext = NULL;
2229 if (reader->ctxt != NULL) {
2230 #ifdef LIBXML_VALID_ENABLED
2231 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2232 (reader->ctxt->vctxt.vstateMax > 0)){
2233 #ifdef LIBXML_REGEXP_ENABLED
2234 while (reader->ctxt->vctxt.vstateNr > 0)
2235 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2236 #endif /* LIBXML_REGEXP_ENABLED */
2237 xmlFree(reader->ctxt->vctxt.vstateTab);
2238 reader->ctxt->vctxt.vstateTab = NULL;
2239 reader->ctxt->vctxt.vstateMax = 0;
2241 #endif /* LIBXML_VALID_ENABLED */
2242 xmlStopParser(reader->ctxt);
2243 if (reader->ctxt->myDoc != NULL) {
2244 if (reader->preserve == 0)
2245 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2246 reader->ctxt->myDoc = NULL;
2249 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2250 xmlFreeParserInputBuffer(reader->input);
2251 reader->allocs -= XML_TEXTREADER_INPUT;
2253 return(0);
2257 * xmlTextReaderGetAttributeNo:
2258 * @reader: the xmlTextReaderPtr used
2259 * @no: the zero-based index of the attribute relative to the containing element
2261 * Provides the value of the attribute with the specified index relative
2262 * to the containing element.
2264 * Returns a string containing the value of the specified attribute, or NULL
2265 * in case of error. The string must be deallocated by the caller.
2267 xmlChar *
2268 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2269 xmlChar *ret;
2270 int i;
2271 xmlAttrPtr cur;
2272 xmlNsPtr ns;
2274 if (reader == NULL)
2275 return(NULL);
2276 if (reader->node == NULL)
2277 return(NULL);
2278 if (reader->curnode != NULL)
2279 return(NULL);
2280 /* TODO: handle the xmlDecl */
2281 if (reader->node->type != XML_ELEMENT_NODE)
2282 return(NULL);
2284 ns = reader->node->nsDef;
2285 for (i = 0;(i < no) && (ns != NULL);i++) {
2286 ns = ns->next;
2288 if (ns != NULL)
2289 return(xmlStrdup(ns->href));
2291 cur = reader->node->properties;
2292 if (cur == NULL)
2293 return(NULL);
2294 for (;i < no;i++) {
2295 cur = cur->next;
2296 if (cur == NULL)
2297 return(NULL);
2299 /* TODO walk the DTD if present */
2301 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2302 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2303 return(ret);
2307 * xmlTextReaderGetAttribute:
2308 * @reader: the xmlTextReaderPtr used
2309 * @name: the qualified name of the attribute.
2311 * Provides the value of the attribute with the specified qualified name.
2313 * Returns a string containing the value of the specified attribute, or NULL
2314 * in case of error. The string must be deallocated by the caller.
2316 xmlChar *
2317 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2318 xmlChar *prefix = NULL;
2319 xmlChar *localname;
2320 xmlNsPtr ns;
2321 xmlChar *ret = NULL;
2323 if ((reader == NULL) || (name == NULL))
2324 return(NULL);
2325 if (reader->node == NULL)
2326 return(NULL);
2327 if (reader->curnode != NULL)
2328 return(NULL);
2330 /* TODO: handle the xmlDecl */
2331 if (reader->node->type != XML_ELEMENT_NODE)
2332 return(NULL);
2334 localname = xmlSplitQName2(name, &prefix);
2335 if (localname == NULL) {
2337 * Namespace default decl
2339 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2340 ns = reader->node->nsDef;
2341 while (ns != NULL) {
2342 if (ns->prefix == NULL) {
2343 return(xmlStrdup(ns->href));
2345 ns = ns->next;
2347 return NULL;
2349 return(xmlGetNoNsProp(reader->node, name));
2353 * Namespace default decl
2355 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2356 ns = reader->node->nsDef;
2357 while (ns != NULL) {
2358 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2359 ret = xmlStrdup(ns->href);
2360 break;
2362 ns = ns->next;
2364 } else {
2365 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2366 if (ns != NULL)
2367 ret = xmlGetNsProp(reader->node, localname, ns->href);
2370 xmlFree(localname);
2371 if (prefix != NULL)
2372 xmlFree(prefix);
2373 return(ret);
2378 * xmlTextReaderGetAttributeNs:
2379 * @reader: the xmlTextReaderPtr used
2380 * @localName: the local name of the attribute.
2381 * @namespaceURI: the namespace URI of the attribute.
2383 * Provides the value of the specified attribute
2385 * Returns a string containing the value of the specified attribute, or NULL
2386 * in case of error. The string must be deallocated by the caller.
2388 xmlChar *
2389 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2390 const xmlChar *namespaceURI) {
2391 xmlChar *prefix = NULL;
2392 xmlNsPtr ns;
2394 if ((reader == NULL) || (localName == NULL))
2395 return(NULL);
2396 if (reader->node == NULL)
2397 return(NULL);
2398 if (reader->curnode != NULL)
2399 return(NULL);
2401 /* TODO: handle the xmlDecl */
2402 if (reader->node->type != XML_ELEMENT_NODE)
2403 return(NULL);
2405 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2406 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2407 prefix = BAD_CAST localName;
2409 ns = reader->node->nsDef;
2410 while (ns != NULL) {
2411 if ((prefix == NULL && ns->prefix == NULL) ||
2412 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2413 return xmlStrdup(ns->href);
2415 ns = ns->next;
2417 return NULL;
2420 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2424 * xmlTextReaderGetRemainder:
2425 * @reader: the xmlTextReaderPtr used
2427 * Method to get the remainder of the buffered XML. this method stops the
2428 * parser, set its state to End Of File and return the input stream with
2429 * what is left that the parser did not use.
2431 * The implementation is not good, the parser certainly progressed past
2432 * what's left in reader->input, and there is an allocation problem. Best
2433 * would be to rewrite it differently.
2435 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2436 * in case of error.
2438 xmlParserInputBufferPtr
2439 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2440 xmlParserInputBufferPtr ret = NULL;
2442 if (reader == NULL)
2443 return(NULL);
2444 if (reader->node == NULL)
2445 return(NULL);
2447 reader->node = NULL;
2448 reader->curnode = NULL;
2449 reader->mode = XML_TEXTREADER_MODE_EOF;
2450 if (reader->ctxt != NULL) {
2451 xmlStopParser(reader->ctxt);
2452 if (reader->ctxt->myDoc != NULL) {
2453 if (reader->preserve == 0)
2454 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2455 reader->ctxt->myDoc = NULL;
2458 if (reader->allocs & XML_TEXTREADER_INPUT) {
2459 ret = reader->input;
2460 reader->input = NULL;
2461 reader->allocs -= XML_TEXTREADER_INPUT;
2462 } else {
2464 * Hum, one may need to duplicate the data structure because
2465 * without reference counting the input may be freed twice:
2466 * - by the layer which allocated it.
2467 * - by the layer to which would have been returned to.
2469 TODO
2470 return(NULL);
2472 return(ret);
2476 * xmlTextReaderLookupNamespace:
2477 * @reader: the xmlTextReaderPtr used
2478 * @prefix: the prefix whose namespace URI is to be resolved. To return
2479 * the default namespace, specify NULL
2481 * Resolves a namespace prefix in the scope of the current element.
2483 * Returns a string containing the namespace URI to which the prefix maps
2484 * or NULL in case of error. The string must be deallocated by the caller.
2486 xmlChar *
2487 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2488 xmlNsPtr ns;
2490 if (reader == NULL)
2491 return(NULL);
2492 if (reader->node == NULL)
2493 return(NULL);
2495 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2496 if (ns == NULL)
2497 return(NULL);
2498 return(xmlStrdup(ns->href));
2502 * xmlTextReaderMoveToAttributeNo:
2503 * @reader: the xmlTextReaderPtr used
2504 * @no: the zero-based index of the attribute relative to the containing
2505 * element.
2507 * Moves the position of the current instance to the attribute with
2508 * the specified index relative to the containing element.
2510 * Returns 1 in case of success, -1 in case of error, 0 if not found
2513 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2514 int i;
2515 xmlAttrPtr cur;
2516 xmlNsPtr ns;
2518 if (reader == NULL)
2519 return(-1);
2520 if (reader->node == NULL)
2521 return(-1);
2522 /* TODO: handle the xmlDecl */
2523 if (reader->node->type != XML_ELEMENT_NODE)
2524 return(-1);
2526 reader->curnode = NULL;
2528 ns = reader->node->nsDef;
2529 for (i = 0;(i < no) && (ns != NULL);i++) {
2530 ns = ns->next;
2532 if (ns != NULL) {
2533 reader->curnode = (xmlNodePtr) ns;
2534 return(1);
2537 cur = reader->node->properties;
2538 if (cur == NULL)
2539 return(0);
2540 for (;i < no;i++) {
2541 cur = cur->next;
2542 if (cur == NULL)
2543 return(0);
2545 /* TODO walk the DTD if present */
2547 reader->curnode = (xmlNodePtr) cur;
2548 return(1);
2552 * xmlTextReaderMoveToAttribute:
2553 * @reader: the xmlTextReaderPtr used
2554 * @name: the qualified name of the attribute.
2556 * Moves the position of the current instance to the attribute with
2557 * the specified qualified name.
2559 * Returns 1 in case of success, -1 in case of error, 0 if not found
2562 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2563 xmlChar *prefix = NULL;
2564 xmlChar *localname;
2565 xmlNsPtr ns;
2566 xmlAttrPtr prop;
2568 if ((reader == NULL) || (name == NULL))
2569 return(-1);
2570 if (reader->node == NULL)
2571 return(-1);
2573 /* TODO: handle the xmlDecl */
2574 if (reader->node->type != XML_ELEMENT_NODE)
2575 return(0);
2577 localname = xmlSplitQName2(name, &prefix);
2578 if (localname == NULL) {
2580 * Namespace default decl
2582 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2583 ns = reader->node->nsDef;
2584 while (ns != NULL) {
2585 if (ns->prefix == NULL) {
2586 reader->curnode = (xmlNodePtr) ns;
2587 return(1);
2589 ns = ns->next;
2591 return(0);
2594 prop = reader->node->properties;
2595 while (prop != NULL) {
2597 * One need to have
2598 * - same attribute names
2599 * - and the attribute carrying that namespace
2601 if ((xmlStrEqual(prop->name, name)) &&
2602 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2603 reader->curnode = (xmlNodePtr) prop;
2604 return(1);
2606 prop = prop->next;
2608 return(0);
2612 * Namespace default decl
2614 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2615 ns = reader->node->nsDef;
2616 while (ns != NULL) {
2617 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2618 reader->curnode = (xmlNodePtr) ns;
2619 goto found;
2621 ns = ns->next;
2623 goto not_found;
2625 prop = reader->node->properties;
2626 while (prop != NULL) {
2628 * One need to have
2629 * - same attribute names
2630 * - and the attribute carrying that namespace
2632 if ((xmlStrEqual(prop->name, localname)) &&
2633 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2634 reader->curnode = (xmlNodePtr) prop;
2635 goto found;
2637 prop = prop->next;
2639 not_found:
2640 if (localname != NULL)
2641 xmlFree(localname);
2642 if (prefix != NULL)
2643 xmlFree(prefix);
2644 return(0);
2646 found:
2647 if (localname != NULL)
2648 xmlFree(localname);
2649 if (prefix != NULL)
2650 xmlFree(prefix);
2651 return(1);
2655 * xmlTextReaderMoveToAttributeNs:
2656 * @reader: the xmlTextReaderPtr used
2657 * @localName: the local name of the attribute.
2658 * @namespaceURI: the namespace URI of the attribute.
2660 * Moves the position of the current instance to the attribute with the
2661 * specified local name and namespace URI.
2663 * Returns 1 in case of success, -1 in case of error, 0 if not found
2666 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2667 const xmlChar *localName, const xmlChar *namespaceURI) {
2668 xmlAttrPtr prop;
2669 xmlNodePtr node;
2670 xmlNsPtr ns;
2671 xmlChar *prefix = NULL;
2673 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2674 return(-1);
2675 if (reader->node == NULL)
2676 return(-1);
2677 if (reader->node->type != XML_ELEMENT_NODE)
2678 return(0);
2679 node = reader->node;
2681 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2682 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2683 prefix = BAD_CAST localName;
2685 ns = reader->node->nsDef;
2686 while (ns != NULL) {
2687 if ((prefix == NULL && ns->prefix == NULL) ||
2688 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2689 reader->curnode = (xmlNodePtr) ns;
2690 return(1);
2692 ns = ns->next;
2694 return(0);
2697 prop = node->properties;
2698 while (prop != NULL) {
2700 * One need to have
2701 * - same attribute names
2702 * - and the attribute carrying that namespace
2704 if (xmlStrEqual(prop->name, localName) &&
2705 ((prop->ns != NULL) &&
2706 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2707 reader->curnode = (xmlNodePtr) prop;
2708 return(1);
2710 prop = prop->next;
2712 return(0);
2716 * xmlTextReaderMoveToFirstAttribute:
2717 * @reader: the xmlTextReaderPtr used
2719 * Moves the position of the current instance to the first attribute
2720 * associated with the current node.
2722 * Returns 1 in case of success, -1 in case of error, 0 if not found
2725 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2726 if (reader == NULL)
2727 return(-1);
2728 if (reader->node == NULL)
2729 return(-1);
2730 if (reader->node->type != XML_ELEMENT_NODE)
2731 return(0);
2733 if (reader->node->nsDef != NULL) {
2734 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2735 return(1);
2737 if (reader->node->properties != NULL) {
2738 reader->curnode = (xmlNodePtr) reader->node->properties;
2739 return(1);
2741 return(0);
2745 * xmlTextReaderMoveToNextAttribute:
2746 * @reader: the xmlTextReaderPtr used
2748 * Moves the position of the current instance to the next attribute
2749 * associated with the current node.
2751 * Returns 1 in case of success, -1 in case of error, 0 if not found
2754 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2755 if (reader == NULL)
2756 return(-1);
2757 if (reader->node == NULL)
2758 return(-1);
2759 if (reader->node->type != XML_ELEMENT_NODE)
2760 return(0);
2761 if (reader->curnode == NULL)
2762 return(xmlTextReaderMoveToFirstAttribute(reader));
2764 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2765 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2766 if (ns->next != NULL) {
2767 reader->curnode = (xmlNodePtr) ns->next;
2768 return(1);
2770 if (reader->node->properties != NULL) {
2771 reader->curnode = (xmlNodePtr) reader->node->properties;
2772 return(1);
2774 return(0);
2775 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2776 (reader->curnode->next != NULL)) {
2777 reader->curnode = reader->curnode->next;
2778 return(1);
2780 return(0);
2784 * xmlTextReaderMoveToElement:
2785 * @reader: the xmlTextReaderPtr used
2787 * Moves the position of the current instance to the node that
2788 * contains the current Attribute node.
2790 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2793 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2794 if (reader == NULL)
2795 return(-1);
2796 if (reader->node == NULL)
2797 return(-1);
2798 if (reader->node->type != XML_ELEMENT_NODE)
2799 return(0);
2800 if (reader->curnode != NULL) {
2801 reader->curnode = NULL;
2802 return(1);
2804 return(0);
2808 * xmlTextReaderReadAttributeValue:
2809 * @reader: the xmlTextReaderPtr used
2811 * Parses an attribute value into one or more Text and EntityReference nodes.
2813 * Returns 1 in case of success, 0 if the reader was not positioned on an
2814 * attribute node or all the attribute values have been read, or -1
2815 * in case of error.
2818 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2819 if (reader == NULL)
2820 return(-1);
2821 if (reader->node == NULL)
2822 return(-1);
2823 if (reader->curnode == NULL)
2824 return(0);
2825 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2826 if (reader->curnode->children == NULL)
2827 return(0);
2828 reader->curnode = reader->curnode->children;
2829 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2830 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2832 if (reader->faketext == NULL) {
2833 reader->faketext = xmlNewDocText(reader->node->doc,
2834 ns->href);
2835 } else {
2836 if ((reader->faketext->content != NULL) &&
2837 (reader->faketext->content !=
2838 (xmlChar *) &(reader->faketext->properties)))
2839 xmlFree(reader->faketext->content);
2840 reader->faketext->content = xmlStrdup(ns->href);
2842 reader->curnode = reader->faketext;
2843 } else {
2844 if (reader->curnode->next == NULL)
2845 return(0);
2846 reader->curnode = reader->curnode->next;
2848 return(1);
2852 * xmlTextReaderConstEncoding:
2853 * @reader: the xmlTextReaderPtr used
2855 * Determine the encoding of the document being read.
2857 * Returns a string containing the encoding of the document or NULL in
2858 * case of error. The string is deallocated with the reader.
2860 const xmlChar *
2861 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2862 xmlDocPtr doc = NULL;
2863 if (reader == NULL)
2864 return(NULL);
2865 if (reader->doc != NULL)
2866 doc = reader->doc;
2867 else if (reader->ctxt != NULL)
2868 doc = reader->ctxt->myDoc;
2869 if (doc == NULL)
2870 return(NULL);
2872 if (doc->encoding == NULL)
2873 return(NULL);
2874 else
2875 return(CONSTSTR(doc->encoding));
2879 /************************************************************************
2881 * Access API to the current node *
2883 ************************************************************************/
2885 * xmlTextReaderAttributeCount:
2886 * @reader: the xmlTextReaderPtr used
2888 * Provides the number of attributes of the current node
2890 * Returns 0 i no attributes, -1 in case of error or the attribute count
2893 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2894 int ret;
2895 xmlAttrPtr attr;
2896 xmlNsPtr ns;
2897 xmlNodePtr node;
2899 if (reader == NULL)
2900 return(-1);
2901 if (reader->node == NULL)
2902 return(0);
2904 if (reader->curnode != NULL)
2905 node = reader->curnode;
2906 else
2907 node = reader->node;
2909 if (node->type != XML_ELEMENT_NODE)
2910 return(0);
2911 if ((reader->state == XML_TEXTREADER_END) ||
2912 (reader->state == XML_TEXTREADER_BACKTRACK))
2913 return(0);
2914 ret = 0;
2915 attr = node->properties;
2916 while (attr != NULL) {
2917 ret++;
2918 attr = attr->next;
2920 ns = node->nsDef;
2921 while (ns != NULL) {
2922 ret++;
2923 ns = ns->next;
2925 return(ret);
2929 * xmlTextReaderNodeType:
2930 * @reader: the xmlTextReaderPtr used
2932 * Get the node type of the current node
2933 * Reference:
2934 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
2936 * Returns the xmlReaderTypes of the current node or -1 in case of error
2939 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2940 xmlNodePtr node;
2942 if (reader == NULL)
2943 return(-1);
2944 if (reader->node == NULL)
2945 return(XML_READER_TYPE_NONE);
2946 if (reader->curnode != NULL)
2947 node = reader->curnode;
2948 else
2949 node = reader->node;
2950 switch (node->type) {
2951 case XML_ELEMENT_NODE:
2952 if ((reader->state == XML_TEXTREADER_END) ||
2953 (reader->state == XML_TEXTREADER_BACKTRACK))
2954 return(XML_READER_TYPE_END_ELEMENT);
2955 return(XML_READER_TYPE_ELEMENT);
2956 case XML_NAMESPACE_DECL:
2957 case XML_ATTRIBUTE_NODE:
2958 return(XML_READER_TYPE_ATTRIBUTE);
2959 case XML_TEXT_NODE:
2960 if (xmlIsBlankNode(reader->node)) {
2961 if (xmlNodeGetSpacePreserve(reader->node))
2962 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2963 else
2964 return(XML_READER_TYPE_WHITESPACE);
2965 } else {
2966 return(XML_READER_TYPE_TEXT);
2968 case XML_CDATA_SECTION_NODE:
2969 return(XML_READER_TYPE_CDATA);
2970 case XML_ENTITY_REF_NODE:
2971 return(XML_READER_TYPE_ENTITY_REFERENCE);
2972 case XML_ENTITY_NODE:
2973 return(XML_READER_TYPE_ENTITY);
2974 case XML_PI_NODE:
2975 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
2976 case XML_COMMENT_NODE:
2977 return(XML_READER_TYPE_COMMENT);
2978 case XML_DOCUMENT_NODE:
2979 case XML_HTML_DOCUMENT_NODE:
2980 return(XML_READER_TYPE_DOCUMENT);
2981 case XML_DOCUMENT_FRAG_NODE:
2982 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
2983 case XML_NOTATION_NODE:
2984 return(XML_READER_TYPE_NOTATION);
2985 case XML_DOCUMENT_TYPE_NODE:
2986 case XML_DTD_NODE:
2987 return(XML_READER_TYPE_DOCUMENT_TYPE);
2989 case XML_ELEMENT_DECL:
2990 case XML_ATTRIBUTE_DECL:
2991 case XML_ENTITY_DECL:
2992 case XML_XINCLUDE_START:
2993 case XML_XINCLUDE_END:
2994 return(XML_READER_TYPE_NONE);
2996 return(-1);
3000 * xmlTextReaderIsEmptyElement:
3001 * @reader: the xmlTextReaderPtr used
3003 * Check if the current node is empty
3005 * Returns 1 if empty, 0 if not and -1 in case of error
3008 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3009 if ((reader == NULL) || (reader->node == NULL))
3010 return(-1);
3011 if (reader->node->type != XML_ELEMENT_NODE)
3012 return(0);
3013 if (reader->curnode != NULL)
3014 return(0);
3015 if (reader->node->children != NULL)
3016 return(0);
3017 if (reader->state == XML_TEXTREADER_END)
3018 return(0);
3019 if (reader->doc != NULL)
3020 return(1);
3021 #ifdef LIBXML_XINCLUDE_ENABLED
3022 if (reader->in_xinclude > 0)
3023 return(1);
3024 #endif
3025 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3029 * xmlTextReaderLocalName:
3030 * @reader: the xmlTextReaderPtr used
3032 * The local name of the node.
3034 * Returns the local name or NULL if not available,
3035 * if non NULL it need to be freed by the caller.
3037 xmlChar *
3038 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3039 xmlNodePtr node;
3040 if ((reader == NULL) || (reader->node == NULL))
3041 return(NULL);
3042 if (reader->curnode != NULL)
3043 node = reader->curnode;
3044 else
3045 node = reader->node;
3046 if (node->type == XML_NAMESPACE_DECL) {
3047 xmlNsPtr ns = (xmlNsPtr) node;
3048 if (ns->prefix == NULL)
3049 return(xmlStrdup(BAD_CAST "xmlns"));
3050 else
3051 return(xmlStrdup(ns->prefix));
3053 if ((node->type != XML_ELEMENT_NODE) &&
3054 (node->type != XML_ATTRIBUTE_NODE))
3055 return(xmlTextReaderName(reader));
3056 return(xmlStrdup(node->name));
3060 * xmlTextReaderConstLocalName:
3061 * @reader: the xmlTextReaderPtr used
3063 * The local name of the node.
3065 * Returns the local name or NULL if not available, the
3066 * string will be deallocated with the reader.
3068 const xmlChar *
3069 xmlTextReaderConstLocalName(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(CONSTSTR(BAD_CAST "xmlns"));
3081 else
3082 return(ns->prefix);
3084 if ((node->type != XML_ELEMENT_NODE) &&
3085 (node->type != XML_ATTRIBUTE_NODE))
3086 return(xmlTextReaderConstName(reader));
3087 return(node->name);
3091 * xmlTextReaderName:
3092 * @reader: the xmlTextReaderPtr used
3094 * The qualified name of the node, equal to Prefix :LocalName.
3096 * Returns the local name or NULL if not available,
3097 * if non NULL it need to be freed by the caller.
3099 xmlChar *
3100 xmlTextReaderName(xmlTextReaderPtr reader) {
3101 xmlNodePtr node;
3102 xmlChar *ret;
3104 if ((reader == NULL) || (reader->node == NULL))
3105 return(NULL);
3106 if (reader->curnode != NULL)
3107 node = reader->curnode;
3108 else
3109 node = reader->node;
3110 switch (node->type) {
3111 case XML_ELEMENT_NODE:
3112 case XML_ATTRIBUTE_NODE:
3113 if ((node->ns == NULL) ||
3114 (node->ns->prefix == NULL))
3115 return(xmlStrdup(node->name));
3117 ret = xmlStrdup(node->ns->prefix);
3118 ret = xmlStrcat(ret, BAD_CAST ":");
3119 ret = xmlStrcat(ret, node->name);
3120 return(ret);
3121 case XML_TEXT_NODE:
3122 return(xmlStrdup(BAD_CAST "#text"));
3123 case XML_CDATA_SECTION_NODE:
3124 return(xmlStrdup(BAD_CAST "#cdata-section"));
3125 case XML_ENTITY_NODE:
3126 case XML_ENTITY_REF_NODE:
3127 return(xmlStrdup(node->name));
3128 case XML_PI_NODE:
3129 return(xmlStrdup(node->name));
3130 case XML_COMMENT_NODE:
3131 return(xmlStrdup(BAD_CAST "#comment"));
3132 case XML_DOCUMENT_NODE:
3133 case XML_HTML_DOCUMENT_NODE:
3134 return(xmlStrdup(BAD_CAST "#document"));
3135 case XML_DOCUMENT_FRAG_NODE:
3136 return(xmlStrdup(BAD_CAST "#document-fragment"));
3137 case XML_NOTATION_NODE:
3138 return(xmlStrdup(node->name));
3139 case XML_DOCUMENT_TYPE_NODE:
3140 case XML_DTD_NODE:
3141 return(xmlStrdup(node->name));
3142 case XML_NAMESPACE_DECL: {
3143 xmlNsPtr ns = (xmlNsPtr) node;
3145 ret = xmlStrdup(BAD_CAST "xmlns");
3146 if (ns->prefix == NULL)
3147 return(ret);
3148 ret = xmlStrcat(ret, BAD_CAST ":");
3149 ret = xmlStrcat(ret, ns->prefix);
3150 return(ret);
3153 case XML_ELEMENT_DECL:
3154 case XML_ATTRIBUTE_DECL:
3155 case XML_ENTITY_DECL:
3156 case XML_XINCLUDE_START:
3157 case XML_XINCLUDE_END:
3158 return(NULL);
3160 return(NULL);
3164 * xmlTextReaderConstName:
3165 * @reader: the xmlTextReaderPtr used
3167 * The qualified name of the node, equal to Prefix :LocalName.
3169 * Returns the local name or NULL if not available, the string is
3170 * deallocated with the reader.
3172 const xmlChar *
3173 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3174 xmlNodePtr node;
3176 if ((reader == NULL) || (reader->node == NULL))
3177 return(NULL);
3178 if (reader->curnode != NULL)
3179 node = reader->curnode;
3180 else
3181 node = reader->node;
3182 switch (node->type) {
3183 case XML_ELEMENT_NODE:
3184 case XML_ATTRIBUTE_NODE:
3185 if ((node->ns == NULL) ||
3186 (node->ns->prefix == NULL))
3187 return(node->name);
3188 return(CONSTQSTR(node->ns->prefix, node->name));
3189 case XML_TEXT_NODE:
3190 return(CONSTSTR(BAD_CAST "#text"));
3191 case XML_CDATA_SECTION_NODE:
3192 return(CONSTSTR(BAD_CAST "#cdata-section"));
3193 case XML_ENTITY_NODE:
3194 case XML_ENTITY_REF_NODE:
3195 return(CONSTSTR(node->name));
3196 case XML_PI_NODE:
3197 return(CONSTSTR(node->name));
3198 case XML_COMMENT_NODE:
3199 return(CONSTSTR(BAD_CAST "#comment"));
3200 case XML_DOCUMENT_NODE:
3201 case XML_HTML_DOCUMENT_NODE:
3202 return(CONSTSTR(BAD_CAST "#document"));
3203 case XML_DOCUMENT_FRAG_NODE:
3204 return(CONSTSTR(BAD_CAST "#document-fragment"));
3205 case XML_NOTATION_NODE:
3206 return(CONSTSTR(node->name));
3207 case XML_DOCUMENT_TYPE_NODE:
3208 case XML_DTD_NODE:
3209 return(CONSTSTR(node->name));
3210 case XML_NAMESPACE_DECL: {
3211 xmlNsPtr ns = (xmlNsPtr) node;
3213 if (ns->prefix == NULL)
3214 return(CONSTSTR(BAD_CAST "xmlns"));
3215 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3218 case XML_ELEMENT_DECL:
3219 case XML_ATTRIBUTE_DECL:
3220 case XML_ENTITY_DECL:
3221 case XML_XINCLUDE_START:
3222 case XML_XINCLUDE_END:
3223 return(NULL);
3225 return(NULL);
3229 * xmlTextReaderPrefix:
3230 * @reader: the xmlTextReaderPtr used
3232 * A shorthand reference to the namespace associated with the node.
3234 * Returns the prefix or NULL if not available,
3235 * if non NULL it need to be freed by the caller.
3237 xmlChar *
3238 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3239 xmlNodePtr node;
3240 if ((reader == NULL) || (reader->node == NULL))
3241 return(NULL);
3242 if (reader->curnode != NULL)
3243 node = reader->curnode;
3244 else
3245 node = reader->node;
3246 if (node->type == XML_NAMESPACE_DECL) {
3247 xmlNsPtr ns = (xmlNsPtr) node;
3248 if (ns->prefix == NULL)
3249 return(NULL);
3250 return(xmlStrdup(BAD_CAST "xmlns"));
3252 if ((node->type != XML_ELEMENT_NODE) &&
3253 (node->type != XML_ATTRIBUTE_NODE))
3254 return(NULL);
3255 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3256 return(xmlStrdup(node->ns->prefix));
3257 return(NULL);
3261 * xmlTextReaderConstPrefix:
3262 * @reader: the xmlTextReaderPtr used
3264 * A shorthand reference to the namespace associated with the node.
3266 * Returns the prefix or NULL if not available, the string is deallocated
3267 * with the reader.
3269 const xmlChar *
3270 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3271 xmlNodePtr node;
3272 if ((reader == NULL) || (reader->node == NULL))
3273 return(NULL);
3274 if (reader->curnode != NULL)
3275 node = reader->curnode;
3276 else
3277 node = reader->node;
3278 if (node->type == XML_NAMESPACE_DECL) {
3279 xmlNsPtr ns = (xmlNsPtr) node;
3280 if (ns->prefix == NULL)
3281 return(NULL);
3282 return(CONSTSTR(BAD_CAST "xmlns"));
3284 if ((node->type != XML_ELEMENT_NODE) &&
3285 (node->type != XML_ATTRIBUTE_NODE))
3286 return(NULL);
3287 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3288 return(CONSTSTR(node->ns->prefix));
3289 return(NULL);
3293 * xmlTextReaderNamespaceUri:
3294 * @reader: the xmlTextReaderPtr used
3296 * The URI defining the namespace associated with the node.
3298 * Returns the namespace URI or NULL if not available,
3299 * if non NULL it need to be freed by the caller.
3301 xmlChar *
3302 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3303 xmlNodePtr node;
3304 if ((reader == NULL) || (reader->node == NULL))
3305 return(NULL);
3306 if (reader->curnode != NULL)
3307 node = reader->curnode;
3308 else
3309 node = reader->node;
3310 if (node->type == XML_NAMESPACE_DECL)
3311 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3312 if ((node->type != XML_ELEMENT_NODE) &&
3313 (node->type != XML_ATTRIBUTE_NODE))
3314 return(NULL);
3315 if (node->ns != NULL)
3316 return(xmlStrdup(node->ns->href));
3317 return(NULL);
3321 * xmlTextReaderConstNamespaceUri:
3322 * @reader: the xmlTextReaderPtr used
3324 * The URI defining the namespace associated with the node.
3326 * Returns the namespace URI or NULL if not available, the string
3327 * will be deallocated with the reader
3329 const xmlChar *
3330 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3331 xmlNodePtr node;
3332 if ((reader == NULL) || (reader->node == NULL))
3333 return(NULL);
3334 if (reader->curnode != NULL)
3335 node = reader->curnode;
3336 else
3337 node = reader->node;
3338 if (node->type == XML_NAMESPACE_DECL)
3339 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3340 if ((node->type != XML_ELEMENT_NODE) &&
3341 (node->type != XML_ATTRIBUTE_NODE))
3342 return(NULL);
3343 if (node->ns != NULL)
3344 return(CONSTSTR(node->ns->href));
3345 return(NULL);
3349 * xmlTextReaderBaseUri:
3350 * @reader: the xmlTextReaderPtr used
3352 * The base URI of the node.
3354 * Returns the base URI or NULL if not available,
3355 * if non NULL it need to be freed by the caller.
3357 xmlChar *
3358 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3359 if ((reader == NULL) || (reader->node == NULL))
3360 return(NULL);
3361 return(xmlNodeGetBase(NULL, reader->node));
3365 * xmlTextReaderConstBaseUri:
3366 * @reader: the xmlTextReaderPtr used
3368 * The base URI of the node.
3370 * Returns the base URI or NULL if not available, the string
3371 * will be deallocated with the reader
3373 const xmlChar *
3374 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3375 xmlChar *tmp;
3376 const xmlChar *ret;
3378 if ((reader == NULL) || (reader->node == NULL))
3379 return(NULL);
3380 tmp = xmlNodeGetBase(NULL, reader->node);
3381 if (tmp == NULL)
3382 return(NULL);
3383 ret = CONSTSTR(tmp);
3384 xmlFree(tmp);
3385 return(ret);
3389 * xmlTextReaderDepth:
3390 * @reader: the xmlTextReaderPtr used
3392 * The depth of the node in the tree.
3394 * Returns the depth or -1 in case of error
3397 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3398 if (reader == NULL)
3399 return(-1);
3400 if (reader->node == NULL)
3401 return(0);
3403 if (reader->curnode != NULL) {
3404 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3405 (reader->curnode->type == XML_NAMESPACE_DECL))
3406 return(reader->depth + 1);
3407 return(reader->depth + 2);
3409 return(reader->depth);
3413 * xmlTextReaderHasAttributes:
3414 * @reader: the xmlTextReaderPtr used
3416 * Whether the node has attributes.
3418 * Returns 1 if true, 0 if false, and -1 in case or error
3421 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3422 xmlNodePtr node;
3423 if (reader == NULL)
3424 return(-1);
3425 if (reader->node == NULL)
3426 return(0);
3427 if (reader->curnode != NULL)
3428 node = reader->curnode;
3429 else
3430 node = reader->node;
3432 if ((node->type == XML_ELEMENT_NODE) &&
3433 ((node->properties != NULL) || (node->nsDef != NULL)))
3434 return(1);
3435 /* TODO: handle the xmlDecl */
3436 return(0);
3440 * xmlTextReaderHasValue:
3441 * @reader: the xmlTextReaderPtr used
3443 * Whether the node can have a text value.
3445 * Returns 1 if true, 0 if false, and -1 in case or error
3448 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3449 xmlNodePtr node;
3450 if (reader == NULL)
3451 return(-1);
3452 if (reader->node == NULL)
3453 return(0);
3454 if (reader->curnode != NULL)
3455 node = reader->curnode;
3456 else
3457 node = reader->node;
3459 switch (node->type) {
3460 case XML_ATTRIBUTE_NODE:
3461 case XML_TEXT_NODE:
3462 case XML_CDATA_SECTION_NODE:
3463 case XML_PI_NODE:
3464 case XML_COMMENT_NODE:
3465 case XML_NAMESPACE_DECL:
3466 return(1);
3467 default:
3468 break;
3470 return(0);
3474 * xmlTextReaderValue:
3475 * @reader: the xmlTextReaderPtr used
3477 * Provides the text value of the node if present
3479 * Returns the string or NULL if not available. The result must be deallocated
3480 * with xmlFree()
3482 xmlChar *
3483 xmlTextReaderValue(xmlTextReaderPtr reader) {
3484 xmlNodePtr node;
3485 if (reader == NULL)
3486 return(NULL);
3487 if (reader->node == NULL)
3488 return(NULL);
3489 if (reader->curnode != NULL)
3490 node = reader->curnode;
3491 else
3492 node = reader->node;
3494 switch (node->type) {
3495 case XML_NAMESPACE_DECL:
3496 return(xmlStrdup(((xmlNsPtr) node)->href));
3497 case XML_ATTRIBUTE_NODE:{
3498 xmlAttrPtr attr = (xmlAttrPtr) node;
3500 if (attr->parent != NULL)
3501 return (xmlNodeListGetString
3502 (attr->parent->doc, attr->children, 1));
3503 else
3504 return (xmlNodeListGetString(NULL, attr->children, 1));
3505 break;
3507 case XML_TEXT_NODE:
3508 case XML_CDATA_SECTION_NODE:
3509 case XML_PI_NODE:
3510 case XML_COMMENT_NODE:
3511 if (node->content != NULL)
3512 return (xmlStrdup(node->content));
3513 default:
3514 break;
3516 return(NULL);
3520 * xmlTextReaderConstValue:
3521 * @reader: the xmlTextReaderPtr used
3523 * Provides the text value of the node if present
3525 * Returns the string or NULL if not available. The result will be
3526 * deallocated on the next Read() operation.
3528 const xmlChar *
3529 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3530 xmlNodePtr node;
3531 if (reader == NULL)
3532 return(NULL);
3533 if (reader->node == NULL)
3534 return(NULL);
3535 if (reader->curnode != NULL)
3536 node = reader->curnode;
3537 else
3538 node = reader->node;
3540 switch (node->type) {
3541 case XML_NAMESPACE_DECL:
3542 return(((xmlNsPtr) node)->href);
3543 case XML_ATTRIBUTE_NODE:{
3544 xmlAttrPtr attr = (xmlAttrPtr) node;
3545 const xmlChar *ret;
3547 if ((attr->children != NULL) &&
3548 (attr->children->type == XML_TEXT_NODE) &&
3549 (attr->children->next == NULL))
3550 return(attr->children->content);
3551 else {
3552 if (reader->buffer == NULL) {
3553 reader->buffer = xmlBufCreateSize(100);
3554 if (reader->buffer == NULL) {
3555 xmlGenericError(xmlGenericErrorContext,
3556 "xmlTextReaderSetup : malloc failed\n");
3557 return (NULL);
3559 xmlBufSetAllocationScheme(reader->buffer,
3560 XML_BUFFER_ALLOC_DOUBLEIT);
3561 } else
3562 xmlBufEmpty(reader->buffer);
3563 xmlBufGetNodeContent(reader->buffer, node);
3564 ret = xmlBufContent(reader->buffer);
3565 if (ret == NULL) {
3566 /* error on the buffer best to reallocate */
3567 xmlBufFree(reader->buffer);
3568 reader->buffer = xmlBufCreateSize(100);
3569 xmlBufSetAllocationScheme(reader->buffer,
3570 XML_BUFFER_ALLOC_DOUBLEIT);
3571 ret = BAD_CAST "";
3573 return(ret);
3575 break;
3577 case XML_TEXT_NODE:
3578 case XML_CDATA_SECTION_NODE:
3579 case XML_PI_NODE:
3580 case XML_COMMENT_NODE:
3581 return(node->content);
3582 default:
3583 break;
3585 return(NULL);
3589 * xmlTextReaderIsDefault:
3590 * @reader: the xmlTextReaderPtr used
3592 * Whether an Attribute node was generated from the default value
3593 * defined in the DTD or schema.
3595 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3598 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3599 if (reader == NULL)
3600 return(-1);
3601 return(0);
3605 * xmlTextReaderQuoteChar:
3606 * @reader: the xmlTextReaderPtr used
3608 * The quotation mark character used to enclose the value of an attribute.
3610 * Returns " or ' and -1 in case of error
3613 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3614 if (reader == NULL)
3615 return(-1);
3616 /* TODO maybe lookup the attribute value for " first */
3617 return('"');
3621 * xmlTextReaderXmlLang:
3622 * @reader: the xmlTextReaderPtr used
3624 * The xml:lang scope within which the node resides.
3626 * Returns the xml:lang value or NULL if none exists.,
3627 * if non NULL it need to be freed by the caller.
3629 xmlChar *
3630 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3631 if (reader == NULL)
3632 return(NULL);
3633 if (reader->node == NULL)
3634 return(NULL);
3635 return(xmlNodeGetLang(reader->node));
3639 * xmlTextReaderConstXmlLang:
3640 * @reader: the xmlTextReaderPtr used
3642 * The xml:lang scope within which the node resides.
3644 * Returns the xml:lang value or NULL if none exists.
3646 const xmlChar *
3647 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3648 xmlChar *tmp;
3649 const xmlChar *ret;
3651 if (reader == NULL)
3652 return(NULL);
3653 if (reader->node == NULL)
3654 return(NULL);
3655 tmp = xmlNodeGetLang(reader->node);
3656 if (tmp == NULL)
3657 return(NULL);
3658 ret = CONSTSTR(tmp);
3659 xmlFree(tmp);
3660 return(ret);
3664 * xmlTextReaderConstString:
3665 * @reader: the xmlTextReaderPtr used
3666 * @str: the string to intern.
3668 * Get an interned string from the reader, allows for example to
3669 * speedup string name comparisons
3671 * Returns an interned copy of the string or NULL in case of error. The
3672 * string will be deallocated with the reader.
3674 const xmlChar *
3675 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3676 if (reader == NULL)
3677 return(NULL);
3678 return(CONSTSTR(str));
3682 * xmlTextReaderNormalization:
3683 * @reader: the xmlTextReaderPtr used
3685 * The value indicating whether to normalize white space and attribute values.
3686 * Since attribute value and end of line normalizations are a MUST in the XML
3687 * specification only the value true is accepted. The broken behaviour of
3688 * accepting out of range character entities like &#0; is of course not
3689 * supported either.
3691 * Returns 1 or -1 in case of error.
3694 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3695 if (reader == NULL)
3696 return(-1);
3697 return(1);
3700 /************************************************************************
3702 * Extensions to the base APIs *
3704 ************************************************************************/
3707 * xmlTextReaderSetParserProp:
3708 * @reader: the xmlTextReaderPtr used
3709 * @prop: the xmlParserProperties to set
3710 * @value: usually 0 or 1 to (de)activate it
3712 * Change the parser processing behaviour by changing some of its internal
3713 * properties. Note that some properties can only be changed before any
3714 * read has been done.
3716 * Returns 0 if the call was successful, or -1 in case of error
3719 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3720 xmlParserProperties p = (xmlParserProperties) prop;
3721 xmlParserCtxtPtr ctxt;
3723 if ((reader == NULL) || (reader->ctxt == NULL))
3724 return(-1);
3725 ctxt = reader->ctxt;
3727 switch (p) {
3728 case XML_PARSER_LOADDTD:
3729 if (value != 0) {
3730 if (ctxt->loadsubset == 0) {
3731 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3732 return(-1);
3733 ctxt->loadsubset = XML_DETECT_IDS;
3735 } else {
3736 ctxt->loadsubset = 0;
3738 return(0);
3739 case XML_PARSER_DEFAULTATTRS:
3740 if (value != 0) {
3741 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3742 } else {
3743 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3744 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3746 return(0);
3747 case XML_PARSER_VALIDATE:
3748 if (value != 0) {
3749 ctxt->options |= XML_PARSE_DTDVALID;
3750 ctxt->validate = 1;
3751 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3752 } else {
3753 ctxt->options &= ~XML_PARSE_DTDVALID;
3754 ctxt->validate = 0;
3756 return(0);
3757 case XML_PARSER_SUBST_ENTITIES:
3758 if (value != 0) {
3759 ctxt->options |= XML_PARSE_NOENT;
3760 ctxt->replaceEntities = 1;
3761 } else {
3762 ctxt->options &= ~XML_PARSE_NOENT;
3763 ctxt->replaceEntities = 0;
3765 return(0);
3767 return(-1);
3771 * xmlTextReaderGetParserProp:
3772 * @reader: the xmlTextReaderPtr used
3773 * @prop: the xmlParserProperties to get
3775 * Read the parser internal property.
3777 * Returns the value, usually 0 or 1, or -1 in case of error.
3780 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3781 xmlParserProperties p = (xmlParserProperties) prop;
3782 xmlParserCtxtPtr ctxt;
3784 if ((reader == NULL) || (reader->ctxt == NULL))
3785 return(-1);
3786 ctxt = reader->ctxt;
3788 switch (p) {
3789 case XML_PARSER_LOADDTD:
3790 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3791 return(1);
3792 return(0);
3793 case XML_PARSER_DEFAULTATTRS:
3794 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3795 return(1);
3796 return(0);
3797 case XML_PARSER_VALIDATE:
3798 return(reader->validate);
3799 case XML_PARSER_SUBST_ENTITIES:
3800 return(ctxt->replaceEntities);
3802 return(-1);
3807 * xmlTextReaderGetParserLineNumber:
3808 * @reader: the user data (XML reader context)
3810 * Provide the line number of the current parsing point.
3812 * Returns an int or 0 if not available
3815 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3817 if ((reader == NULL) || (reader->ctxt == NULL) ||
3818 (reader->ctxt->input == NULL)) {
3819 return (0);
3821 return (reader->ctxt->input->line);
3825 * xmlTextReaderGetParserColumnNumber:
3826 * @reader: the user data (XML reader context)
3828 * Provide the column number of the current parsing point.
3830 * Returns an int or 0 if not available
3833 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3835 if ((reader == NULL) || (reader->ctxt == NULL) ||
3836 (reader->ctxt->input == NULL)) {
3837 return (0);
3839 return (reader->ctxt->input->col);
3843 * xmlTextReaderCurrentNode:
3844 * @reader: the xmlTextReaderPtr used
3846 * Hacking interface allowing to get the xmlNodePtr corresponding to the
3847 * current node being accessed by the xmlTextReader. This is dangerous
3848 * because the underlying node may be destroyed on the next Reads.
3850 * Returns the xmlNodePtr or NULL in case of error.
3852 xmlNodePtr
3853 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3854 if (reader == NULL)
3855 return(NULL);
3857 if (reader->curnode != NULL)
3858 return(reader->curnode);
3859 return(reader->node);
3863 * xmlTextReaderPreserve:
3864 * @reader: the xmlTextReaderPtr used
3866 * This tells the XML Reader to preserve the current node.
3867 * The caller must also use xmlTextReaderCurrentDoc() to
3868 * keep an handle on the resulting document once parsing has finished
3870 * Returns the xmlNodePtr or NULL in case of error.
3872 xmlNodePtr
3873 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3874 xmlNodePtr cur, parent;
3876 if (reader == NULL)
3877 return(NULL);
3879 if (reader->curnode != NULL)
3880 cur = reader->curnode;
3881 else
3882 cur = reader->node;
3883 if (cur == NULL)
3884 return(NULL);
3886 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3887 cur->extra |= NODE_IS_PRESERVED;
3888 cur->extra |= NODE_IS_SPRESERVED;
3890 reader->preserves++;
3892 parent = cur->parent;;
3893 while (parent != NULL) {
3894 if (parent->type == XML_ELEMENT_NODE)
3895 parent->extra |= NODE_IS_PRESERVED;
3896 parent = parent->parent;
3898 return(cur);
3901 #ifdef LIBXML_PATTERN_ENABLED
3903 * xmlTextReaderPreservePattern:
3904 * @reader: the xmlTextReaderPtr used
3905 * @pattern: an XPath subset pattern
3906 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3908 * This tells the XML Reader to preserve all nodes matched by the
3909 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3910 * keep an handle on the resulting document once parsing has finished
3912 * Returns a non-negative number in case of success and -1 in case of error
3915 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3916 const xmlChar **namespaces)
3918 xmlPatternPtr comp;
3920 if ((reader == NULL) || (pattern == NULL))
3921 return(-1);
3923 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3924 if (comp == NULL)
3925 return(-1);
3927 if (reader->patternMax <= 0) {
3928 reader->patternMax = 4;
3929 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3930 sizeof(reader->patternTab[0]));
3931 if (reader->patternTab == NULL) {
3932 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3933 return (-1);
3936 if (reader->patternNr >= reader->patternMax) {
3937 xmlPatternPtr *tmp;
3938 reader->patternMax *= 2;
3939 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3940 reader->patternMax *
3941 sizeof(reader->patternTab[0]));
3942 if (tmp == NULL) {
3943 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3944 reader->patternMax /= 2;
3945 return (-1);
3947 reader->patternTab = tmp;
3949 reader->patternTab[reader->patternNr] = comp;
3950 return(reader->patternNr++);
3952 #endif
3955 * xmlTextReaderCurrentDoc:
3956 * @reader: the xmlTextReaderPtr used
3958 * Hacking interface allowing to get the xmlDocPtr corresponding to the
3959 * current document being accessed by the xmlTextReader.
3960 * NOTE: as a result of this call, the reader will not destroy the
3961 * associated XML document and calling xmlFreeDoc() on the result
3962 * is needed once the reader parsing has finished.
3964 * Returns the xmlDocPtr or NULL in case of error.
3966 xmlDocPtr
3967 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
3968 if (reader == NULL)
3969 return(NULL);
3970 if (reader->doc != NULL)
3971 return(reader->doc);
3972 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
3973 return(NULL);
3975 reader->preserve = 1;
3976 return(reader->ctxt->myDoc);
3979 #ifdef LIBXML_SCHEMAS_ENABLED
3980 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
3982 static void XMLCDECL
3983 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3985 static void XMLCDECL
3986 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3988 static void XMLCDECL
3989 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3991 static void XMLCDECL
3992 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3994 static void XMLCDECL
3995 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
3997 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3999 char *str;
4001 va_list ap;
4003 va_start(ap, msg);
4004 str = xmlTextReaderBuildMessage(msg, ap);
4005 if (!reader->errorFunc) {
4006 xmlTextReaderValidityError(ctx, "%s", str);
4007 } else {
4008 reader->errorFunc(reader->errorFuncArg, str,
4009 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4010 NULL /* locator */ );
4012 if (str != NULL)
4013 xmlFree(str);
4014 va_end(ap);
4017 static void XMLCDECL
4018 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4020 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4022 char *str;
4024 va_list ap;
4026 va_start(ap, msg);
4027 str = xmlTextReaderBuildMessage(msg, ap);
4028 if (!reader->errorFunc) {
4029 xmlTextReaderValidityWarning(ctx, "%s", str);
4030 } else {
4031 reader->errorFunc(reader->errorFuncArg, str,
4032 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4033 NULL /* locator */ );
4035 if (str != NULL)
4036 xmlFree(str);
4037 va_end(ap);
4040 static void
4041 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4043 static void
4044 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4046 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4048 if (reader->sErrorFunc) {
4049 reader->sErrorFunc(reader->errorFuncArg, error);
4050 } else {
4051 xmlTextReaderStructuredError(reader, error);
4055 * xmlTextReaderRelaxNGSetSchema:
4056 * @reader: the xmlTextReaderPtr used
4057 * @schema: a precompiled RelaxNG schema
4059 * Use RelaxNG to validate the document as it is processed.
4060 * Activation is only possible before the first Read().
4061 * if @schema is NULL, then RelaxNG validation is deactivated.
4062 @ The @schema should not be freed until the reader is deallocated
4063 * or its use has been deactivated.
4065 * Returns 0 in case the RelaxNG validation could be (de)activated and
4066 * -1 in case of error.
4069 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4070 if (reader == NULL)
4071 return(-1);
4072 if (schema == NULL) {
4073 if (reader->rngSchemas != NULL) {
4074 xmlRelaxNGFree(reader->rngSchemas);
4075 reader->rngSchemas = NULL;
4077 if (reader->rngValidCtxt != NULL) {
4078 if (! reader->rngPreserveCtxt)
4079 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4080 reader->rngValidCtxt = NULL;
4082 reader->rngPreserveCtxt = 0;
4083 return(0);
4085 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4086 return(-1);
4087 if (reader->rngSchemas != NULL) {
4088 xmlRelaxNGFree(reader->rngSchemas);
4089 reader->rngSchemas = NULL;
4091 if (reader->rngValidCtxt != NULL) {
4092 if (! reader->rngPreserveCtxt)
4093 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4094 reader->rngValidCtxt = NULL;
4096 reader->rngPreserveCtxt = 0;
4097 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4098 if (reader->rngValidCtxt == NULL)
4099 return(-1);
4100 if (reader->errorFunc != NULL) {
4101 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4102 xmlTextReaderValidityErrorRelay,
4103 xmlTextReaderValidityWarningRelay,
4104 reader);
4106 if (reader->sErrorFunc != NULL) {
4107 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4108 xmlTextReaderValidityStructuredRelay,
4109 reader);
4111 reader->rngValidErrors = 0;
4112 reader->rngFullNode = NULL;
4113 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4114 return(0);
4118 * xmlTextReaderLocator:
4119 * @ctx: the xmlTextReaderPtr used
4120 * @file: returned file information
4121 * @line: returned line information
4123 * Internal locator function for the readers
4125 * Returns 0 in case the Schema validation could be (de)activated and
4126 * -1 in case of error.
4128 static int
4129 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4130 xmlTextReaderPtr reader;
4132 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4133 return(-1);
4135 if (file != NULL)
4136 *file = NULL;
4137 if (line != NULL)
4138 *line = 0;
4140 reader = (xmlTextReaderPtr) ctx;
4141 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4142 if (file != NULL)
4143 *file = reader->ctxt->input->filename;
4144 if (line != NULL)
4145 *line = reader->ctxt->input->line;
4146 return(0);
4148 if (reader->node != NULL) {
4149 long res;
4150 int ret = 0;
4152 if (line != NULL) {
4153 res = xmlGetLineNo(reader->node);
4154 if (res > 0)
4155 *line = (unsigned long) res;
4156 else
4157 ret = -1;
4159 if (file != NULL) {
4160 xmlDocPtr doc = reader->node->doc;
4161 if ((doc != NULL) && (doc->URL != NULL))
4162 *file = (const char *) doc->URL;
4163 else
4164 ret = -1;
4166 return(ret);
4168 return(-1);
4172 * xmlTextReaderSetSchema:
4173 * @reader: the xmlTextReaderPtr used
4174 * @schema: a precompiled Schema schema
4176 * Use XSD Schema to validate the document as it is processed.
4177 * Activation is only possible before the first Read().
4178 * if @schema is NULL, then Schema validation is deactivated.
4179 * The @schema should not be freed until the reader is deallocated
4180 * or its use has been deactivated.
4182 * Returns 0 in case the Schema validation could be (de)activated and
4183 * -1 in case of error.
4186 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4187 if (reader == NULL)
4188 return(-1);
4189 if (schema == NULL) {
4190 if (reader->xsdPlug != NULL) {
4191 xmlSchemaSAXUnplug(reader->xsdPlug);
4192 reader->xsdPlug = NULL;
4194 if (reader->xsdValidCtxt != NULL) {
4195 if (! reader->xsdPreserveCtxt)
4196 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4197 reader->xsdValidCtxt = NULL;
4199 reader->xsdPreserveCtxt = 0;
4200 if (reader->xsdSchemas != NULL) {
4201 xmlSchemaFree(reader->xsdSchemas);
4202 reader->xsdSchemas = NULL;
4204 return(0);
4206 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4207 return(-1);
4208 if (reader->xsdPlug != NULL) {
4209 xmlSchemaSAXUnplug(reader->xsdPlug);
4210 reader->xsdPlug = NULL;
4212 if (reader->xsdValidCtxt != NULL) {
4213 if (! reader->xsdPreserveCtxt)
4214 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4215 reader->xsdValidCtxt = NULL;
4217 reader->xsdPreserveCtxt = 0;
4218 if (reader->xsdSchemas != NULL) {
4219 xmlSchemaFree(reader->xsdSchemas);
4220 reader->xsdSchemas = NULL;
4222 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4223 if (reader->xsdValidCtxt == NULL) {
4224 xmlSchemaFree(reader->xsdSchemas);
4225 reader->xsdSchemas = NULL;
4226 return(-1);
4228 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4229 &(reader->ctxt->sax),
4230 &(reader->ctxt->userData));
4231 if (reader->xsdPlug == NULL) {
4232 xmlSchemaFree(reader->xsdSchemas);
4233 reader->xsdSchemas = NULL;
4234 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4235 reader->xsdValidCtxt = NULL;
4236 return(-1);
4238 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4239 xmlTextReaderLocator,
4240 (void *) reader);
4242 if (reader->errorFunc != NULL) {
4243 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4244 xmlTextReaderValidityErrorRelay,
4245 xmlTextReaderValidityWarningRelay,
4246 reader);
4248 if (reader->sErrorFunc != NULL) {
4249 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4250 xmlTextReaderValidityStructuredRelay,
4251 reader);
4253 reader->xsdValidErrors = 0;
4254 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4255 return(0);
4259 * xmlTextReaderRelaxNGValidateInternal:
4260 * @reader: the xmlTextReaderPtr used
4261 * @rng: the path to a RelaxNG schema or NULL
4262 * @ctxt: the RelaxNG schema validation context or NULL
4263 * @options: options (not yet used)
4265 * Use RelaxNG to validate the document as it is processed.
4266 * Activation is only possible before the first Read().
4267 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4269 * Returns 0 in case the RelaxNG validation could be (de)activated and
4270 * -1 in case of error.
4272 static int
4273 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4274 const char *rng,
4275 xmlRelaxNGValidCtxtPtr ctxt,
4276 int options ATTRIBUTE_UNUSED)
4278 if (reader == NULL)
4279 return(-1);
4281 if ((rng != NULL) && (ctxt != NULL))
4282 return (-1);
4284 if (((rng != NULL) || (ctxt != NULL)) &&
4285 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4286 (reader->ctxt == NULL)))
4287 return(-1);
4289 /* Cleanup previous validation stuff. */
4290 if (reader->rngValidCtxt != NULL) {
4291 if ( !reader->rngPreserveCtxt)
4292 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4293 reader->rngValidCtxt = NULL;
4295 reader->rngPreserveCtxt = 0;
4296 if (reader->rngSchemas != NULL) {
4297 xmlRelaxNGFree(reader->rngSchemas);
4298 reader->rngSchemas = NULL;
4301 if ((rng == NULL) && (ctxt == NULL)) {
4302 /* We just want to deactivate the validation, so get out. */
4303 return(0);
4307 if (rng != NULL) {
4308 xmlRelaxNGParserCtxtPtr pctxt;
4309 /* Parse the schema and create validation environment. */
4311 pctxt = xmlRelaxNGNewParserCtxt(rng);
4312 if (reader->errorFunc != NULL) {
4313 xmlRelaxNGSetParserErrors(pctxt,
4314 xmlTextReaderValidityErrorRelay,
4315 xmlTextReaderValidityWarningRelay,
4316 reader);
4318 if (reader->sErrorFunc != NULL) {
4319 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4320 xmlTextReaderValidityStructuredRelay,
4321 reader);
4323 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4324 xmlRelaxNGFreeParserCtxt(pctxt);
4325 if (reader->rngSchemas == NULL)
4326 return(-1);
4327 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4328 if (reader->rngValidCtxt == NULL) {
4329 xmlRelaxNGFree(reader->rngSchemas);
4330 reader->rngSchemas = NULL;
4331 return(-1);
4333 } else {
4334 /* Use the given validation context. */
4335 reader->rngValidCtxt = ctxt;
4336 reader->rngPreserveCtxt = 1;
4339 * Redirect the validation context's error channels to use
4340 * the reader channels.
4341 * TODO: In case the user provides the validation context we
4342 * could make this redirection optional.
4344 if (reader->errorFunc != NULL) {
4345 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4346 xmlTextReaderValidityErrorRelay,
4347 xmlTextReaderValidityWarningRelay,
4348 reader);
4350 if (reader->sErrorFunc != NULL) {
4351 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4352 xmlTextReaderValidityStructuredRelay,
4353 reader);
4355 reader->rngValidErrors = 0;
4356 reader->rngFullNode = NULL;
4357 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4358 return(0);
4362 * xmlTextReaderSchemaValidateInternal:
4363 * @reader: the xmlTextReaderPtr used
4364 * @xsd: the path to a W3C XSD schema or NULL
4365 * @ctxt: the XML Schema validation context or NULL
4366 * @options: options (not used yet)
4368 * Validate the document as it is processed using XML Schema.
4369 * Activation is only possible before the first Read().
4370 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4372 * Returns 0 in case the schemas validation could be (de)activated and
4373 * -1 in case of error.
4375 static int
4376 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4377 const char *xsd,
4378 xmlSchemaValidCtxtPtr ctxt,
4379 int options ATTRIBUTE_UNUSED)
4381 if (reader == NULL)
4382 return(-1);
4384 if ((xsd != NULL) && (ctxt != NULL))
4385 return(-1);
4387 if (((xsd != NULL) || (ctxt != NULL)) &&
4388 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4389 (reader->ctxt == NULL)))
4390 return(-1);
4392 /* Cleanup previous validation stuff. */
4393 if (reader->xsdPlug != NULL) {
4394 xmlSchemaSAXUnplug(reader->xsdPlug);
4395 reader->xsdPlug = NULL;
4397 if (reader->xsdValidCtxt != NULL) {
4398 if (! reader->xsdPreserveCtxt)
4399 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4400 reader->xsdValidCtxt = NULL;
4402 reader->xsdPreserveCtxt = 0;
4403 if (reader->xsdSchemas != NULL) {
4404 xmlSchemaFree(reader->xsdSchemas);
4405 reader->xsdSchemas = NULL;
4408 if ((xsd == NULL) && (ctxt == NULL)) {
4409 /* We just want to deactivate the validation, so get out. */
4410 return(0);
4413 if (xsd != NULL) {
4414 xmlSchemaParserCtxtPtr pctxt;
4415 /* Parse the schema and create validation environment. */
4416 pctxt = xmlSchemaNewParserCtxt(xsd);
4417 if (reader->errorFunc != NULL) {
4418 xmlSchemaSetParserErrors(pctxt,
4419 xmlTextReaderValidityErrorRelay,
4420 xmlTextReaderValidityWarningRelay,
4421 reader);
4423 reader->xsdSchemas = xmlSchemaParse(pctxt);
4424 xmlSchemaFreeParserCtxt(pctxt);
4425 if (reader->xsdSchemas == NULL)
4426 return(-1);
4427 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4428 if (reader->xsdValidCtxt == NULL) {
4429 xmlSchemaFree(reader->xsdSchemas);
4430 reader->xsdSchemas = NULL;
4431 return(-1);
4433 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4434 &(reader->ctxt->sax),
4435 &(reader->ctxt->userData));
4436 if (reader->xsdPlug == NULL) {
4437 xmlSchemaFree(reader->xsdSchemas);
4438 reader->xsdSchemas = NULL;
4439 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4440 reader->xsdValidCtxt = NULL;
4441 return(-1);
4443 } else {
4444 /* Use the given validation context. */
4445 reader->xsdValidCtxt = ctxt;
4446 reader->xsdPreserveCtxt = 1;
4447 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4448 &(reader->ctxt->sax),
4449 &(reader->ctxt->userData));
4450 if (reader->xsdPlug == NULL) {
4451 reader->xsdValidCtxt = NULL;
4452 reader->xsdPreserveCtxt = 0;
4453 return(-1);
4456 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4457 xmlTextReaderLocator,
4458 (void *) reader);
4460 * Redirect the validation context's error channels to use
4461 * the reader channels.
4462 * TODO: In case the user provides the validation context we
4463 * could make this redirection optional.
4465 if (reader->errorFunc != NULL) {
4466 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4467 xmlTextReaderValidityErrorRelay,
4468 xmlTextReaderValidityWarningRelay,
4469 reader);
4471 if (reader->sErrorFunc != NULL) {
4472 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4473 xmlTextReaderValidityStructuredRelay,
4474 reader);
4476 reader->xsdValidErrors = 0;
4477 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4478 return(0);
4482 * xmlTextReaderSchemaValidateCtxt:
4483 * @reader: the xmlTextReaderPtr used
4484 * @ctxt: the XML Schema validation context or NULL
4485 * @options: options (not used yet)
4487 * Use W3C XSD schema context to validate the document as it is processed.
4488 * Activation is only possible before the first Read().
4489 * If @ctxt is NULL, then XML Schema validation is deactivated.
4491 * Returns 0 in case the schemas validation could be (de)activated and
4492 * -1 in case of error.
4495 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4496 xmlSchemaValidCtxtPtr ctxt,
4497 int options)
4499 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4503 * xmlTextReaderSchemaValidate:
4504 * @reader: the xmlTextReaderPtr used
4505 * @xsd: the path to a W3C XSD schema or NULL
4507 * Use W3C XSD schema to validate the document as it is processed.
4508 * Activation is only possible before the first Read().
4509 * If @xsd is NULL, then XML Schema validation is deactivated.
4511 * Returns 0 in case the schemas validation could be (de)activated and
4512 * -1 in case of error.
4515 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4517 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4521 * xmlTextReaderRelaxNGValidateCtxt:
4522 * @reader: the xmlTextReaderPtr used
4523 * @ctxt: the RelaxNG schema validation context or NULL
4524 * @options: options (not used yet)
4526 * Use RelaxNG schema context to validate the document as it is processed.
4527 * Activation is only possible before the first Read().
4528 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4530 * Returns 0 in case the schemas validation could be (de)activated and
4531 * -1 in case of error.
4534 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4535 xmlRelaxNGValidCtxtPtr ctxt,
4536 int options)
4538 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4542 * xmlTextReaderRelaxNGValidate:
4543 * @reader: the xmlTextReaderPtr used
4544 * @rng: the path to a RelaxNG schema or NULL
4546 * Use RelaxNG schema to validate the document as it is processed.
4547 * Activation is only possible before the first Read().
4548 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4550 * Returns 0 in case the schemas validation could be (de)activated and
4551 * -1 in case of error.
4554 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4556 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4559 #endif
4562 * xmlTextReaderIsNamespaceDecl:
4563 * @reader: the xmlTextReaderPtr used
4565 * Determine whether the current node is a namespace declaration
4566 * rather than a regular attribute.
4568 * Returns 1 if the current node is a namespace declaration, 0 if it
4569 * is a regular attribute or other type of node, or -1 in case of
4570 * error.
4573 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4574 xmlNodePtr node;
4575 if (reader == NULL)
4576 return(-1);
4577 if (reader->node == NULL)
4578 return(-1);
4579 if (reader->curnode != NULL)
4580 node = reader->curnode;
4581 else
4582 node = reader->node;
4584 if (XML_NAMESPACE_DECL == node->type)
4585 return(1);
4586 else
4587 return(0);
4591 * xmlTextReaderConstXmlVersion:
4592 * @reader: the xmlTextReaderPtr used
4594 * Determine the XML version of the document being read.
4596 * Returns a string containing the XML version of the document or NULL
4597 * in case of error. The string is deallocated with the reader.
4599 const xmlChar *
4600 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4601 xmlDocPtr doc = NULL;
4602 if (reader == NULL)
4603 return(NULL);
4604 if (reader->doc != NULL)
4605 doc = reader->doc;
4606 else if (reader->ctxt != NULL)
4607 doc = reader->ctxt->myDoc;
4608 if (doc == NULL)
4609 return(NULL);
4611 if (doc->version == NULL)
4612 return(NULL);
4613 else
4614 return(CONSTSTR(doc->version));
4618 * xmlTextReaderStandalone:
4619 * @reader: the xmlTextReaderPtr used
4621 * Determine the standalone status of the document being read.
4623 * Returns 1 if the document was declared to be standalone, 0 if it
4624 * was declared to be not standalone, or -1 if the document did not
4625 * specify its standalone status or in case of error.
4628 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4629 xmlDocPtr doc = NULL;
4630 if (reader == NULL)
4631 return(-1);
4632 if (reader->doc != NULL)
4633 doc = reader->doc;
4634 else if (reader->ctxt != NULL)
4635 doc = reader->ctxt->myDoc;
4636 if (doc == NULL)
4637 return(-1);
4639 return(doc->standalone);
4642 /************************************************************************
4644 * Error Handling Extensions *
4646 ************************************************************************/
4648 /* helper to build a xmlMalloc'ed string from a format and va_list */
4649 static char *
4650 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4651 int size = 0;
4652 int chars;
4653 char *larger;
4654 char *str = NULL;
4655 va_list aq;
4657 while (1) {
4658 VA_COPY(aq, ap);
4659 chars = vsnprintf(str, size, msg, aq);
4660 va_end(aq);
4661 if (chars < 0) {
4662 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4663 if (str)
4664 xmlFree(str);
4665 return NULL;
4667 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4668 break;
4669 if (chars < MAX_ERR_MSG_SIZE)
4670 size = chars + 1;
4671 else
4672 size = MAX_ERR_MSG_SIZE;
4673 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4674 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4675 if (str)
4676 xmlFree(str);
4677 return NULL;
4679 str = larger;
4682 return str;
4686 * xmlTextReaderLocatorLineNumber:
4687 * @locator: the xmlTextReaderLocatorPtr used
4689 * Obtain the line number for the given locator.
4691 * Returns the line number or -1 in case of error.
4694 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4695 /* we know that locator is a xmlParserCtxtPtr */
4696 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4697 int ret = -1;
4699 if (locator == NULL)
4700 return(-1);
4701 if (ctx->node != NULL) {
4702 ret = xmlGetLineNo(ctx->node);
4704 else {
4705 /* inspired from error.c */
4706 xmlParserInputPtr input;
4707 input = ctx->input;
4708 if ((input->filename == NULL) && (ctx->inputNr > 1))
4709 input = ctx->inputTab[ctx->inputNr - 2];
4710 if (input != NULL) {
4711 ret = input->line;
4713 else {
4714 ret = -1;
4718 return ret;
4722 * xmlTextReaderLocatorBaseURI:
4723 * @locator: the xmlTextReaderLocatorPtr used
4725 * Obtain the base URI for the given locator.
4727 * Returns the base URI or NULL in case of error,
4728 * if non NULL it need to be freed by the caller.
4730 xmlChar *
4731 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4732 /* we know that locator is a xmlParserCtxtPtr */
4733 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4734 xmlChar *ret = NULL;
4736 if (locator == NULL)
4737 return(NULL);
4738 if (ctx->node != NULL) {
4739 ret = xmlNodeGetBase(NULL,ctx->node);
4741 else {
4742 /* inspired from error.c */
4743 xmlParserInputPtr input;
4744 input = ctx->input;
4745 if ((input->filename == NULL) && (ctx->inputNr > 1))
4746 input = ctx->inputTab[ctx->inputNr - 2];
4747 if (input != NULL) {
4748 ret = xmlStrdup(BAD_CAST input->filename);
4750 else {
4751 ret = NULL;
4755 return ret;
4758 static void
4759 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4760 char *str)
4762 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4764 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4766 if (str != NULL) {
4767 if (reader->errorFunc)
4768 reader->errorFunc(reader->errorFuncArg, str, severity,
4769 (xmlTextReaderLocatorPtr) ctx);
4770 xmlFree(str);
4774 static void
4775 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4777 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4779 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4781 if (error && reader->sErrorFunc) {
4782 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4786 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4787 xmlTextReaderError(void *ctxt, const char *msg, ...)
4789 va_list ap;
4791 va_start(ap, msg);
4792 xmlTextReaderGenericError(ctxt,
4793 XML_PARSER_SEVERITY_ERROR,
4794 xmlTextReaderBuildMessage(msg, ap));
4795 va_end(ap);
4799 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4800 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4802 va_list ap;
4804 va_start(ap, msg);
4805 xmlTextReaderGenericError(ctxt,
4806 XML_PARSER_SEVERITY_WARNING,
4807 xmlTextReaderBuildMessage(msg, ap));
4808 va_end(ap);
4811 static void XMLCDECL
4812 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4814 va_list ap;
4816 int len = xmlStrlen((const xmlChar *) msg);
4818 if ((len > 1) && (msg[len - 2] != ':')) {
4820 * some callbacks only report locator information:
4821 * skip them (mimicking behaviour in error.c)
4823 va_start(ap, msg);
4824 xmlTextReaderGenericError(ctxt,
4825 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4826 xmlTextReaderBuildMessage(msg, ap));
4827 va_end(ap);
4831 static void XMLCDECL
4832 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4834 va_list ap;
4836 int len = xmlStrlen((const xmlChar *) msg);
4838 if ((len != 0) && (msg[len - 1] != ':')) {
4840 * some callbacks only report locator information:
4841 * skip them (mimicking behaviour in error.c)
4843 va_start(ap, msg);
4844 xmlTextReaderGenericError(ctxt,
4845 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4846 xmlTextReaderBuildMessage(msg, ap));
4847 va_end(ap);
4852 * xmlTextReaderSetErrorHandler:
4853 * @reader: the xmlTextReaderPtr used
4854 * @f: the callback function to call on error and warnings
4855 * @arg: a user argument to pass to the callback function
4857 * Register a callback function that will be called on error and warnings.
4859 * If @f is NULL, the default error and warning handlers are restored.
4861 void
4862 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4863 xmlTextReaderErrorFunc f, void *arg)
4865 if (f != NULL) {
4866 reader->ctxt->sax->error = xmlTextReaderError;
4867 reader->ctxt->sax->serror = NULL;
4868 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4869 reader->ctxt->sax->warning = xmlTextReaderWarning;
4870 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4871 reader->errorFunc = f;
4872 reader->sErrorFunc = NULL;
4873 reader->errorFuncArg = arg;
4874 #ifdef LIBXML_SCHEMAS_ENABLED
4875 if (reader->rngValidCtxt) {
4876 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4877 xmlTextReaderValidityErrorRelay,
4878 xmlTextReaderValidityWarningRelay,
4879 reader);
4880 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4881 reader);
4883 if (reader->xsdValidCtxt) {
4884 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4885 xmlTextReaderValidityErrorRelay,
4886 xmlTextReaderValidityWarningRelay,
4887 reader);
4888 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4889 reader);
4891 #endif
4892 } else {
4893 /* restore defaults */
4894 reader->ctxt->sax->error = xmlParserError;
4895 reader->ctxt->vctxt.error = xmlParserValidityError;
4896 reader->ctxt->sax->warning = xmlParserWarning;
4897 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4898 reader->errorFunc = NULL;
4899 reader->sErrorFunc = NULL;
4900 reader->errorFuncArg = NULL;
4901 #ifdef LIBXML_SCHEMAS_ENABLED
4902 if (reader->rngValidCtxt) {
4903 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4904 reader);
4905 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4906 reader);
4908 if (reader->xsdValidCtxt) {
4909 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4910 reader);
4911 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4912 reader);
4914 #endif
4919 * xmlTextReaderSetStructuredErrorHandler:
4920 * @reader: the xmlTextReaderPtr used
4921 * @f: the callback function to call on error and warnings
4922 * @arg: a user argument to pass to the callback function
4924 * Register a callback function that will be called on error and warnings.
4926 * If @f is NULL, the default error and warning handlers are restored.
4928 void
4929 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4930 xmlStructuredErrorFunc f, void *arg)
4932 if (f != NULL) {
4933 reader->ctxt->sax->error = NULL;
4934 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4935 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4936 reader->ctxt->sax->warning = xmlTextReaderWarning;
4937 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4938 reader->sErrorFunc = f;
4939 reader->errorFunc = NULL;
4940 reader->errorFuncArg = arg;
4941 #ifdef LIBXML_SCHEMAS_ENABLED
4942 if (reader->rngValidCtxt) {
4943 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4944 reader);
4945 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4946 xmlTextReaderValidityStructuredRelay,
4947 reader);
4949 if (reader->xsdValidCtxt) {
4950 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4951 reader);
4952 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4953 xmlTextReaderValidityStructuredRelay,
4954 reader);
4956 #endif
4957 } else {
4958 /* restore defaults */
4959 reader->ctxt->sax->error = xmlParserError;
4960 reader->ctxt->sax->serror = NULL;
4961 reader->ctxt->vctxt.error = xmlParserValidityError;
4962 reader->ctxt->sax->warning = xmlParserWarning;
4963 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4964 reader->errorFunc = NULL;
4965 reader->sErrorFunc = NULL;
4966 reader->errorFuncArg = NULL;
4967 #ifdef LIBXML_SCHEMAS_ENABLED
4968 if (reader->rngValidCtxt) {
4969 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4970 reader);
4971 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4972 reader);
4974 if (reader->xsdValidCtxt) {
4975 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4976 reader);
4977 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4978 reader);
4980 #endif
4985 * xmlTextReaderIsValid:
4986 * @reader: the xmlTextReaderPtr used
4988 * Retrieve the validity status from the parser context
4990 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4993 xmlTextReaderIsValid(xmlTextReaderPtr reader)
4995 if (reader == NULL)
4996 return (-1);
4997 #ifdef LIBXML_SCHEMAS_ENABLED
4998 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4999 return (reader->rngValidErrors == 0);
5000 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5001 return (reader->xsdValidErrors == 0);
5002 #endif
5003 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5004 return (reader->ctxt->valid);
5005 return (0);
5009 * xmlTextReaderGetErrorHandler:
5010 * @reader: the xmlTextReaderPtr used
5011 * @f: the callback function or NULL is no callback has been registered
5012 * @arg: a user argument
5014 * Retrieve the error callback function and user argument.
5016 void
5017 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5018 xmlTextReaderErrorFunc * f, void **arg)
5020 if (f != NULL)
5021 *f = reader->errorFunc;
5022 if (arg != NULL)
5023 *arg = reader->errorFuncArg;
5025 /************************************************************************
5027 * New set (2.6.0) of simpler and more flexible APIs *
5029 ************************************************************************/
5032 * xmlTextReaderSetup:
5033 * @reader: an XML reader
5034 * @input: xmlParserInputBufferPtr used to feed the reader, will
5035 * be destroyed with it.
5036 * @URL: the base URL to use for the document
5037 * @encoding: the document encoding, or NULL
5038 * @options: a combination of xmlParserOption
5040 * Setup an XML reader with new options
5042 * Returns 0 in case of success and -1 in case of error.
5045 xmlTextReaderSetup(xmlTextReaderPtr reader,
5046 xmlParserInputBufferPtr input, const char *URL,
5047 const char *encoding, int options)
5049 if (reader == NULL) {
5050 if (input != NULL)
5051 xmlFreeParserInputBuffer(input);
5052 return (-1);
5056 * we force the generation of compact text nodes on the reader
5057 * since usr applications should never modify the tree
5059 options |= XML_PARSE_COMPACT;
5061 reader->doc = NULL;
5062 reader->entNr = 0;
5063 reader->parserFlags = options;
5064 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5065 if ((input != NULL) && (reader->input != NULL) &&
5066 (reader->allocs & XML_TEXTREADER_INPUT)) {
5067 xmlFreeParserInputBuffer(reader->input);
5068 reader->input = NULL;
5069 reader->allocs -= XML_TEXTREADER_INPUT;
5071 if (input != NULL) {
5072 reader->input = input;
5073 reader->allocs |= XML_TEXTREADER_INPUT;
5075 if (reader->buffer == NULL)
5076 reader->buffer = xmlBufCreateSize(100);
5077 if (reader->buffer == NULL) {
5078 xmlGenericError(xmlGenericErrorContext,
5079 "xmlTextReaderSetup : malloc failed\n");
5080 return (-1);
5082 /* no operation on a reader should require a huge buffer */
5083 xmlBufSetAllocationScheme(reader->buffer,
5084 XML_BUFFER_ALLOC_DOUBLEIT);
5085 if (reader->sax == NULL)
5086 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5087 if (reader->sax == NULL) {
5088 xmlGenericError(xmlGenericErrorContext,
5089 "xmlTextReaderSetup : malloc failed\n");
5090 return (-1);
5092 xmlSAXVersion(reader->sax, 2);
5093 reader->startElement = reader->sax->startElement;
5094 reader->sax->startElement = xmlTextReaderStartElement;
5095 reader->endElement = reader->sax->endElement;
5096 reader->sax->endElement = xmlTextReaderEndElement;
5097 #ifdef LIBXML_SAX1_ENABLED
5098 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5099 #endif /* LIBXML_SAX1_ENABLED */
5100 reader->startElementNs = reader->sax->startElementNs;
5101 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5102 reader->endElementNs = reader->sax->endElementNs;
5103 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5104 #ifdef LIBXML_SAX1_ENABLED
5105 } else {
5106 reader->startElementNs = NULL;
5107 reader->endElementNs = NULL;
5109 #endif /* LIBXML_SAX1_ENABLED */
5110 reader->characters = reader->sax->characters;
5111 reader->sax->characters = xmlTextReaderCharacters;
5112 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5113 reader->cdataBlock = reader->sax->cdataBlock;
5114 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5116 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5117 reader->node = NULL;
5118 reader->curnode = NULL;
5119 if (input != NULL) {
5120 if (xmlBufUse(reader->input->buffer) < 4) {
5121 xmlParserInputBufferRead(input, 4);
5123 if (reader->ctxt == NULL) {
5124 if (xmlBufUse(reader->input->buffer) >= 4) {
5125 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5126 (const char *) xmlBufContent(reader->input->buffer),
5127 4, URL);
5128 reader->base = 0;
5129 reader->cur = 4;
5130 } else {
5131 reader->ctxt =
5132 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5133 reader->base = 0;
5134 reader->cur = 0;
5136 } else {
5137 xmlParserInputPtr inputStream;
5138 xmlParserInputBufferPtr buf;
5139 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5141 xmlCtxtReset(reader->ctxt);
5142 buf = xmlAllocParserInputBuffer(enc);
5143 if (buf == NULL) return(-1);
5144 inputStream = xmlNewInputStream(reader->ctxt);
5145 if (inputStream == NULL) {
5146 xmlFreeParserInputBuffer(buf);
5147 return(-1);
5150 if (URL == NULL)
5151 inputStream->filename = NULL;
5152 else
5153 inputStream->filename = (char *)
5154 xmlCanonicPath((const xmlChar *) URL);
5155 inputStream->buf = buf;
5156 xmlBufResetInput(buf->buffer, inputStream);
5158 inputPush(reader->ctxt, inputStream);
5159 reader->cur = 0;
5161 if (reader->ctxt == NULL) {
5162 xmlGenericError(xmlGenericErrorContext,
5163 "xmlTextReaderSetup : malloc failed\n");
5164 return (-1);
5167 if (reader->dict != NULL) {
5168 if (reader->ctxt->dict != NULL) {
5169 if (reader->dict != reader->ctxt->dict) {
5170 xmlDictFree(reader->dict);
5171 reader->dict = reader->ctxt->dict;
5173 } else {
5174 reader->ctxt->dict = reader->dict;
5176 } else {
5177 if (reader->ctxt->dict == NULL)
5178 reader->ctxt->dict = xmlDictCreate();
5179 reader->dict = reader->ctxt->dict;
5181 reader->ctxt->_private = reader;
5182 reader->ctxt->linenumbers = 1;
5183 reader->ctxt->dictNames = 1;
5185 * use the parser dictionary to allocate all elements and attributes names
5187 reader->ctxt->docdict = 1;
5188 reader->ctxt->parseMode = XML_PARSE_READER;
5190 #ifdef LIBXML_XINCLUDE_ENABLED
5191 if (reader->xincctxt != NULL) {
5192 xmlXIncludeFreeContext(reader->xincctxt);
5193 reader->xincctxt = NULL;
5195 if (options & XML_PARSE_XINCLUDE) {
5196 reader->xinclude = 1;
5197 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5198 options -= XML_PARSE_XINCLUDE;
5199 } else
5200 reader->xinclude = 0;
5201 reader->in_xinclude = 0;
5202 #endif
5203 #ifdef LIBXML_PATTERN_ENABLED
5204 if (reader->patternTab == NULL) {
5205 reader->patternNr = 0;
5206 reader->patternMax = 0;
5208 while (reader->patternNr > 0) {
5209 reader->patternNr--;
5210 if (reader->patternTab[reader->patternNr] != NULL) {
5211 xmlFreePattern(reader->patternTab[reader->patternNr]);
5212 reader->patternTab[reader->patternNr] = NULL;
5215 #endif
5217 if (options & XML_PARSE_DTDVALID)
5218 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5220 xmlCtxtUseOptions(reader->ctxt, options);
5221 if (encoding != NULL) {
5222 xmlCharEncodingHandlerPtr hdlr;
5224 hdlr = xmlFindCharEncodingHandler(encoding);
5225 if (hdlr != NULL)
5226 xmlSwitchToEncoding(reader->ctxt, hdlr);
5228 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5229 (reader->ctxt->input->filename == NULL))
5230 reader->ctxt->input->filename = (char *)
5231 xmlStrdup((const xmlChar *) URL);
5233 reader->doc = NULL;
5235 return (0);
5239 * xmlTextReaderByteConsumed:
5240 * @reader: an XML reader
5242 * This function provides the current index of the parser used
5243 * by the reader, relative to the start of the current entity.
5244 * This function actually just wraps a call to xmlBytesConsumed()
5245 * for the parser context associated with the reader.
5246 * See xmlBytesConsumed() for more information.
5248 * Returns the index in bytes from the beginning of the entity or -1
5249 * in case the index could not be computed.
5251 long
5252 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5253 if ((reader == NULL) || (reader->ctxt == NULL))
5254 return(-1);
5255 return(xmlByteConsumed(reader->ctxt));
5260 * xmlReaderWalker:
5261 * @doc: a preparsed document
5263 * Create an xmltextReader for a preparsed document.
5265 * Returns the new reader or NULL in case of error.
5267 xmlTextReaderPtr
5268 xmlReaderWalker(xmlDocPtr doc)
5270 xmlTextReaderPtr ret;
5272 if (doc == NULL)
5273 return(NULL);
5275 ret = xmlMalloc(sizeof(xmlTextReader));
5276 if (ret == NULL) {
5277 xmlGenericError(xmlGenericErrorContext,
5278 "xmlNewTextReader : malloc failed\n");
5279 return(NULL);
5281 memset(ret, 0, sizeof(xmlTextReader));
5282 ret->entNr = 0;
5283 ret->input = NULL;
5284 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5285 ret->node = NULL;
5286 ret->curnode = NULL;
5287 ret->base = 0;
5288 ret->cur = 0;
5289 ret->allocs = XML_TEXTREADER_CTXT;
5290 ret->doc = doc;
5291 ret->state = XML_TEXTREADER_START;
5292 ret->dict = xmlDictCreate();
5293 return(ret);
5297 * xmlReaderForDoc:
5298 * @cur: a pointer to a zero terminated string
5299 * @URL: the base URL to use for the document
5300 * @encoding: the document encoding, or NULL
5301 * @options: a combination of xmlParserOption
5303 * Create an xmltextReader for an XML in-memory document.
5304 * The parsing flags @options are a combination of xmlParserOption.
5306 * Returns the new reader or NULL in case of error.
5308 xmlTextReaderPtr
5309 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5310 int options)
5312 int len;
5314 if (cur == NULL)
5315 return (NULL);
5316 len = xmlStrlen(cur);
5318 return (xmlReaderForMemory
5319 ((const char *) cur, len, URL, encoding, options));
5323 * xmlReaderForFile:
5324 * @filename: a file or URL
5325 * @encoding: the document encoding, or NULL
5326 * @options: a combination of xmlParserOption
5328 * parse an XML file from the filesystem or the network.
5329 * The parsing flags @options are a combination of xmlParserOption.
5331 * Returns the new reader or NULL in case of error.
5333 xmlTextReaderPtr
5334 xmlReaderForFile(const char *filename, const char *encoding, int options)
5336 xmlTextReaderPtr reader;
5338 reader = xmlNewTextReaderFilename(filename);
5339 if (reader == NULL)
5340 return (NULL);
5341 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5342 return (reader);
5346 * xmlReaderForMemory:
5347 * @buffer: a pointer to a char array
5348 * @size: the size of the array
5349 * @URL: the base URL to use for the document
5350 * @encoding: the document encoding, or NULL
5351 * @options: a combination of xmlParserOption
5353 * Create an xmltextReader for an XML in-memory document.
5354 * The parsing flags @options are a combination of xmlParserOption.
5356 * Returns the new reader or NULL in case of error.
5358 xmlTextReaderPtr
5359 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5360 const char *encoding, int options)
5362 xmlTextReaderPtr reader;
5363 xmlParserInputBufferPtr buf;
5365 buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
5366 if (buf == NULL) {
5367 return (NULL);
5369 reader = xmlNewTextReader(buf, URL);
5370 if (reader == NULL) {
5371 xmlFreeParserInputBuffer(buf);
5372 return (NULL);
5374 reader->allocs |= XML_TEXTREADER_INPUT;
5375 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5376 return (reader);
5380 * xmlReaderForFd:
5381 * @fd: an open file descriptor
5382 * @URL: the base URL to use for the document
5383 * @encoding: the document encoding, or NULL
5384 * @options: a combination of xmlParserOption
5386 * Create an xmltextReader for an XML from a file descriptor.
5387 * The parsing flags @options are a combination of xmlParserOption.
5388 * NOTE that the file descriptor will not be closed when the
5389 * reader is closed or reset.
5391 * Returns the new reader or NULL in case of error.
5393 xmlTextReaderPtr
5394 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5396 xmlTextReaderPtr reader;
5397 xmlParserInputBufferPtr input;
5399 if (fd < 0)
5400 return (NULL);
5402 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5403 if (input == NULL)
5404 return (NULL);
5405 input->closecallback = NULL;
5406 reader = xmlNewTextReader(input, URL);
5407 if (reader == NULL) {
5408 xmlFreeParserInputBuffer(input);
5409 return (NULL);
5411 reader->allocs |= XML_TEXTREADER_INPUT;
5412 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5413 return (reader);
5417 * xmlReaderForIO:
5418 * @ioread: an I/O read function
5419 * @ioclose: an I/O close function
5420 * @ioctx: an I/O handler
5421 * @URL: the base URL to use for the document
5422 * @encoding: the document encoding, or NULL
5423 * @options: a combination of xmlParserOption
5425 * Create an xmltextReader for an XML document from I/O functions and source.
5426 * The parsing flags @options are a combination of xmlParserOption.
5428 * Returns the new reader or NULL in case of error.
5430 xmlTextReaderPtr
5431 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5432 void *ioctx, const char *URL, const char *encoding,
5433 int options)
5435 xmlTextReaderPtr reader;
5436 xmlParserInputBufferPtr input;
5438 if (ioread == NULL)
5439 return (NULL);
5441 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5442 XML_CHAR_ENCODING_NONE);
5443 if (input == NULL) {
5444 if (ioclose != NULL)
5445 ioclose(ioctx);
5446 return (NULL);
5448 reader = xmlNewTextReader(input, URL);
5449 if (reader == NULL) {
5450 xmlFreeParserInputBuffer(input);
5451 return (NULL);
5453 reader->allocs |= XML_TEXTREADER_INPUT;
5454 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5455 return (reader);
5459 * xmlReaderNewWalker:
5460 * @reader: an XML reader
5461 * @doc: a preparsed document
5463 * Setup an xmltextReader to parse a preparsed XML document.
5464 * This reuses the existing @reader xmlTextReader.
5466 * Returns 0 in case of success and -1 in case of error
5469 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5471 if (doc == NULL)
5472 return (-1);
5473 if (reader == NULL)
5474 return (-1);
5476 if (reader->input != NULL) {
5477 xmlFreeParserInputBuffer(reader->input);
5479 if (reader->ctxt != NULL) {
5480 xmlCtxtReset(reader->ctxt);
5483 reader->entNr = 0;
5484 reader->input = NULL;
5485 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5486 reader->node = NULL;
5487 reader->curnode = NULL;
5488 reader->base = 0;
5489 reader->cur = 0;
5490 reader->allocs = XML_TEXTREADER_CTXT;
5491 reader->doc = doc;
5492 reader->state = XML_TEXTREADER_START;
5493 if (reader->dict == NULL) {
5494 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5495 reader->dict = reader->ctxt->dict;
5496 else
5497 reader->dict = xmlDictCreate();
5499 return(0);
5503 * xmlReaderNewDoc:
5504 * @reader: an XML reader
5505 * @cur: a pointer to a zero terminated string
5506 * @URL: the base URL to use for the document
5507 * @encoding: the document encoding, or NULL
5508 * @options: a combination of xmlParserOption
5510 * Setup an xmltextReader to parse an XML in-memory document.
5511 * The parsing flags @options are a combination of xmlParserOption.
5512 * This reuses the existing @reader xmlTextReader.
5514 * Returns 0 in case of success and -1 in case of error
5517 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5518 const char *URL, const char *encoding, int options)
5521 int len;
5523 if (cur == NULL)
5524 return (-1);
5525 if (reader == NULL)
5526 return (-1);
5528 len = xmlStrlen(cur);
5529 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5530 URL, encoding, options));
5534 * xmlReaderNewFile:
5535 * @reader: an XML reader
5536 * @filename: a file or URL
5537 * @encoding: the document encoding, or NULL
5538 * @options: a combination of xmlParserOption
5540 * parse an XML file from the filesystem or the network.
5541 * The parsing flags @options are a combination of xmlParserOption.
5542 * This reuses the existing @reader xmlTextReader.
5544 * Returns 0 in case of success and -1 in case of error
5547 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5548 const char *encoding, int options)
5550 xmlParserInputBufferPtr input;
5552 if (filename == NULL)
5553 return (-1);
5554 if (reader == NULL)
5555 return (-1);
5557 input =
5558 xmlParserInputBufferCreateFilename(filename,
5559 XML_CHAR_ENCODING_NONE);
5560 if (input == NULL)
5561 return (-1);
5562 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5566 * xmlReaderNewMemory:
5567 * @reader: an XML reader
5568 * @buffer: a pointer to a char array
5569 * @size: the size of the array
5570 * @URL: the base URL to use for the document
5571 * @encoding: the document encoding, or NULL
5572 * @options: a combination of xmlParserOption
5574 * Setup an xmltextReader to parse an XML in-memory document.
5575 * The parsing flags @options are a combination of xmlParserOption.
5576 * This reuses the existing @reader xmlTextReader.
5578 * Returns 0 in case of success and -1 in case of error
5581 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5582 const char *URL, const char *encoding, int options)
5584 xmlParserInputBufferPtr input;
5586 if (reader == NULL)
5587 return (-1);
5588 if (buffer == NULL)
5589 return (-1);
5591 input = xmlParserInputBufferCreateMem(buffer, size,
5592 XML_CHAR_ENCODING_NONE);
5593 if (input == NULL) {
5594 return (-1);
5596 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5600 * xmlReaderNewFd:
5601 * @reader: an XML reader
5602 * @fd: an open file descriptor
5603 * @URL: the base URL to use for the document
5604 * @encoding: the document encoding, or NULL
5605 * @options: a combination of xmlParserOption
5607 * Setup an xmltextReader to parse an XML from a file descriptor.
5608 * NOTE that the file descriptor will not be closed when the
5609 * reader is closed or reset.
5610 * The parsing flags @options are a combination of xmlParserOption.
5611 * This reuses the existing @reader xmlTextReader.
5613 * Returns 0 in case of success and -1 in case of error
5616 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5617 const char *URL, const char *encoding, int options)
5619 xmlParserInputBufferPtr input;
5621 if (fd < 0)
5622 return (-1);
5623 if (reader == NULL)
5624 return (-1);
5626 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5627 if (input == NULL)
5628 return (-1);
5629 input->closecallback = NULL;
5630 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5634 * xmlReaderNewIO:
5635 * @reader: an XML reader
5636 * @ioread: an I/O read function
5637 * @ioclose: an I/O close function
5638 * @ioctx: an I/O handler
5639 * @URL: the base URL to use for the document
5640 * @encoding: the document encoding, or NULL
5641 * @options: a combination of xmlParserOption
5643 * Setup an xmltextReader to parse an XML document from I/O functions
5644 * and source.
5645 * The parsing flags @options are a combination of xmlParserOption.
5646 * This reuses the existing @reader xmlTextReader.
5648 * Returns 0 in case of success and -1 in case of error
5651 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5652 xmlInputCloseCallback ioclose, void *ioctx,
5653 const char *URL, const char *encoding, int options)
5655 xmlParserInputBufferPtr input;
5657 if (ioread == NULL)
5658 return (-1);
5659 if (reader == NULL)
5660 return (-1);
5662 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5663 XML_CHAR_ENCODING_NONE);
5664 if (input == NULL) {
5665 if (ioclose != NULL)
5666 ioclose(ioctx);
5667 return (-1);
5669 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5672 /************************************************************************
5674 * Utilities *
5676 ************************************************************************/
5677 #ifdef NOT_USED_YET
5680 * xmlBase64Decode:
5681 * @in: the input buffer
5682 * @inlen: the size of the input (in), the size read from it (out)
5683 * @to: the output buffer
5684 * @tolen: the size of the output (in), the size written to (out)
5686 * Base64 decoder, reads from @in and save in @to
5687 * TODO: tell jody when this is actually exported
5689 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5690 * 2 if there wasn't enough space on the output or -1 in case of error.
5692 static int
5693 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5694 unsigned char *to, unsigned long *tolen)
5696 unsigned long incur; /* current index in in[] */
5698 unsigned long inblk; /* last block index in in[] */
5700 unsigned long outcur; /* current index in out[] */
5702 unsigned long inmax; /* size of in[] */
5704 unsigned long outmax; /* size of out[] */
5706 unsigned char cur; /* the current value read from in[] */
5708 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5710 int nbintmp; /* number of byte in intmp[] */
5712 int is_ignore; /* cur should be ignored */
5714 int is_end = 0; /* the end of the base64 was found */
5716 int retval = 1;
5718 int i;
5720 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5721 return (-1);
5723 incur = 0;
5724 inblk = 0;
5725 outcur = 0;
5726 inmax = *inlen;
5727 outmax = *tolen;
5728 nbintmp = 0;
5730 while (1) {
5731 if (incur >= inmax)
5732 break;
5733 cur = in[incur++];
5734 is_ignore = 0;
5735 if ((cur >= 'A') && (cur <= 'Z'))
5736 cur = cur - 'A';
5737 else if ((cur >= 'a') && (cur <= 'z'))
5738 cur = cur - 'a' + 26;
5739 else if ((cur >= '0') && (cur <= '9'))
5740 cur = cur - '0' + 52;
5741 else if (cur == '+')
5742 cur = 62;
5743 else if (cur == '/')
5744 cur = 63;
5745 else if (cur == '.')
5746 cur = 0;
5747 else if (cur == '=') /*no op , end of the base64 stream */
5748 is_end = 1;
5749 else {
5750 is_ignore = 1;
5751 if (nbintmp == 0)
5752 inblk = incur;
5755 if (!is_ignore) {
5756 int nbouttmp = 3;
5758 int is_break = 0;
5760 if (is_end) {
5761 if (nbintmp == 0)
5762 break;
5763 if ((nbintmp == 1) || (nbintmp == 2))
5764 nbouttmp = 1;
5765 else
5766 nbouttmp = 2;
5767 nbintmp = 3;
5768 is_break = 1;
5770 intmp[nbintmp++] = cur;
5772 * if intmp is full, push the 4byte sequence as a 3 byte
5773 * sequence out
5775 if (nbintmp == 4) {
5776 nbintmp = 0;
5777 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5778 outtmp[1] =
5779 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5780 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5781 if (outcur + 3 >= outmax) {
5782 retval = 2;
5783 break;
5786 for (i = 0; i < nbouttmp; i++)
5787 to[outcur++] = outtmp[i];
5788 inblk = incur;
5791 if (is_break) {
5792 retval = 0;
5793 break;
5798 *tolen = outcur;
5799 *inlen = inblk;
5800 return (retval);
5804 * Test routine for the xmlBase64Decode function
5806 #if 0
5808 main(int argc, char **argv)
5810 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5812 char output[100];
5814 char output2[100];
5816 char output3[100];
5818 unsigned long inlen = strlen(input);
5820 unsigned long outlen = 100;
5822 int ret;
5824 unsigned long cons, tmp, tmp2, prod;
5827 * Direct
5829 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5831 output[outlen] = 0;
5832 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5833 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5837 * output chunking
5839 cons = 0;
5840 prod = 0;
5841 while (cons < inlen) {
5842 tmp = 5;
5843 tmp2 = inlen - cons;
5845 printf("%ld %ld\n", cons, prod);
5846 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5847 cons += tmp2;
5848 prod += tmp;
5849 printf("%ld %ld\n", cons, prod);
5851 output2[outlen] = 0;
5852 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5853 prod, output2);
5856 * input chunking
5858 cons = 0;
5859 prod = 0;
5860 while (cons < inlen) {
5861 tmp = 100 - prod;
5862 tmp2 = inlen - cons;
5863 if (tmp2 > 5)
5864 tmp2 = 5;
5866 printf("%ld %ld\n", cons, prod);
5867 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5868 cons += tmp2;
5869 prod += tmp;
5870 printf("%ld %ld\n", cons, prod);
5872 output3[outlen] = 0;
5873 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5874 prod, output3);
5875 return (0);
5878 #endif
5879 #endif /* NOT_USED_YET */
5881 #endif /* LIBXML_READER_ENABLED */