include: Add IFACEMETHOD macros.
[wine.git] / libs / xml2 / xmlreader.c
blob172d1d7ce0b663d69779aa286d1b9f944a55ca55
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->state != XML_TEXTREADER_BACKTRACK) &&
1447 (reader->node != NULL) &&
1448 (reader->node->type == XML_ELEMENT_NODE) &&
1449 (reader->node->ns != NULL) &&
1450 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1451 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1452 if (reader->xincctxt == NULL) {
1453 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1454 xmlXIncludeSetFlags(reader->xincctxt,
1455 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1456 xmlXIncludeSetStreamingMode(reader->xincctxt, 1);
1459 * expand that node and process it
1461 if (xmlTextReaderExpand(reader) == NULL)
1462 return -1;
1463 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1465 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1466 reader->in_xinclude++;
1467 goto get_next_node;
1469 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1470 reader->in_xinclude--;
1471 goto get_next_node;
1473 #endif
1475 * Handle entities enter and exit when in entity replacement mode
1477 if ((reader->node != NULL) &&
1478 (reader->node->type == XML_ENTITY_REF_NODE) &&
1479 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1480 if ((reader->node->children != NULL) &&
1481 (reader->node->children->type == XML_ENTITY_DECL) &&
1482 (reader->node->children->children != NULL)) {
1483 if (xmlTextReaderEntPush(reader, reader->node) < 0)
1484 goto get_next_node;
1485 reader->node = reader->node->children->children;
1487 #ifdef LIBXML_REGEXP_ENABLED
1488 } else if ((reader->node != NULL) &&
1489 (reader->node->type == XML_ENTITY_REF_NODE) &&
1490 (reader->ctxt != NULL) && (reader->validate)) {
1491 xmlTextReaderValidateEntity(reader);
1492 #endif /* LIBXML_REGEXP_ENABLED */
1494 if ((reader->node != NULL) &&
1495 (reader->node->type == XML_ENTITY_DECL) &&
1496 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1497 reader->node = xmlTextReaderEntPop(reader);
1498 reader->depth++;
1499 goto get_next_node;
1501 #ifdef LIBXML_REGEXP_ENABLED
1502 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1503 xmlNodePtr node = reader->node;
1505 if ((node->type == XML_ELEMENT_NODE) &&
1506 ((reader->state != XML_TEXTREADER_END) &&
1507 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1508 xmlTextReaderValidatePush(reader);
1509 } else if ((node->type == XML_TEXT_NODE) ||
1510 (node->type == XML_CDATA_SECTION_NODE)) {
1511 xmlTextReaderValidateCData(reader, node->content,
1512 xmlStrlen(node->content));
1515 #endif /* LIBXML_REGEXP_ENABLED */
1516 #ifdef LIBXML_PATTERN_ENABLED
1517 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1518 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1519 int i;
1520 for (i = 0;i < reader->patternNr;i++) {
1521 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1522 xmlTextReaderPreserve(reader);
1523 break;
1527 #endif /* LIBXML_PATTERN_ENABLED */
1528 #ifdef LIBXML_SCHEMAS_ENABLED
1529 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1530 (reader->xsdValidErrors == 0) &&
1531 (reader->xsdValidCtxt != NULL)) {
1532 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1534 #endif /* LIBXML_PATTERN_ENABLED */
1535 return(1);
1536 node_end:
1537 reader->state = XML_TEXTREADER_DONE;
1538 return(0);
1542 * xmlTextReaderReadState:
1543 * @reader: the xmlTextReaderPtr used
1545 * Gets the read state of the reader.
1547 * Returns the state value, or -1 in case of error
1550 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1551 if (reader == NULL)
1552 return(-1);
1553 return(reader->mode);
1557 * xmlTextReaderExpand:
1558 * @reader: the xmlTextReaderPtr used
1560 * Reads the contents of the current node and the full subtree. It then makes
1561 * the subtree available until the next xmlTextReaderRead() call
1563 * Returns a node pointer valid until the next xmlTextReaderRead() call
1564 * or NULL in case of error.
1566 xmlNodePtr
1567 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1568 if ((reader == NULL) || (reader->node == NULL))
1569 return(NULL);
1570 if (reader->doc != NULL)
1571 return(reader->node);
1572 if (reader->ctxt == NULL)
1573 return(NULL);
1574 if (xmlTextReaderDoExpand(reader) < 0)
1575 return(NULL);
1576 return(reader->node);
1580 * xmlTextReaderNext:
1581 * @reader: the xmlTextReaderPtr used
1583 * Skip to the node following the current one in document order while
1584 * avoiding the subtree if any.
1586 * Returns 1 if the node was read successfully, 0 if there is no more
1587 * nodes to read, or -1 in case of error
1590 xmlTextReaderNext(xmlTextReaderPtr reader) {
1591 int ret;
1592 xmlNodePtr cur;
1594 if (reader == NULL)
1595 return(-1);
1596 if (reader->doc != NULL)
1597 return(xmlTextReaderNextTree(reader));
1598 cur = reader->node;
1599 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1600 return(xmlTextReaderRead(reader));
1601 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1602 return(xmlTextReaderRead(reader));
1603 if (cur->extra & NODE_IS_EMPTY)
1604 return(xmlTextReaderRead(reader));
1605 do {
1606 ret = xmlTextReaderRead(reader);
1607 if (ret != 1)
1608 return(ret);
1609 } while (reader->node != cur);
1610 return(xmlTextReaderRead(reader));
1613 #ifdef LIBXML_WRITER_ENABLED
1615 * xmlTextReaderReadInnerXml:
1616 * @reader: the xmlTextReaderPtr used
1618 * Reads the contents of the current node, including child nodes and markup.
1620 * Returns a string containing the XML content, or NULL if the current node
1621 * is neither an element nor attribute, or has no child nodes. The
1622 * string must be deallocated by the caller.
1624 xmlChar *
1625 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1627 xmlChar *resbuf;
1628 xmlNodePtr node, cur_node;
1629 xmlBufferPtr buff, buff2;
1630 xmlDocPtr doc;
1632 if (xmlTextReaderExpand(reader) == NULL) {
1633 return NULL;
1635 doc = reader->node->doc;
1636 buff = xmlBufferCreate();
1637 if (buff == NULL)
1638 return NULL;
1639 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1640 for (cur_node = reader->node->children; cur_node != NULL;
1641 cur_node = cur_node->next) {
1642 /* XXX: Why is the node copied? */
1643 node = xmlDocCopyNode(cur_node, doc, 1);
1644 /* XXX: Why do we need a second buffer? */
1645 buff2 = xmlBufferCreate();
1646 xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT);
1647 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1648 xmlFreeNode(node);
1649 xmlBufferFree(buff2);
1650 xmlBufferFree(buff);
1651 return NULL;
1653 xmlBufferCat(buff, buff2->content);
1654 xmlFreeNode(node);
1655 xmlBufferFree(buff2);
1657 resbuf = buff->content;
1658 buff->content = NULL;
1660 xmlBufferFree(buff);
1661 return resbuf;
1663 #endif
1665 #ifdef LIBXML_WRITER_ENABLED
1667 * xmlTextReaderReadOuterXml:
1668 * @reader: the xmlTextReaderPtr used
1670 * Reads the contents of the current node, including child nodes and markup.
1672 * Returns a string containing the node and any XML content, or NULL if the
1673 * current node cannot be serialized. The string must be deallocated
1674 * by the caller.
1676 xmlChar *
1677 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1679 xmlChar *resbuf;
1680 xmlNodePtr node;
1681 xmlBufferPtr buff;
1682 xmlDocPtr doc;
1684 if (xmlTextReaderExpand(reader) == NULL) {
1685 return NULL;
1687 node = reader->node;
1688 doc = node->doc;
1689 /* XXX: Why is the node copied? */
1690 if (node->type == XML_DTD_NODE) {
1691 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1692 } else {
1693 node = xmlDocCopyNode(node, doc, 1);
1695 buff = xmlBufferCreate();
1696 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1697 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1698 xmlFreeNode(node);
1699 xmlBufferFree(buff);
1700 return NULL;
1703 resbuf = buff->content;
1704 buff->content = NULL;
1706 xmlFreeNode(node);
1707 xmlBufferFree(buff);
1708 return resbuf;
1710 #endif
1713 * xmlTextReaderReadString:
1714 * @reader: the xmlTextReaderPtr used
1716 * Reads the contents of an element or a text node as a string.
1718 * Returns a string containing the contents of the Element or Text node,
1719 * or NULL if the reader is positioned on any other type of node.
1720 * The string must be deallocated by the caller.
1722 xmlChar *
1723 xmlTextReaderReadString(xmlTextReaderPtr reader)
1725 xmlNodePtr node;
1727 if ((reader == NULL) || (reader->node == NULL))
1728 return(NULL);
1730 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1731 switch (node->type) {
1732 case XML_TEXT_NODE:
1733 if (node->content != NULL)
1734 return(xmlStrdup(node->content));
1735 break;
1736 case XML_ELEMENT_NODE:
1737 if (xmlTextReaderDoExpand(reader) != -1) {
1738 return xmlTextReaderCollectSiblings(node->children);
1740 break;
1741 case XML_ATTRIBUTE_NODE:
1742 TODO
1743 break;
1744 default:
1745 break;
1747 return(NULL);
1750 #if 0
1752 * xmlTextReaderReadBase64:
1753 * @reader: the xmlTextReaderPtr used
1754 * @array: a byte array to store the content.
1755 * @offset: the zero-based index into array where the method should
1756 * begin to write.
1757 * @len: the number of bytes to write.
1759 * Reads and decodes the Base64 encoded contents of an element and
1760 * stores the result in a byte buffer.
1762 * Returns the number of bytes written to array, or zero if the current
1763 * instance is not positioned on an element or -1 in case of error.
1766 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1767 unsigned char *array ATTRIBUTE_UNUSED,
1768 int offset ATTRIBUTE_UNUSED,
1769 int len ATTRIBUTE_UNUSED) {
1770 if ((reader == NULL) || (reader->ctxt == NULL))
1771 return(-1);
1772 if (reader->ctxt->wellFormed != 1)
1773 return(-1);
1775 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1776 return(0);
1777 TODO
1778 return(0);
1782 * xmlTextReaderReadBinHex:
1783 * @reader: the xmlTextReaderPtr used
1784 * @array: a byte array to store the content.
1785 * @offset: the zero-based index into array where the method should
1786 * begin to write.
1787 * @len: the number of bytes to write.
1789 * Reads and decodes the BinHex encoded contents of an element and
1790 * stores the result in a byte buffer.
1792 * Returns the number of bytes written to array, or zero if the current
1793 * instance is not positioned on an element or -1 in case of error.
1796 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1797 unsigned char *array ATTRIBUTE_UNUSED,
1798 int offset ATTRIBUTE_UNUSED,
1799 int len ATTRIBUTE_UNUSED) {
1800 if ((reader == NULL) || (reader->ctxt == NULL))
1801 return(-1);
1802 if (reader->ctxt->wellFormed != 1)
1803 return(-1);
1805 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1806 return(0);
1807 TODO
1808 return(0);
1810 #endif
1812 /************************************************************************
1814 * Operating on a preparsed tree *
1816 ************************************************************************/
1817 static int
1818 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1820 if (reader == NULL)
1821 return(-1);
1823 if (reader->state == XML_TEXTREADER_END)
1824 return(0);
1826 if (reader->node == NULL) {
1827 if (reader->doc->children == NULL) {
1828 reader->state = XML_TEXTREADER_END;
1829 return(0);
1832 reader->node = reader->doc->children;
1833 reader->state = XML_TEXTREADER_START;
1834 return(1);
1837 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1838 /* Here removed traversal to child, because we want to skip the subtree,
1839 replace with traversal to sibling to skip subtree */
1840 if (reader->node->next != 0) {
1841 /* Move to sibling if present,skipping sub-tree */
1842 reader->node = reader->node->next;
1843 reader->state = XML_TEXTREADER_START;
1844 return(1);
1847 /* if reader->node->next is NULL mean no subtree for current node,
1848 so need to move to sibling of parent node if present */
1849 reader->state = XML_TEXTREADER_BACKTRACK;
1850 /* This will move to parent if present */
1851 xmlTextReaderRead(reader);
1854 if (reader->node->next != 0) {
1855 reader->node = reader->node->next;
1856 reader->state = XML_TEXTREADER_START;
1857 return(1);
1860 if (reader->node->parent != 0) {
1861 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1862 reader->state = XML_TEXTREADER_END;
1863 return(0);
1866 reader->node = reader->node->parent;
1867 reader->depth--;
1868 reader->state = XML_TEXTREADER_BACKTRACK;
1869 /* Repeat process to move to sibling of parent node if present */
1870 xmlTextReaderNextTree(reader);
1873 reader->state = XML_TEXTREADER_END;
1875 return(1);
1879 * xmlTextReaderReadTree:
1880 * @reader: the xmlTextReaderPtr used
1882 * Moves the position of the current instance to the next node in
1883 * the stream, exposing its properties.
1885 * Returns 1 if the node was read successfully, 0 if there is no more
1886 * nodes to read, or -1 in case of error
1888 static int
1889 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1890 if (reader->state == XML_TEXTREADER_END)
1891 return(0);
1893 next_node:
1894 if (reader->node == NULL) {
1895 if (reader->doc->children == NULL) {
1896 reader->state = XML_TEXTREADER_END;
1897 return(0);
1900 reader->node = reader->doc->children;
1901 reader->state = XML_TEXTREADER_START;
1902 goto found_node;
1905 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1906 (reader->node->type != XML_DTD_NODE) &&
1907 (reader->node->type != XML_XINCLUDE_START) &&
1908 (reader->node->type != XML_ENTITY_REF_NODE)) {
1909 if (reader->node->children != NULL) {
1910 reader->node = reader->node->children;
1911 reader->depth++;
1912 reader->state = XML_TEXTREADER_START;
1913 goto found_node;
1916 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1917 reader->state = XML_TEXTREADER_BACKTRACK;
1918 goto found_node;
1922 if (reader->node->next != NULL) {
1923 reader->node = reader->node->next;
1924 reader->state = XML_TEXTREADER_START;
1925 goto found_node;
1928 if (reader->node->parent != NULL) {
1929 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1930 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1931 reader->state = XML_TEXTREADER_END;
1932 return(0);
1935 reader->node = reader->node->parent;
1936 reader->depth--;
1937 reader->state = XML_TEXTREADER_BACKTRACK;
1938 goto found_node;
1941 reader->state = XML_TEXTREADER_END;
1943 found_node:
1944 if ((reader->node->type == XML_XINCLUDE_START) ||
1945 (reader->node->type == XML_XINCLUDE_END))
1946 goto next_node;
1948 return(1);
1952 * xmlTextReaderNextSibling:
1953 * @reader: the xmlTextReaderPtr used
1955 * Skip to the node following the current one in document order while
1956 * avoiding the subtree if any.
1957 * Currently implemented only for Readers built on a document
1959 * Returns 1 if the node was read successfully, 0 if there is no more
1960 * nodes to read, or -1 in case of error
1963 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1964 if (reader == NULL)
1965 return(-1);
1966 if (reader->doc == NULL) {
1967 /* TODO */
1968 return(-1);
1971 if (reader->state == XML_TEXTREADER_END)
1972 return(0);
1974 if (reader->node == NULL)
1975 return(xmlTextReaderNextTree(reader));
1977 if (reader->node->next != NULL) {
1978 reader->node = reader->node->next;
1979 reader->state = XML_TEXTREADER_START;
1980 return(1);
1983 return(0);
1986 /************************************************************************
1988 * Constructor and destructors *
1990 ************************************************************************/
1992 * xmlNewTextReader:
1993 * @input: the xmlParserInputBufferPtr used to read data
1994 * @URI: the URI information for the source if available
1996 * Create an xmlTextReader structure fed with @input
1998 * Returns the new xmlTextReaderPtr or NULL in case of error
2000 xmlTextReaderPtr
2001 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2002 xmlTextReaderPtr ret;
2004 if (input == NULL)
2005 return(NULL);
2006 ret = xmlMalloc(sizeof(xmlTextReader));
2007 if (ret == NULL) {
2008 xmlGenericError(xmlGenericErrorContext,
2009 "xmlNewTextReader : malloc failed\n");
2010 return(NULL);
2012 memset(ret, 0, sizeof(xmlTextReader));
2013 ret->doc = NULL;
2014 ret->entTab = NULL;
2015 ret->entMax = 0;
2016 ret->entNr = 0;
2017 ret->input = input;
2018 ret->buffer = xmlBufCreateSize(100);
2019 if (ret->buffer == NULL) {
2020 xmlFree(ret);
2021 xmlGenericError(xmlGenericErrorContext,
2022 "xmlNewTextReader : malloc failed\n");
2023 return(NULL);
2025 /* no operation on a reader should require a huge buffer */
2026 xmlBufSetAllocationScheme(ret->buffer,
2027 XML_BUFFER_ALLOC_DOUBLEIT);
2028 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2029 if (ret->sax == NULL) {
2030 xmlBufFree(ret->buffer);
2031 xmlFree(ret);
2032 xmlGenericError(xmlGenericErrorContext,
2033 "xmlNewTextReader : malloc failed\n");
2034 return(NULL);
2036 xmlSAXVersion(ret->sax, 2);
2037 ret->startElement = ret->sax->startElement;
2038 ret->sax->startElement = xmlTextReaderStartElement;
2039 ret->endElement = ret->sax->endElement;
2040 ret->sax->endElement = xmlTextReaderEndElement;
2041 #ifdef LIBXML_SAX1_ENABLED
2042 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2043 #endif /* LIBXML_SAX1_ENABLED */
2044 ret->startElementNs = ret->sax->startElementNs;
2045 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2046 ret->endElementNs = ret->sax->endElementNs;
2047 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2048 #ifdef LIBXML_SAX1_ENABLED
2049 } else {
2050 ret->startElementNs = NULL;
2051 ret->endElementNs = NULL;
2053 #endif /* LIBXML_SAX1_ENABLED */
2054 ret->characters = ret->sax->characters;
2055 ret->sax->characters = xmlTextReaderCharacters;
2056 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2057 ret->cdataBlock = ret->sax->cdataBlock;
2058 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2060 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2061 ret->node = NULL;
2062 ret->curnode = NULL;
2063 if (xmlBufUse(ret->input->buffer) < 4) {
2064 xmlParserInputBufferRead(input, 4);
2066 if (xmlBufUse(ret->input->buffer) >= 4) {
2067 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2068 (const char *) xmlBufContent(ret->input->buffer),
2069 4, URI);
2070 ret->base = 0;
2071 ret->cur = 4;
2072 } else {
2073 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2074 ret->base = 0;
2075 ret->cur = 0;
2078 if (ret->ctxt == NULL) {
2079 xmlGenericError(xmlGenericErrorContext,
2080 "xmlNewTextReader : malloc failed\n");
2081 xmlBufFree(ret->buffer);
2082 xmlFree(ret->sax);
2083 xmlFree(ret);
2084 return(NULL);
2086 ret->ctxt->parseMode = XML_PARSE_READER;
2087 ret->ctxt->_private = ret;
2088 ret->ctxt->linenumbers = 1;
2089 ret->ctxt->dictNames = 1;
2090 ret->allocs = XML_TEXTREADER_CTXT;
2092 * use the parser dictionary to allocate all elements and attributes names
2094 ret->ctxt->docdict = 1;
2095 ret->dict = ret->ctxt->dict;
2096 #ifdef LIBXML_XINCLUDE_ENABLED
2097 ret->xinclude = 0;
2098 #endif
2099 #ifdef LIBXML_PATTERN_ENABLED
2100 ret->patternMax = 0;
2101 ret->patternTab = NULL;
2102 #endif
2103 return(ret);
2107 * xmlNewTextReaderFilename:
2108 * @URI: the URI of the resource to process
2110 * Create an xmlTextReader structure fed with the resource at @URI
2112 * Returns the new xmlTextReaderPtr or NULL in case of error
2114 xmlTextReaderPtr
2115 xmlNewTextReaderFilename(const char *URI) {
2116 xmlParserInputBufferPtr input;
2117 xmlTextReaderPtr ret;
2118 char *directory = NULL;
2120 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2121 if (input == NULL)
2122 return(NULL);
2123 ret = xmlNewTextReader(input, URI);
2124 if (ret == NULL) {
2125 xmlFreeParserInputBuffer(input);
2126 return(NULL);
2128 ret->allocs |= XML_TEXTREADER_INPUT;
2129 if (ret->ctxt->directory == NULL)
2130 directory = xmlParserGetDirectory(URI);
2131 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2132 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2133 if (directory != NULL)
2134 xmlFree(directory);
2135 return(ret);
2139 * xmlFreeTextReader:
2140 * @reader: the xmlTextReaderPtr
2142 * Deallocate all the resources associated to the reader
2144 void
2145 xmlFreeTextReader(xmlTextReaderPtr reader) {
2146 if (reader == NULL)
2147 return;
2148 #ifdef LIBXML_SCHEMAS_ENABLED
2149 if (reader->rngSchemas != NULL) {
2150 xmlRelaxNGFree(reader->rngSchemas);
2151 reader->rngSchemas = NULL;
2153 if (reader->rngValidCtxt != NULL) {
2154 if (! reader->rngPreserveCtxt)
2155 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2156 reader->rngValidCtxt = NULL;
2158 if (reader->xsdPlug != NULL) {
2159 xmlSchemaSAXUnplug(reader->xsdPlug);
2160 reader->xsdPlug = NULL;
2162 if (reader->xsdValidCtxt != NULL) {
2163 if (! reader->xsdPreserveCtxt)
2164 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2165 reader->xsdValidCtxt = NULL;
2167 if (reader->xsdSchemas != NULL) {
2168 xmlSchemaFree(reader->xsdSchemas);
2169 reader->xsdSchemas = NULL;
2171 #endif
2172 #ifdef LIBXML_XINCLUDE_ENABLED
2173 if (reader->xincctxt != NULL)
2174 xmlXIncludeFreeContext(reader->xincctxt);
2175 #endif
2176 #ifdef LIBXML_PATTERN_ENABLED
2177 if (reader->patternTab != NULL) {
2178 int i;
2179 for (i = 0;i < reader->patternNr;i++) {
2180 if (reader->patternTab[i] != NULL)
2181 xmlFreePattern(reader->patternTab[i]);
2183 xmlFree(reader->patternTab);
2185 #endif
2186 if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
2187 xmlTextReaderClose(reader);
2188 if (reader->ctxt != NULL) {
2189 if (reader->dict == reader->ctxt->dict)
2190 reader->dict = NULL;
2191 if (reader->allocs & XML_TEXTREADER_CTXT)
2192 xmlFreeParserCtxt(reader->ctxt);
2194 if (reader->sax != NULL)
2195 xmlFree(reader->sax);
2196 if (reader->buffer != NULL)
2197 xmlBufFree(reader->buffer);
2198 if (reader->entTab != NULL)
2199 xmlFree(reader->entTab);
2200 if (reader->dict != NULL)
2201 xmlDictFree(reader->dict);
2202 xmlFree(reader);
2205 /************************************************************************
2207 * Methods for XmlTextReader *
2209 ************************************************************************/
2211 * xmlTextReaderClose:
2212 * @reader: the xmlTextReaderPtr used
2214 * This method releases any resources allocated by the current instance
2215 * changes the state to Closed and close any underlying input.
2217 * Returns 0 or -1 in case of error
2220 xmlTextReaderClose(xmlTextReaderPtr reader) {
2221 if (reader == NULL)
2222 return(-1);
2223 reader->node = NULL;
2224 reader->curnode = NULL;
2225 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2226 if (reader->faketext != NULL) {
2227 xmlFreeNode(reader->faketext);
2228 reader->faketext = NULL;
2230 if (reader->ctxt != NULL) {
2231 #ifdef LIBXML_VALID_ENABLED
2232 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2233 (reader->ctxt->vctxt.vstateMax > 0)){
2234 #ifdef LIBXML_REGEXP_ENABLED
2235 while (reader->ctxt->vctxt.vstateNr > 0)
2236 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2237 #endif /* LIBXML_REGEXP_ENABLED */
2238 xmlFree(reader->ctxt->vctxt.vstateTab);
2239 reader->ctxt->vctxt.vstateTab = NULL;
2240 reader->ctxt->vctxt.vstateMax = 0;
2242 #endif /* LIBXML_VALID_ENABLED */
2243 xmlStopParser(reader->ctxt);
2244 if (reader->ctxt->myDoc != NULL) {
2245 if (reader->preserve == 0)
2246 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2247 reader->ctxt->myDoc = NULL;
2250 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2251 xmlFreeParserInputBuffer(reader->input);
2252 reader->allocs -= XML_TEXTREADER_INPUT;
2254 return(0);
2258 * xmlTextReaderGetAttributeNo:
2259 * @reader: the xmlTextReaderPtr used
2260 * @no: the zero-based index of the attribute relative to the containing element
2262 * Provides the value of the attribute with the specified index relative
2263 * to the containing element.
2265 * Returns a string containing the value of the specified attribute, or NULL
2266 * in case of error. The string must be deallocated by the caller.
2268 xmlChar *
2269 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2270 xmlChar *ret;
2271 int i;
2272 xmlAttrPtr cur;
2273 xmlNsPtr ns;
2275 if (reader == NULL)
2276 return(NULL);
2277 if (reader->node == NULL)
2278 return(NULL);
2279 if (reader->curnode != NULL)
2280 return(NULL);
2281 /* TODO: handle the xmlDecl */
2282 if (reader->node->type != XML_ELEMENT_NODE)
2283 return(NULL);
2285 ns = reader->node->nsDef;
2286 for (i = 0;(i < no) && (ns != NULL);i++) {
2287 ns = ns->next;
2289 if (ns != NULL)
2290 return(xmlStrdup(ns->href));
2292 cur = reader->node->properties;
2293 if (cur == NULL)
2294 return(NULL);
2295 for (;i < no;i++) {
2296 cur = cur->next;
2297 if (cur == NULL)
2298 return(NULL);
2300 /* TODO walk the DTD if present */
2302 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2303 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2304 return(ret);
2308 * xmlTextReaderGetAttribute:
2309 * @reader: the xmlTextReaderPtr used
2310 * @name: the qualified name of the attribute.
2312 * Provides the value of the attribute with the specified qualified name.
2314 * Returns a string containing the value of the specified attribute, or NULL
2315 * in case of error. The string must be deallocated by the caller.
2317 xmlChar *
2318 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2319 xmlChar *prefix = NULL;
2320 xmlChar *localname;
2321 xmlNsPtr ns;
2322 xmlChar *ret = NULL;
2324 if ((reader == NULL) || (name == NULL))
2325 return(NULL);
2326 if (reader->node == NULL)
2327 return(NULL);
2328 if (reader->curnode != NULL)
2329 return(NULL);
2331 /* TODO: handle the xmlDecl */
2332 if (reader->node->type != XML_ELEMENT_NODE)
2333 return(NULL);
2335 localname = xmlSplitQName2(name, &prefix);
2336 if (localname == NULL) {
2338 * Namespace default decl
2340 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2341 ns = reader->node->nsDef;
2342 while (ns != NULL) {
2343 if (ns->prefix == NULL) {
2344 return(xmlStrdup(ns->href));
2346 ns = ns->next;
2348 return NULL;
2350 return(xmlGetNoNsProp(reader->node, name));
2354 * Namespace default decl
2356 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2357 ns = reader->node->nsDef;
2358 while (ns != NULL) {
2359 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2360 ret = xmlStrdup(ns->href);
2361 break;
2363 ns = ns->next;
2365 } else {
2366 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2367 if (ns != NULL)
2368 ret = xmlGetNsProp(reader->node, localname, ns->href);
2371 xmlFree(localname);
2372 if (prefix != NULL)
2373 xmlFree(prefix);
2374 return(ret);
2379 * xmlTextReaderGetAttributeNs:
2380 * @reader: the xmlTextReaderPtr used
2381 * @localName: the local name of the attribute.
2382 * @namespaceURI: the namespace URI of the attribute.
2384 * Provides the value of the specified attribute
2386 * Returns a string containing the value of the specified attribute, or NULL
2387 * in case of error. The string must be deallocated by the caller.
2389 xmlChar *
2390 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2391 const xmlChar *namespaceURI) {
2392 xmlChar *prefix = NULL;
2393 xmlNsPtr ns;
2395 if ((reader == NULL) || (localName == NULL))
2396 return(NULL);
2397 if (reader->node == NULL)
2398 return(NULL);
2399 if (reader->curnode != NULL)
2400 return(NULL);
2402 /* TODO: handle the xmlDecl */
2403 if (reader->node->type != XML_ELEMENT_NODE)
2404 return(NULL);
2406 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2407 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2408 prefix = BAD_CAST localName;
2410 ns = reader->node->nsDef;
2411 while (ns != NULL) {
2412 if ((prefix == NULL && ns->prefix == NULL) ||
2413 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2414 return xmlStrdup(ns->href);
2416 ns = ns->next;
2418 return NULL;
2421 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2425 * xmlTextReaderGetRemainder:
2426 * @reader: the xmlTextReaderPtr used
2428 * Method to get the remainder of the buffered XML. this method stops the
2429 * parser, set its state to End Of File and return the input stream with
2430 * what is left that the parser did not use.
2432 * The implementation is not good, the parser certainly progressed past
2433 * what's left in reader->input, and there is an allocation problem. Best
2434 * would be to rewrite it differently.
2436 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2437 * in case of error.
2439 xmlParserInputBufferPtr
2440 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2441 xmlParserInputBufferPtr ret = NULL;
2443 if (reader == NULL)
2444 return(NULL);
2445 if (reader->node == NULL)
2446 return(NULL);
2448 reader->node = NULL;
2449 reader->curnode = NULL;
2450 reader->mode = XML_TEXTREADER_MODE_EOF;
2451 if (reader->ctxt != NULL) {
2452 xmlStopParser(reader->ctxt);
2453 if (reader->ctxt->myDoc != NULL) {
2454 if (reader->preserve == 0)
2455 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2456 reader->ctxt->myDoc = NULL;
2459 if (reader->allocs & XML_TEXTREADER_INPUT) {
2460 ret = reader->input;
2461 reader->input = NULL;
2462 reader->allocs -= XML_TEXTREADER_INPUT;
2463 } else {
2465 * Hum, one may need to duplicate the data structure because
2466 * without reference counting the input may be freed twice:
2467 * - by the layer which allocated it.
2468 * - by the layer to which would have been returned to.
2470 TODO
2471 return(NULL);
2473 return(ret);
2477 * xmlTextReaderLookupNamespace:
2478 * @reader: the xmlTextReaderPtr used
2479 * @prefix: the prefix whose namespace URI is to be resolved. To return
2480 * the default namespace, specify NULL
2482 * Resolves a namespace prefix in the scope of the current element.
2484 * Returns a string containing the namespace URI to which the prefix maps
2485 * or NULL in case of error. The string must be deallocated by the caller.
2487 xmlChar *
2488 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2489 xmlNsPtr ns;
2491 if (reader == NULL)
2492 return(NULL);
2493 if (reader->node == NULL)
2494 return(NULL);
2496 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2497 if (ns == NULL)
2498 return(NULL);
2499 return(xmlStrdup(ns->href));
2503 * xmlTextReaderMoveToAttributeNo:
2504 * @reader: the xmlTextReaderPtr used
2505 * @no: the zero-based index of the attribute relative to the containing
2506 * element.
2508 * Moves the position of the current instance to the attribute with
2509 * the specified index relative to the containing element.
2511 * Returns 1 in case of success, -1 in case of error, 0 if not found
2514 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2515 int i;
2516 xmlAttrPtr cur;
2517 xmlNsPtr ns;
2519 if (reader == NULL)
2520 return(-1);
2521 if (reader->node == NULL)
2522 return(-1);
2523 /* TODO: handle the xmlDecl */
2524 if (reader->node->type != XML_ELEMENT_NODE)
2525 return(-1);
2527 reader->curnode = NULL;
2529 ns = reader->node->nsDef;
2530 for (i = 0;(i < no) && (ns != NULL);i++) {
2531 ns = ns->next;
2533 if (ns != NULL) {
2534 reader->curnode = (xmlNodePtr) ns;
2535 return(1);
2538 cur = reader->node->properties;
2539 if (cur == NULL)
2540 return(0);
2541 for (;i < no;i++) {
2542 cur = cur->next;
2543 if (cur == NULL)
2544 return(0);
2546 /* TODO walk the DTD if present */
2548 reader->curnode = (xmlNodePtr) cur;
2549 return(1);
2553 * xmlTextReaderMoveToAttribute:
2554 * @reader: the xmlTextReaderPtr used
2555 * @name: the qualified name of the attribute.
2557 * Moves the position of the current instance to the attribute with
2558 * the specified qualified name.
2560 * Returns 1 in case of success, -1 in case of error, 0 if not found
2563 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2564 xmlChar *prefix = NULL;
2565 xmlChar *localname;
2566 xmlNsPtr ns;
2567 xmlAttrPtr prop;
2569 if ((reader == NULL) || (name == NULL))
2570 return(-1);
2571 if (reader->node == NULL)
2572 return(-1);
2574 /* TODO: handle the xmlDecl */
2575 if (reader->node->type != XML_ELEMENT_NODE)
2576 return(0);
2578 localname = xmlSplitQName2(name, &prefix);
2579 if (localname == NULL) {
2581 * Namespace default decl
2583 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2584 ns = reader->node->nsDef;
2585 while (ns != NULL) {
2586 if (ns->prefix == NULL) {
2587 reader->curnode = (xmlNodePtr) ns;
2588 return(1);
2590 ns = ns->next;
2592 return(0);
2595 prop = reader->node->properties;
2596 while (prop != NULL) {
2598 * One need to have
2599 * - same attribute names
2600 * - and the attribute carrying that namespace
2602 if ((xmlStrEqual(prop->name, name)) &&
2603 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2604 reader->curnode = (xmlNodePtr) prop;
2605 return(1);
2607 prop = prop->next;
2609 return(0);
2613 * Namespace default decl
2615 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2616 ns = reader->node->nsDef;
2617 while (ns != NULL) {
2618 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2619 reader->curnode = (xmlNodePtr) ns;
2620 goto found;
2622 ns = ns->next;
2624 goto not_found;
2626 prop = reader->node->properties;
2627 while (prop != NULL) {
2629 * One need to have
2630 * - same attribute names
2631 * - and the attribute carrying that namespace
2633 if ((xmlStrEqual(prop->name, localname)) &&
2634 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2635 reader->curnode = (xmlNodePtr) prop;
2636 goto found;
2638 prop = prop->next;
2640 not_found:
2641 if (localname != NULL)
2642 xmlFree(localname);
2643 if (prefix != NULL)
2644 xmlFree(prefix);
2645 return(0);
2647 found:
2648 if (localname != NULL)
2649 xmlFree(localname);
2650 if (prefix != NULL)
2651 xmlFree(prefix);
2652 return(1);
2656 * xmlTextReaderMoveToAttributeNs:
2657 * @reader: the xmlTextReaderPtr used
2658 * @localName: the local name of the attribute.
2659 * @namespaceURI: the namespace URI of the attribute.
2661 * Moves the position of the current instance to the attribute with the
2662 * specified local name and namespace URI.
2664 * Returns 1 in case of success, -1 in case of error, 0 if not found
2667 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2668 const xmlChar *localName, const xmlChar *namespaceURI) {
2669 xmlAttrPtr prop;
2670 xmlNodePtr node;
2671 xmlNsPtr ns;
2672 xmlChar *prefix = NULL;
2674 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2675 return(-1);
2676 if (reader->node == NULL)
2677 return(-1);
2678 if (reader->node->type != XML_ELEMENT_NODE)
2679 return(0);
2680 node = reader->node;
2682 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2683 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2684 prefix = BAD_CAST localName;
2686 ns = reader->node->nsDef;
2687 while (ns != NULL) {
2688 if ((prefix == NULL && ns->prefix == NULL) ||
2689 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2690 reader->curnode = (xmlNodePtr) ns;
2691 return(1);
2693 ns = ns->next;
2695 return(0);
2698 prop = node->properties;
2699 while (prop != NULL) {
2701 * One need to have
2702 * - same attribute names
2703 * - and the attribute carrying that namespace
2705 if (xmlStrEqual(prop->name, localName) &&
2706 ((prop->ns != NULL) &&
2707 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2708 reader->curnode = (xmlNodePtr) prop;
2709 return(1);
2711 prop = prop->next;
2713 return(0);
2717 * xmlTextReaderMoveToFirstAttribute:
2718 * @reader: the xmlTextReaderPtr used
2720 * Moves the position of the current instance to the first attribute
2721 * associated with the current node.
2723 * Returns 1 in case of success, -1 in case of error, 0 if not found
2726 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2727 if (reader == NULL)
2728 return(-1);
2729 if (reader->node == NULL)
2730 return(-1);
2731 if (reader->node->type != XML_ELEMENT_NODE)
2732 return(0);
2734 if (reader->node->nsDef != NULL) {
2735 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2736 return(1);
2738 if (reader->node->properties != NULL) {
2739 reader->curnode = (xmlNodePtr) reader->node->properties;
2740 return(1);
2742 return(0);
2746 * xmlTextReaderMoveToNextAttribute:
2747 * @reader: the xmlTextReaderPtr used
2749 * Moves the position of the current instance to the next attribute
2750 * associated with the current node.
2752 * Returns 1 in case of success, -1 in case of error, 0 if not found
2755 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2756 if (reader == NULL)
2757 return(-1);
2758 if (reader->node == NULL)
2759 return(-1);
2760 if (reader->node->type != XML_ELEMENT_NODE)
2761 return(0);
2762 if (reader->curnode == NULL)
2763 return(xmlTextReaderMoveToFirstAttribute(reader));
2765 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2766 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2767 if (ns->next != NULL) {
2768 reader->curnode = (xmlNodePtr) ns->next;
2769 return(1);
2771 if (reader->node->properties != NULL) {
2772 reader->curnode = (xmlNodePtr) reader->node->properties;
2773 return(1);
2775 return(0);
2776 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2777 (reader->curnode->next != NULL)) {
2778 reader->curnode = reader->curnode->next;
2779 return(1);
2781 return(0);
2785 * xmlTextReaderMoveToElement:
2786 * @reader: the xmlTextReaderPtr used
2788 * Moves the position of the current instance to the node that
2789 * contains the current Attribute node.
2791 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2794 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2795 if (reader == NULL)
2796 return(-1);
2797 if (reader->node == NULL)
2798 return(-1);
2799 if (reader->node->type != XML_ELEMENT_NODE)
2800 return(0);
2801 if (reader->curnode != NULL) {
2802 reader->curnode = NULL;
2803 return(1);
2805 return(0);
2809 * xmlTextReaderReadAttributeValue:
2810 * @reader: the xmlTextReaderPtr used
2812 * Parses an attribute value into one or more Text and EntityReference nodes.
2814 * Returns 1 in case of success, 0 if the reader was not positioned on an
2815 * attribute node or all the attribute values have been read, or -1
2816 * in case of error.
2819 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2820 if (reader == NULL)
2821 return(-1);
2822 if (reader->node == NULL)
2823 return(-1);
2824 if (reader->curnode == NULL)
2825 return(0);
2826 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2827 if (reader->curnode->children == NULL)
2828 return(0);
2829 reader->curnode = reader->curnode->children;
2830 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2831 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2833 if (reader->faketext == NULL) {
2834 reader->faketext = xmlNewDocText(reader->node->doc,
2835 ns->href);
2836 } else {
2837 if ((reader->faketext->content != NULL) &&
2838 (reader->faketext->content !=
2839 (xmlChar *) &(reader->faketext->properties)))
2840 xmlFree(reader->faketext->content);
2841 reader->faketext->content = xmlStrdup(ns->href);
2843 reader->curnode = reader->faketext;
2844 } else {
2845 if (reader->curnode->next == NULL)
2846 return(0);
2847 reader->curnode = reader->curnode->next;
2849 return(1);
2853 * xmlTextReaderConstEncoding:
2854 * @reader: the xmlTextReaderPtr used
2856 * Determine the encoding of the document being read.
2858 * Returns a string containing the encoding of the document or NULL in
2859 * case of error. The string is deallocated with the reader.
2861 const xmlChar *
2862 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2863 xmlDocPtr doc = NULL;
2864 if (reader == NULL)
2865 return(NULL);
2866 if (reader->doc != NULL)
2867 doc = reader->doc;
2868 else if (reader->ctxt != NULL)
2869 doc = reader->ctxt->myDoc;
2870 if (doc == NULL)
2871 return(NULL);
2873 if (doc->encoding == NULL)
2874 return(NULL);
2875 else
2876 return(CONSTSTR(doc->encoding));
2880 /************************************************************************
2882 * Access API to the current node *
2884 ************************************************************************/
2886 * xmlTextReaderAttributeCount:
2887 * @reader: the xmlTextReaderPtr used
2889 * Provides the number of attributes of the current node
2891 * Returns 0 i no attributes, -1 in case of error or the attribute count
2894 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2895 int ret;
2896 xmlAttrPtr attr;
2897 xmlNsPtr ns;
2898 xmlNodePtr node;
2900 if (reader == NULL)
2901 return(-1);
2902 if (reader->node == NULL)
2903 return(0);
2905 if (reader->curnode != NULL)
2906 node = reader->curnode;
2907 else
2908 node = reader->node;
2910 if (node->type != XML_ELEMENT_NODE)
2911 return(0);
2912 if ((reader->state == XML_TEXTREADER_END) ||
2913 (reader->state == XML_TEXTREADER_BACKTRACK))
2914 return(0);
2915 ret = 0;
2916 attr = node->properties;
2917 while (attr != NULL) {
2918 ret++;
2919 attr = attr->next;
2921 ns = node->nsDef;
2922 while (ns != NULL) {
2923 ret++;
2924 ns = ns->next;
2926 return(ret);
2930 * xmlTextReaderNodeType:
2931 * @reader: the xmlTextReaderPtr used
2933 * Get the node type of the current node
2934 * Reference:
2935 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
2937 * Returns the xmlReaderTypes of the current node or -1 in case of error
2940 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2941 xmlNodePtr node;
2943 if (reader == NULL)
2944 return(-1);
2945 if (reader->node == NULL)
2946 return(XML_READER_TYPE_NONE);
2947 if (reader->curnode != NULL)
2948 node = reader->curnode;
2949 else
2950 node = reader->node;
2951 switch (node->type) {
2952 case XML_ELEMENT_NODE:
2953 if ((reader->state == XML_TEXTREADER_END) ||
2954 (reader->state == XML_TEXTREADER_BACKTRACK))
2955 return(XML_READER_TYPE_END_ELEMENT);
2956 return(XML_READER_TYPE_ELEMENT);
2957 case XML_NAMESPACE_DECL:
2958 case XML_ATTRIBUTE_NODE:
2959 return(XML_READER_TYPE_ATTRIBUTE);
2960 case XML_TEXT_NODE:
2961 if (xmlIsBlankNode(reader->node)) {
2962 if (xmlNodeGetSpacePreserve(reader->node))
2963 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2964 else
2965 return(XML_READER_TYPE_WHITESPACE);
2966 } else {
2967 return(XML_READER_TYPE_TEXT);
2969 case XML_CDATA_SECTION_NODE:
2970 return(XML_READER_TYPE_CDATA);
2971 case XML_ENTITY_REF_NODE:
2972 return(XML_READER_TYPE_ENTITY_REFERENCE);
2973 case XML_ENTITY_NODE:
2974 return(XML_READER_TYPE_ENTITY);
2975 case XML_PI_NODE:
2976 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
2977 case XML_COMMENT_NODE:
2978 return(XML_READER_TYPE_COMMENT);
2979 case XML_DOCUMENT_NODE:
2980 case XML_HTML_DOCUMENT_NODE:
2981 return(XML_READER_TYPE_DOCUMENT);
2982 case XML_DOCUMENT_FRAG_NODE:
2983 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
2984 case XML_NOTATION_NODE:
2985 return(XML_READER_TYPE_NOTATION);
2986 case XML_DOCUMENT_TYPE_NODE:
2987 case XML_DTD_NODE:
2988 return(XML_READER_TYPE_DOCUMENT_TYPE);
2990 case XML_ELEMENT_DECL:
2991 case XML_ATTRIBUTE_DECL:
2992 case XML_ENTITY_DECL:
2993 case XML_XINCLUDE_START:
2994 case XML_XINCLUDE_END:
2995 return(XML_READER_TYPE_NONE);
2997 return(-1);
3001 * xmlTextReaderIsEmptyElement:
3002 * @reader: the xmlTextReaderPtr used
3004 * Check if the current node is empty
3006 * Returns 1 if empty, 0 if not and -1 in case of error
3009 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3010 if ((reader == NULL) || (reader->node == NULL))
3011 return(-1);
3012 if (reader->node->type != XML_ELEMENT_NODE)
3013 return(0);
3014 if (reader->curnode != NULL)
3015 return(0);
3016 if (reader->node->children != NULL)
3017 return(0);
3018 if (reader->state == XML_TEXTREADER_END)
3019 return(0);
3020 if (reader->doc != NULL)
3021 return(1);
3022 #ifdef LIBXML_XINCLUDE_ENABLED
3023 if (reader->in_xinclude > 0)
3024 return(1);
3025 #endif
3026 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3030 * xmlTextReaderLocalName:
3031 * @reader: the xmlTextReaderPtr used
3033 * The local name of the node.
3035 * Returns the local name or NULL if not available,
3036 * if non NULL it need to be freed by the caller.
3038 xmlChar *
3039 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3040 xmlNodePtr node;
3041 if ((reader == NULL) || (reader->node == NULL))
3042 return(NULL);
3043 if (reader->curnode != NULL)
3044 node = reader->curnode;
3045 else
3046 node = reader->node;
3047 if (node->type == XML_NAMESPACE_DECL) {
3048 xmlNsPtr ns = (xmlNsPtr) node;
3049 if (ns->prefix == NULL)
3050 return(xmlStrdup(BAD_CAST "xmlns"));
3051 else
3052 return(xmlStrdup(ns->prefix));
3054 if ((node->type != XML_ELEMENT_NODE) &&
3055 (node->type != XML_ATTRIBUTE_NODE))
3056 return(xmlTextReaderName(reader));
3057 return(xmlStrdup(node->name));
3061 * xmlTextReaderConstLocalName:
3062 * @reader: the xmlTextReaderPtr used
3064 * The local name of the node.
3066 * Returns the local name or NULL if not available, the
3067 * string will be deallocated with the reader.
3069 const xmlChar *
3070 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3071 xmlNodePtr node;
3072 if ((reader == NULL) || (reader->node == NULL))
3073 return(NULL);
3074 if (reader->curnode != NULL)
3075 node = reader->curnode;
3076 else
3077 node = reader->node;
3078 if (node->type == XML_NAMESPACE_DECL) {
3079 xmlNsPtr ns = (xmlNsPtr) node;
3080 if (ns->prefix == NULL)
3081 return(CONSTSTR(BAD_CAST "xmlns"));
3082 else
3083 return(ns->prefix);
3085 if ((node->type != XML_ELEMENT_NODE) &&
3086 (node->type != XML_ATTRIBUTE_NODE))
3087 return(xmlTextReaderConstName(reader));
3088 return(node->name);
3092 * xmlTextReaderName:
3093 * @reader: the xmlTextReaderPtr used
3095 * The qualified name of the node, equal to Prefix :LocalName.
3097 * Returns the local name or NULL if not available,
3098 * if non NULL it need to be freed by the caller.
3100 xmlChar *
3101 xmlTextReaderName(xmlTextReaderPtr reader) {
3102 xmlNodePtr node;
3103 xmlChar *ret;
3105 if ((reader == NULL) || (reader->node == NULL))
3106 return(NULL);
3107 if (reader->curnode != NULL)
3108 node = reader->curnode;
3109 else
3110 node = reader->node;
3111 switch (node->type) {
3112 case XML_ELEMENT_NODE:
3113 case XML_ATTRIBUTE_NODE:
3114 if ((node->ns == NULL) ||
3115 (node->ns->prefix == NULL))
3116 return(xmlStrdup(node->name));
3118 ret = xmlStrdup(node->ns->prefix);
3119 ret = xmlStrcat(ret, BAD_CAST ":");
3120 ret = xmlStrcat(ret, node->name);
3121 return(ret);
3122 case XML_TEXT_NODE:
3123 return(xmlStrdup(BAD_CAST "#text"));
3124 case XML_CDATA_SECTION_NODE:
3125 return(xmlStrdup(BAD_CAST "#cdata-section"));
3126 case XML_ENTITY_NODE:
3127 case XML_ENTITY_REF_NODE:
3128 return(xmlStrdup(node->name));
3129 case XML_PI_NODE:
3130 return(xmlStrdup(node->name));
3131 case XML_COMMENT_NODE:
3132 return(xmlStrdup(BAD_CAST "#comment"));
3133 case XML_DOCUMENT_NODE:
3134 case XML_HTML_DOCUMENT_NODE:
3135 return(xmlStrdup(BAD_CAST "#document"));
3136 case XML_DOCUMENT_FRAG_NODE:
3137 return(xmlStrdup(BAD_CAST "#document-fragment"));
3138 case XML_NOTATION_NODE:
3139 return(xmlStrdup(node->name));
3140 case XML_DOCUMENT_TYPE_NODE:
3141 case XML_DTD_NODE:
3142 return(xmlStrdup(node->name));
3143 case XML_NAMESPACE_DECL: {
3144 xmlNsPtr ns = (xmlNsPtr) node;
3146 ret = xmlStrdup(BAD_CAST "xmlns");
3147 if (ns->prefix == NULL)
3148 return(ret);
3149 ret = xmlStrcat(ret, BAD_CAST ":");
3150 ret = xmlStrcat(ret, ns->prefix);
3151 return(ret);
3154 case XML_ELEMENT_DECL:
3155 case XML_ATTRIBUTE_DECL:
3156 case XML_ENTITY_DECL:
3157 case XML_XINCLUDE_START:
3158 case XML_XINCLUDE_END:
3159 return(NULL);
3161 return(NULL);
3165 * xmlTextReaderConstName:
3166 * @reader: the xmlTextReaderPtr used
3168 * The qualified name of the node, equal to Prefix :LocalName.
3170 * Returns the local name or NULL if not available, the string is
3171 * deallocated with the reader.
3173 const xmlChar *
3174 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3175 xmlNodePtr node;
3177 if ((reader == NULL) || (reader->node == NULL))
3178 return(NULL);
3179 if (reader->curnode != NULL)
3180 node = reader->curnode;
3181 else
3182 node = reader->node;
3183 switch (node->type) {
3184 case XML_ELEMENT_NODE:
3185 case XML_ATTRIBUTE_NODE:
3186 if ((node->ns == NULL) ||
3187 (node->ns->prefix == NULL))
3188 return(node->name);
3189 return(CONSTQSTR(node->ns->prefix, node->name));
3190 case XML_TEXT_NODE:
3191 return(CONSTSTR(BAD_CAST "#text"));
3192 case XML_CDATA_SECTION_NODE:
3193 return(CONSTSTR(BAD_CAST "#cdata-section"));
3194 case XML_ENTITY_NODE:
3195 case XML_ENTITY_REF_NODE:
3196 return(CONSTSTR(node->name));
3197 case XML_PI_NODE:
3198 return(CONSTSTR(node->name));
3199 case XML_COMMENT_NODE:
3200 return(CONSTSTR(BAD_CAST "#comment"));
3201 case XML_DOCUMENT_NODE:
3202 case XML_HTML_DOCUMENT_NODE:
3203 return(CONSTSTR(BAD_CAST "#document"));
3204 case XML_DOCUMENT_FRAG_NODE:
3205 return(CONSTSTR(BAD_CAST "#document-fragment"));
3206 case XML_NOTATION_NODE:
3207 return(CONSTSTR(node->name));
3208 case XML_DOCUMENT_TYPE_NODE:
3209 case XML_DTD_NODE:
3210 return(CONSTSTR(node->name));
3211 case XML_NAMESPACE_DECL: {
3212 xmlNsPtr ns = (xmlNsPtr) node;
3214 if (ns->prefix == NULL)
3215 return(CONSTSTR(BAD_CAST "xmlns"));
3216 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3219 case XML_ELEMENT_DECL:
3220 case XML_ATTRIBUTE_DECL:
3221 case XML_ENTITY_DECL:
3222 case XML_XINCLUDE_START:
3223 case XML_XINCLUDE_END:
3224 return(NULL);
3226 return(NULL);
3230 * xmlTextReaderPrefix:
3231 * @reader: the xmlTextReaderPtr used
3233 * A shorthand reference to the namespace associated with the node.
3235 * Returns the prefix or NULL if not available,
3236 * if non NULL it need to be freed by the caller.
3238 xmlChar *
3239 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3240 xmlNodePtr node;
3241 if ((reader == NULL) || (reader->node == NULL))
3242 return(NULL);
3243 if (reader->curnode != NULL)
3244 node = reader->curnode;
3245 else
3246 node = reader->node;
3247 if (node->type == XML_NAMESPACE_DECL) {
3248 xmlNsPtr ns = (xmlNsPtr) node;
3249 if (ns->prefix == NULL)
3250 return(NULL);
3251 return(xmlStrdup(BAD_CAST "xmlns"));
3253 if ((node->type != XML_ELEMENT_NODE) &&
3254 (node->type != XML_ATTRIBUTE_NODE))
3255 return(NULL);
3256 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3257 return(xmlStrdup(node->ns->prefix));
3258 return(NULL);
3262 * xmlTextReaderConstPrefix:
3263 * @reader: the xmlTextReaderPtr used
3265 * A shorthand reference to the namespace associated with the node.
3267 * Returns the prefix or NULL if not available, the string is deallocated
3268 * with the reader.
3270 const xmlChar *
3271 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3272 xmlNodePtr node;
3273 if ((reader == NULL) || (reader->node == NULL))
3274 return(NULL);
3275 if (reader->curnode != NULL)
3276 node = reader->curnode;
3277 else
3278 node = reader->node;
3279 if (node->type == XML_NAMESPACE_DECL) {
3280 xmlNsPtr ns = (xmlNsPtr) node;
3281 if (ns->prefix == NULL)
3282 return(NULL);
3283 return(CONSTSTR(BAD_CAST "xmlns"));
3285 if ((node->type != XML_ELEMENT_NODE) &&
3286 (node->type != XML_ATTRIBUTE_NODE))
3287 return(NULL);
3288 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3289 return(CONSTSTR(node->ns->prefix));
3290 return(NULL);
3294 * xmlTextReaderNamespaceUri:
3295 * @reader: the xmlTextReaderPtr used
3297 * The URI defining the namespace associated with the node.
3299 * Returns the namespace URI or NULL if not available,
3300 * if non NULL it need to be freed by the caller.
3302 xmlChar *
3303 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3304 xmlNodePtr node;
3305 if ((reader == NULL) || (reader->node == NULL))
3306 return(NULL);
3307 if (reader->curnode != NULL)
3308 node = reader->curnode;
3309 else
3310 node = reader->node;
3311 if (node->type == XML_NAMESPACE_DECL)
3312 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3313 if ((node->type != XML_ELEMENT_NODE) &&
3314 (node->type != XML_ATTRIBUTE_NODE))
3315 return(NULL);
3316 if (node->ns != NULL)
3317 return(xmlStrdup(node->ns->href));
3318 return(NULL);
3322 * xmlTextReaderConstNamespaceUri:
3323 * @reader: the xmlTextReaderPtr used
3325 * The URI defining the namespace associated with the node.
3327 * Returns the namespace URI or NULL if not available, the string
3328 * will be deallocated with the reader
3330 const xmlChar *
3331 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3332 xmlNodePtr node;
3333 if ((reader == NULL) || (reader->node == NULL))
3334 return(NULL);
3335 if (reader->curnode != NULL)
3336 node = reader->curnode;
3337 else
3338 node = reader->node;
3339 if (node->type == XML_NAMESPACE_DECL)
3340 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3341 if ((node->type != XML_ELEMENT_NODE) &&
3342 (node->type != XML_ATTRIBUTE_NODE))
3343 return(NULL);
3344 if (node->ns != NULL)
3345 return(CONSTSTR(node->ns->href));
3346 return(NULL);
3350 * xmlTextReaderBaseUri:
3351 * @reader: the xmlTextReaderPtr used
3353 * The base URI of the node.
3355 * Returns the base URI or NULL if not available,
3356 * if non NULL it need to be freed by the caller.
3358 xmlChar *
3359 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3360 if ((reader == NULL) || (reader->node == NULL))
3361 return(NULL);
3362 return(xmlNodeGetBase(NULL, reader->node));
3366 * xmlTextReaderConstBaseUri:
3367 * @reader: the xmlTextReaderPtr used
3369 * The base URI of the node.
3371 * Returns the base URI or NULL if not available, the string
3372 * will be deallocated with the reader
3374 const xmlChar *
3375 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3376 xmlChar *tmp;
3377 const xmlChar *ret;
3379 if ((reader == NULL) || (reader->node == NULL))
3380 return(NULL);
3381 tmp = xmlNodeGetBase(NULL, reader->node);
3382 if (tmp == NULL)
3383 return(NULL);
3384 ret = CONSTSTR(tmp);
3385 xmlFree(tmp);
3386 return(ret);
3390 * xmlTextReaderDepth:
3391 * @reader: the xmlTextReaderPtr used
3393 * The depth of the node in the tree.
3395 * Returns the depth or -1 in case of error
3398 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3399 if (reader == NULL)
3400 return(-1);
3401 if (reader->node == NULL)
3402 return(0);
3404 if (reader->curnode != NULL) {
3405 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3406 (reader->curnode->type == XML_NAMESPACE_DECL))
3407 return(reader->depth + 1);
3408 return(reader->depth + 2);
3410 return(reader->depth);
3414 * xmlTextReaderHasAttributes:
3415 * @reader: the xmlTextReaderPtr used
3417 * Whether the node has attributes.
3419 * Returns 1 if true, 0 if false, and -1 in case or error
3422 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3423 xmlNodePtr node;
3424 if (reader == NULL)
3425 return(-1);
3426 if (reader->node == NULL)
3427 return(0);
3428 if (reader->curnode != NULL)
3429 node = reader->curnode;
3430 else
3431 node = reader->node;
3433 if ((node->type == XML_ELEMENT_NODE) &&
3434 ((node->properties != NULL) || (node->nsDef != NULL)))
3435 return(1);
3436 /* TODO: handle the xmlDecl */
3437 return(0);
3441 * xmlTextReaderHasValue:
3442 * @reader: the xmlTextReaderPtr used
3444 * Whether the node can have a text value.
3446 * Returns 1 if true, 0 if false, and -1 in case or error
3449 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3450 xmlNodePtr node;
3451 if (reader == NULL)
3452 return(-1);
3453 if (reader->node == NULL)
3454 return(0);
3455 if (reader->curnode != NULL)
3456 node = reader->curnode;
3457 else
3458 node = reader->node;
3460 switch (node->type) {
3461 case XML_ATTRIBUTE_NODE:
3462 case XML_TEXT_NODE:
3463 case XML_CDATA_SECTION_NODE:
3464 case XML_PI_NODE:
3465 case XML_COMMENT_NODE:
3466 case XML_NAMESPACE_DECL:
3467 return(1);
3468 default:
3469 break;
3471 return(0);
3475 * xmlTextReaderValue:
3476 * @reader: the xmlTextReaderPtr used
3478 * Provides the text value of the node if present
3480 * Returns the string or NULL if not available. The result must be deallocated
3481 * with xmlFree()
3483 xmlChar *
3484 xmlTextReaderValue(xmlTextReaderPtr reader) {
3485 xmlNodePtr node;
3486 if (reader == NULL)
3487 return(NULL);
3488 if (reader->node == NULL)
3489 return(NULL);
3490 if (reader->curnode != NULL)
3491 node = reader->curnode;
3492 else
3493 node = reader->node;
3495 switch (node->type) {
3496 case XML_NAMESPACE_DECL:
3497 return(xmlStrdup(((xmlNsPtr) node)->href));
3498 case XML_ATTRIBUTE_NODE:{
3499 xmlAttrPtr attr = (xmlAttrPtr) node;
3501 if (attr->parent != NULL)
3502 return (xmlNodeListGetString
3503 (attr->parent->doc, attr->children, 1));
3504 else
3505 return (xmlNodeListGetString(NULL, attr->children, 1));
3506 break;
3508 case XML_TEXT_NODE:
3509 case XML_CDATA_SECTION_NODE:
3510 case XML_PI_NODE:
3511 case XML_COMMENT_NODE:
3512 if (node->content != NULL)
3513 return (xmlStrdup(node->content));
3514 default:
3515 break;
3517 return(NULL);
3521 * xmlTextReaderConstValue:
3522 * @reader: the xmlTextReaderPtr used
3524 * Provides the text value of the node if present
3526 * Returns the string or NULL if not available. The result will be
3527 * deallocated on the next Read() operation.
3529 const xmlChar *
3530 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3531 xmlNodePtr node;
3532 if (reader == NULL)
3533 return(NULL);
3534 if (reader->node == NULL)
3535 return(NULL);
3536 if (reader->curnode != NULL)
3537 node = reader->curnode;
3538 else
3539 node = reader->node;
3541 switch (node->type) {
3542 case XML_NAMESPACE_DECL:
3543 return(((xmlNsPtr) node)->href);
3544 case XML_ATTRIBUTE_NODE:{
3545 xmlAttrPtr attr = (xmlAttrPtr) node;
3546 const xmlChar *ret;
3548 if ((attr->children != NULL) &&
3549 (attr->children->type == XML_TEXT_NODE) &&
3550 (attr->children->next == NULL))
3551 return(attr->children->content);
3552 else {
3553 if (reader->buffer == NULL) {
3554 reader->buffer = xmlBufCreateSize(100);
3555 if (reader->buffer == NULL) {
3556 xmlGenericError(xmlGenericErrorContext,
3557 "xmlTextReaderSetup : malloc failed\n");
3558 return (NULL);
3560 xmlBufSetAllocationScheme(reader->buffer,
3561 XML_BUFFER_ALLOC_DOUBLEIT);
3562 } else
3563 xmlBufEmpty(reader->buffer);
3564 xmlBufGetNodeContent(reader->buffer, node);
3565 ret = xmlBufContent(reader->buffer);
3566 if (ret == NULL) {
3567 /* error on the buffer best to reallocate */
3568 xmlBufFree(reader->buffer);
3569 reader->buffer = xmlBufCreateSize(100);
3570 xmlBufSetAllocationScheme(reader->buffer,
3571 XML_BUFFER_ALLOC_DOUBLEIT);
3572 ret = BAD_CAST "";
3574 return(ret);
3576 break;
3578 case XML_TEXT_NODE:
3579 case XML_CDATA_SECTION_NODE:
3580 case XML_PI_NODE:
3581 case XML_COMMENT_NODE:
3582 return(node->content);
3583 default:
3584 break;
3586 return(NULL);
3590 * xmlTextReaderIsDefault:
3591 * @reader: the xmlTextReaderPtr used
3593 * Whether an Attribute node was generated from the default value
3594 * defined in the DTD or schema.
3596 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3599 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3600 if (reader == NULL)
3601 return(-1);
3602 return(0);
3606 * xmlTextReaderQuoteChar:
3607 * @reader: the xmlTextReaderPtr used
3609 * The quotation mark character used to enclose the value of an attribute.
3611 * Returns " or ' and -1 in case of error
3614 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3615 if (reader == NULL)
3616 return(-1);
3617 /* TODO maybe lookup the attribute value for " first */
3618 return('"');
3622 * xmlTextReaderXmlLang:
3623 * @reader: the xmlTextReaderPtr used
3625 * The xml:lang scope within which the node resides.
3627 * Returns the xml:lang value or NULL if none exists.,
3628 * if non NULL it need to be freed by the caller.
3630 xmlChar *
3631 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3632 if (reader == NULL)
3633 return(NULL);
3634 if (reader->node == NULL)
3635 return(NULL);
3636 return(xmlNodeGetLang(reader->node));
3640 * xmlTextReaderConstXmlLang:
3641 * @reader: the xmlTextReaderPtr used
3643 * The xml:lang scope within which the node resides.
3645 * Returns the xml:lang value or NULL if none exists.
3647 const xmlChar *
3648 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3649 xmlChar *tmp;
3650 const xmlChar *ret;
3652 if (reader == NULL)
3653 return(NULL);
3654 if (reader->node == NULL)
3655 return(NULL);
3656 tmp = xmlNodeGetLang(reader->node);
3657 if (tmp == NULL)
3658 return(NULL);
3659 ret = CONSTSTR(tmp);
3660 xmlFree(tmp);
3661 return(ret);
3665 * xmlTextReaderConstString:
3666 * @reader: the xmlTextReaderPtr used
3667 * @str: the string to intern.
3669 * Get an interned string from the reader, allows for example to
3670 * speedup string name comparisons
3672 * Returns an interned copy of the string or NULL in case of error. The
3673 * string will be deallocated with the reader.
3675 const xmlChar *
3676 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3677 if (reader == NULL)
3678 return(NULL);
3679 return(CONSTSTR(str));
3683 * xmlTextReaderNormalization:
3684 * @reader: the xmlTextReaderPtr used
3686 * The value indicating whether to normalize white space and attribute values.
3687 * Since attribute value and end of line normalizations are a MUST in the XML
3688 * specification only the value true is accepted. The broken behaviour of
3689 * accepting out of range character entities like &#0; is of course not
3690 * supported either.
3692 * Returns 1 or -1 in case of error.
3695 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3696 if (reader == NULL)
3697 return(-1);
3698 return(1);
3701 /************************************************************************
3703 * Extensions to the base APIs *
3705 ************************************************************************/
3708 * xmlTextReaderSetParserProp:
3709 * @reader: the xmlTextReaderPtr used
3710 * @prop: the xmlParserProperties to set
3711 * @value: usually 0 or 1 to (de)activate it
3713 * Change the parser processing behaviour by changing some of its internal
3714 * properties. Note that some properties can only be changed before any
3715 * read has been done.
3717 * Returns 0 if the call was successful, or -1 in case of error
3720 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3721 xmlParserProperties p = (xmlParserProperties) prop;
3722 xmlParserCtxtPtr ctxt;
3724 if ((reader == NULL) || (reader->ctxt == NULL))
3725 return(-1);
3726 ctxt = reader->ctxt;
3728 switch (p) {
3729 case XML_PARSER_LOADDTD:
3730 if (value != 0) {
3731 if (ctxt->loadsubset == 0) {
3732 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3733 return(-1);
3734 ctxt->loadsubset = XML_DETECT_IDS;
3736 } else {
3737 ctxt->loadsubset = 0;
3739 return(0);
3740 case XML_PARSER_DEFAULTATTRS:
3741 if (value != 0) {
3742 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3743 } else {
3744 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3745 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3747 return(0);
3748 case XML_PARSER_VALIDATE:
3749 if (value != 0) {
3750 ctxt->options |= XML_PARSE_DTDVALID;
3751 ctxt->validate = 1;
3752 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3753 } else {
3754 ctxt->options &= ~XML_PARSE_DTDVALID;
3755 ctxt->validate = 0;
3757 return(0);
3758 case XML_PARSER_SUBST_ENTITIES:
3759 if (value != 0) {
3760 ctxt->options |= XML_PARSE_NOENT;
3761 ctxt->replaceEntities = 1;
3762 } else {
3763 ctxt->options &= ~XML_PARSE_NOENT;
3764 ctxt->replaceEntities = 0;
3766 return(0);
3768 return(-1);
3772 * xmlTextReaderGetParserProp:
3773 * @reader: the xmlTextReaderPtr used
3774 * @prop: the xmlParserProperties to get
3776 * Read the parser internal property.
3778 * Returns the value, usually 0 or 1, or -1 in case of error.
3781 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3782 xmlParserProperties p = (xmlParserProperties) prop;
3783 xmlParserCtxtPtr ctxt;
3785 if ((reader == NULL) || (reader->ctxt == NULL))
3786 return(-1);
3787 ctxt = reader->ctxt;
3789 switch (p) {
3790 case XML_PARSER_LOADDTD:
3791 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3792 return(1);
3793 return(0);
3794 case XML_PARSER_DEFAULTATTRS:
3795 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3796 return(1);
3797 return(0);
3798 case XML_PARSER_VALIDATE:
3799 return(reader->validate);
3800 case XML_PARSER_SUBST_ENTITIES:
3801 return(ctxt->replaceEntities);
3803 return(-1);
3808 * xmlTextReaderGetParserLineNumber:
3809 * @reader: the user data (XML reader context)
3811 * Provide the line number of the current parsing point.
3813 * Returns an int or 0 if not available
3816 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3818 if ((reader == NULL) || (reader->ctxt == NULL) ||
3819 (reader->ctxt->input == NULL)) {
3820 return (0);
3822 return (reader->ctxt->input->line);
3826 * xmlTextReaderGetParserColumnNumber:
3827 * @reader: the user data (XML reader context)
3829 * Provide the column number of the current parsing point.
3831 * Returns an int or 0 if not available
3834 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3836 if ((reader == NULL) || (reader->ctxt == NULL) ||
3837 (reader->ctxt->input == NULL)) {
3838 return (0);
3840 return (reader->ctxt->input->col);
3844 * xmlTextReaderCurrentNode:
3845 * @reader: the xmlTextReaderPtr used
3847 * Hacking interface allowing to get the xmlNodePtr corresponding to the
3848 * current node being accessed by the xmlTextReader. This is dangerous
3849 * because the underlying node may be destroyed on the next Reads.
3851 * Returns the xmlNodePtr or NULL in case of error.
3853 xmlNodePtr
3854 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3855 if (reader == NULL)
3856 return(NULL);
3858 if (reader->curnode != NULL)
3859 return(reader->curnode);
3860 return(reader->node);
3864 * xmlTextReaderPreserve:
3865 * @reader: the xmlTextReaderPtr used
3867 * This tells the XML Reader to preserve the current node.
3868 * The caller must also use xmlTextReaderCurrentDoc() to
3869 * keep an handle on the resulting document once parsing has finished
3871 * Returns the xmlNodePtr or NULL in case of error.
3873 xmlNodePtr
3874 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3875 xmlNodePtr cur, parent;
3877 if (reader == NULL)
3878 return(NULL);
3880 if (reader->curnode != NULL)
3881 cur = reader->curnode;
3882 else
3883 cur = reader->node;
3884 if (cur == NULL)
3885 return(NULL);
3887 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3888 cur->extra |= NODE_IS_PRESERVED;
3889 cur->extra |= NODE_IS_SPRESERVED;
3891 reader->preserves++;
3893 parent = cur->parent;
3894 while (parent != NULL) {
3895 if (parent->type == XML_ELEMENT_NODE)
3896 parent->extra |= NODE_IS_PRESERVED;
3897 parent = parent->parent;
3899 return(cur);
3902 #ifdef LIBXML_PATTERN_ENABLED
3904 * xmlTextReaderPreservePattern:
3905 * @reader: the xmlTextReaderPtr used
3906 * @pattern: an XPath subset pattern
3907 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3909 * This tells the XML Reader to preserve all nodes matched by the
3910 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3911 * keep an handle on the resulting document once parsing has finished
3913 * Returns a non-negative number in case of success and -1 in case of error
3916 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3917 const xmlChar **namespaces)
3919 xmlPatternPtr comp;
3921 if ((reader == NULL) || (pattern == NULL))
3922 return(-1);
3924 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3925 if (comp == NULL)
3926 return(-1);
3928 if (reader->patternMax <= 0) {
3929 reader->patternMax = 4;
3930 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3931 sizeof(reader->patternTab[0]));
3932 if (reader->patternTab == NULL) {
3933 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3934 return (-1);
3937 if (reader->patternNr >= reader->patternMax) {
3938 xmlPatternPtr *tmp;
3939 reader->patternMax *= 2;
3940 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3941 reader->patternMax *
3942 sizeof(reader->patternTab[0]));
3943 if (tmp == NULL) {
3944 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3945 reader->patternMax /= 2;
3946 return (-1);
3948 reader->patternTab = tmp;
3950 reader->patternTab[reader->patternNr] = comp;
3951 return(reader->patternNr++);
3953 #endif
3956 * xmlTextReaderCurrentDoc:
3957 * @reader: the xmlTextReaderPtr used
3959 * Hacking interface allowing to get the xmlDocPtr corresponding to the
3960 * current document being accessed by the xmlTextReader.
3961 * NOTE: as a result of this call, the reader will not destroy the
3962 * associated XML document and calling xmlFreeDoc() on the result
3963 * is needed once the reader parsing has finished.
3965 * Returns the xmlDocPtr or NULL in case of error.
3967 xmlDocPtr
3968 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
3969 if (reader == NULL)
3970 return(NULL);
3971 if (reader->doc != NULL)
3972 return(reader->doc);
3973 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
3974 return(NULL);
3976 reader->preserve = 1;
3977 return(reader->ctxt->myDoc);
3980 #ifdef LIBXML_SCHEMAS_ENABLED
3981 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
3983 static void
3984 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3986 static void
3987 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3989 static void
3990 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3992 static void
3993 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3995 static void
3996 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
3998 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4000 char *str;
4002 va_list ap;
4004 va_start(ap, msg);
4005 str = xmlTextReaderBuildMessage(msg, ap);
4006 if (!reader->errorFunc) {
4007 xmlTextReaderValidityError(ctx, "%s", str);
4008 } else {
4009 reader->errorFunc(reader->errorFuncArg, str,
4010 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4011 NULL /* locator */ );
4013 if (str != NULL)
4014 xmlFree(str);
4015 va_end(ap);
4018 static void
4019 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4021 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4023 char *str;
4025 va_list ap;
4027 va_start(ap, msg);
4028 str = xmlTextReaderBuildMessage(msg, ap);
4029 if (!reader->errorFunc) {
4030 xmlTextReaderValidityWarning(ctx, "%s", str);
4031 } else {
4032 reader->errorFunc(reader->errorFuncArg, str,
4033 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4034 NULL /* locator */ );
4036 if (str != NULL)
4037 xmlFree(str);
4038 va_end(ap);
4041 static void
4042 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4044 static void
4045 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4047 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4049 if (reader->sErrorFunc) {
4050 reader->sErrorFunc(reader->errorFuncArg, error);
4051 } else {
4052 xmlTextReaderStructuredError(reader, error);
4056 * xmlTextReaderRelaxNGSetSchema:
4057 * @reader: the xmlTextReaderPtr used
4058 * @schema: a precompiled RelaxNG schema
4060 * Use RelaxNG to validate the document as it is processed.
4061 * Activation is only possible before the first Read().
4062 * if @schema is NULL, then RelaxNG validation is deactivated.
4063 @ The @schema should not be freed until the reader is deallocated
4064 * or its use has been deactivated.
4066 * Returns 0 in case the RelaxNG validation could be (de)activated and
4067 * -1 in case of error.
4070 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4071 if (reader == NULL)
4072 return(-1);
4073 if (schema == NULL) {
4074 if (reader->rngSchemas != NULL) {
4075 xmlRelaxNGFree(reader->rngSchemas);
4076 reader->rngSchemas = NULL;
4078 if (reader->rngValidCtxt != NULL) {
4079 if (! reader->rngPreserveCtxt)
4080 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4081 reader->rngValidCtxt = NULL;
4083 reader->rngPreserveCtxt = 0;
4084 return(0);
4086 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4087 return(-1);
4088 if (reader->rngSchemas != NULL) {
4089 xmlRelaxNGFree(reader->rngSchemas);
4090 reader->rngSchemas = NULL;
4092 if (reader->rngValidCtxt != NULL) {
4093 if (! reader->rngPreserveCtxt)
4094 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4095 reader->rngValidCtxt = NULL;
4097 reader->rngPreserveCtxt = 0;
4098 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4099 if (reader->rngValidCtxt == NULL)
4100 return(-1);
4101 if (reader->errorFunc != NULL) {
4102 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4103 xmlTextReaderValidityErrorRelay,
4104 xmlTextReaderValidityWarningRelay,
4105 reader);
4107 if (reader->sErrorFunc != NULL) {
4108 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4109 xmlTextReaderValidityStructuredRelay,
4110 reader);
4112 reader->rngValidErrors = 0;
4113 reader->rngFullNode = NULL;
4114 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4115 return(0);
4119 * xmlTextReaderLocator:
4120 * @ctx: the xmlTextReaderPtr used
4121 * @file: returned file information
4122 * @line: returned line information
4124 * Internal locator function for the readers
4126 * Returns 0 in case the Schema validation could be (de)activated and
4127 * -1 in case of error.
4129 static int
4130 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4131 xmlTextReaderPtr reader;
4133 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4134 return(-1);
4136 if (file != NULL)
4137 *file = NULL;
4138 if (line != NULL)
4139 *line = 0;
4141 reader = (xmlTextReaderPtr) ctx;
4142 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4143 if (file != NULL)
4144 *file = reader->ctxt->input->filename;
4145 if (line != NULL)
4146 *line = reader->ctxt->input->line;
4147 return(0);
4149 if (reader->node != NULL) {
4150 long res;
4151 int ret = 0;
4153 if (line != NULL) {
4154 res = xmlGetLineNo(reader->node);
4155 if (res > 0)
4156 *line = (unsigned long) res;
4157 else
4158 ret = -1;
4160 if (file != NULL) {
4161 xmlDocPtr doc = reader->node->doc;
4162 if ((doc != NULL) && (doc->URL != NULL))
4163 *file = (const char *) doc->URL;
4164 else
4165 ret = -1;
4167 return(ret);
4169 return(-1);
4173 * xmlTextReaderSetSchema:
4174 * @reader: the xmlTextReaderPtr used
4175 * @schema: a precompiled Schema schema
4177 * Use XSD Schema to validate the document as it is processed.
4178 * Activation is only possible before the first Read().
4179 * if @schema is NULL, then Schema validation is deactivated.
4180 * The @schema should not be freed until the reader is deallocated
4181 * or its use has been deactivated.
4183 * Returns 0 in case the Schema validation could be (de)activated and
4184 * -1 in case of error.
4187 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4188 if (reader == NULL)
4189 return(-1);
4190 if (schema == NULL) {
4191 if (reader->xsdPlug != NULL) {
4192 xmlSchemaSAXUnplug(reader->xsdPlug);
4193 reader->xsdPlug = NULL;
4195 if (reader->xsdValidCtxt != NULL) {
4196 if (! reader->xsdPreserveCtxt)
4197 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4198 reader->xsdValidCtxt = NULL;
4200 reader->xsdPreserveCtxt = 0;
4201 if (reader->xsdSchemas != NULL) {
4202 xmlSchemaFree(reader->xsdSchemas);
4203 reader->xsdSchemas = NULL;
4205 return(0);
4207 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4208 return(-1);
4209 if (reader->xsdPlug != NULL) {
4210 xmlSchemaSAXUnplug(reader->xsdPlug);
4211 reader->xsdPlug = NULL;
4213 if (reader->xsdValidCtxt != NULL) {
4214 if (! reader->xsdPreserveCtxt)
4215 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4216 reader->xsdValidCtxt = NULL;
4218 reader->xsdPreserveCtxt = 0;
4219 if (reader->xsdSchemas != NULL) {
4220 xmlSchemaFree(reader->xsdSchemas);
4221 reader->xsdSchemas = NULL;
4223 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4224 if (reader->xsdValidCtxt == NULL) {
4225 xmlSchemaFree(reader->xsdSchemas);
4226 reader->xsdSchemas = NULL;
4227 return(-1);
4229 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4230 &(reader->ctxt->sax),
4231 &(reader->ctxt->userData));
4232 if (reader->xsdPlug == NULL) {
4233 xmlSchemaFree(reader->xsdSchemas);
4234 reader->xsdSchemas = NULL;
4235 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4236 reader->xsdValidCtxt = NULL;
4237 return(-1);
4239 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4240 xmlTextReaderLocator,
4241 (void *) reader);
4243 if (reader->errorFunc != NULL) {
4244 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4245 xmlTextReaderValidityErrorRelay,
4246 xmlTextReaderValidityWarningRelay,
4247 reader);
4249 if (reader->sErrorFunc != NULL) {
4250 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4251 xmlTextReaderValidityStructuredRelay,
4252 reader);
4254 reader->xsdValidErrors = 0;
4255 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4256 return(0);
4260 * xmlTextReaderRelaxNGValidateInternal:
4261 * @reader: the xmlTextReaderPtr used
4262 * @rng: the path to a RelaxNG schema or NULL
4263 * @ctxt: the RelaxNG schema validation context or NULL
4264 * @options: options (not yet used)
4266 * Use RelaxNG to validate the document as it is processed.
4267 * Activation is only possible before the first Read().
4268 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4270 * Returns 0 in case the RelaxNG validation could be (de)activated and
4271 * -1 in case of error.
4273 static int
4274 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4275 const char *rng,
4276 xmlRelaxNGValidCtxtPtr ctxt,
4277 int options ATTRIBUTE_UNUSED)
4279 if (reader == NULL)
4280 return(-1);
4282 if ((rng != NULL) && (ctxt != NULL))
4283 return (-1);
4285 if (((rng != NULL) || (ctxt != NULL)) &&
4286 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4287 (reader->ctxt == NULL)))
4288 return(-1);
4290 /* Cleanup previous validation stuff. */
4291 if (reader->rngValidCtxt != NULL) {
4292 if ( !reader->rngPreserveCtxt)
4293 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4294 reader->rngValidCtxt = NULL;
4296 reader->rngPreserveCtxt = 0;
4297 if (reader->rngSchemas != NULL) {
4298 xmlRelaxNGFree(reader->rngSchemas);
4299 reader->rngSchemas = NULL;
4302 if ((rng == NULL) && (ctxt == NULL)) {
4303 /* We just want to deactivate the validation, so get out. */
4304 return(0);
4308 if (rng != NULL) {
4309 xmlRelaxNGParserCtxtPtr pctxt;
4310 /* Parse the schema and create validation environment. */
4312 pctxt = xmlRelaxNGNewParserCtxt(rng);
4313 if (reader->errorFunc != NULL) {
4314 xmlRelaxNGSetParserErrors(pctxt,
4315 xmlTextReaderValidityErrorRelay,
4316 xmlTextReaderValidityWarningRelay,
4317 reader);
4319 if (reader->sErrorFunc != NULL) {
4320 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4321 xmlTextReaderValidityStructuredRelay,
4322 reader);
4324 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4325 xmlRelaxNGFreeParserCtxt(pctxt);
4326 if (reader->rngSchemas == NULL)
4327 return(-1);
4328 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4329 if (reader->rngValidCtxt == NULL) {
4330 xmlRelaxNGFree(reader->rngSchemas);
4331 reader->rngSchemas = NULL;
4332 return(-1);
4334 } else {
4335 /* Use the given validation context. */
4336 reader->rngValidCtxt = ctxt;
4337 reader->rngPreserveCtxt = 1;
4340 * Redirect the validation context's error channels to use
4341 * the reader channels.
4342 * TODO: In case the user provides the validation context we
4343 * could make this redirection optional.
4345 if (reader->errorFunc != NULL) {
4346 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4347 xmlTextReaderValidityErrorRelay,
4348 xmlTextReaderValidityWarningRelay,
4349 reader);
4351 if (reader->sErrorFunc != NULL) {
4352 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4353 xmlTextReaderValidityStructuredRelay,
4354 reader);
4356 reader->rngValidErrors = 0;
4357 reader->rngFullNode = NULL;
4358 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4359 return(0);
4363 * xmlTextReaderSchemaValidateInternal:
4364 * @reader: the xmlTextReaderPtr used
4365 * @xsd: the path to a W3C XSD schema or NULL
4366 * @ctxt: the XML Schema validation context or NULL
4367 * @options: options (not used yet)
4369 * Validate the document as it is processed using XML Schema.
4370 * Activation is only possible before the first Read().
4371 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4373 * Returns 0 in case the schemas validation could be (de)activated and
4374 * -1 in case of error.
4376 static int
4377 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4378 const char *xsd,
4379 xmlSchemaValidCtxtPtr ctxt,
4380 int options ATTRIBUTE_UNUSED)
4382 if (reader == NULL)
4383 return(-1);
4385 if ((xsd != NULL) && (ctxt != NULL))
4386 return(-1);
4388 if (((xsd != NULL) || (ctxt != NULL)) &&
4389 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4390 (reader->ctxt == NULL)))
4391 return(-1);
4393 /* Cleanup previous validation stuff. */
4394 if (reader->xsdPlug != NULL) {
4395 xmlSchemaSAXUnplug(reader->xsdPlug);
4396 reader->xsdPlug = NULL;
4398 if (reader->xsdValidCtxt != NULL) {
4399 if (! reader->xsdPreserveCtxt)
4400 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4401 reader->xsdValidCtxt = NULL;
4403 reader->xsdPreserveCtxt = 0;
4404 if (reader->xsdSchemas != NULL) {
4405 xmlSchemaFree(reader->xsdSchemas);
4406 reader->xsdSchemas = NULL;
4409 if ((xsd == NULL) && (ctxt == NULL)) {
4410 /* We just want to deactivate the validation, so get out. */
4411 return(0);
4414 if (xsd != NULL) {
4415 xmlSchemaParserCtxtPtr pctxt;
4416 /* Parse the schema and create validation environment. */
4417 pctxt = xmlSchemaNewParserCtxt(xsd);
4418 if (reader->errorFunc != NULL) {
4419 xmlSchemaSetParserErrors(pctxt,
4420 xmlTextReaderValidityErrorRelay,
4421 xmlTextReaderValidityWarningRelay,
4422 reader);
4424 reader->xsdSchemas = xmlSchemaParse(pctxt);
4425 xmlSchemaFreeParserCtxt(pctxt);
4426 if (reader->xsdSchemas == NULL)
4427 return(-1);
4428 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4429 if (reader->xsdValidCtxt == NULL) {
4430 xmlSchemaFree(reader->xsdSchemas);
4431 reader->xsdSchemas = NULL;
4432 return(-1);
4434 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4435 &(reader->ctxt->sax),
4436 &(reader->ctxt->userData));
4437 if (reader->xsdPlug == NULL) {
4438 xmlSchemaFree(reader->xsdSchemas);
4439 reader->xsdSchemas = NULL;
4440 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4441 reader->xsdValidCtxt = NULL;
4442 return(-1);
4444 } else {
4445 /* Use the given validation context. */
4446 reader->xsdValidCtxt = ctxt;
4447 reader->xsdPreserveCtxt = 1;
4448 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4449 &(reader->ctxt->sax),
4450 &(reader->ctxt->userData));
4451 if (reader->xsdPlug == NULL) {
4452 reader->xsdValidCtxt = NULL;
4453 reader->xsdPreserveCtxt = 0;
4454 return(-1);
4457 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4458 xmlTextReaderLocator,
4459 (void *) reader);
4461 * Redirect the validation context's error channels to use
4462 * the reader channels.
4463 * TODO: In case the user provides the validation context we
4464 * could make this redirection optional.
4466 if (reader->errorFunc != NULL) {
4467 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4468 xmlTextReaderValidityErrorRelay,
4469 xmlTextReaderValidityWarningRelay,
4470 reader);
4472 if (reader->sErrorFunc != NULL) {
4473 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4474 xmlTextReaderValidityStructuredRelay,
4475 reader);
4477 reader->xsdValidErrors = 0;
4478 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4479 return(0);
4483 * xmlTextReaderSchemaValidateCtxt:
4484 * @reader: the xmlTextReaderPtr used
4485 * @ctxt: the XML Schema validation context or NULL
4486 * @options: options (not used yet)
4488 * Use W3C XSD schema context to validate the document as it is processed.
4489 * Activation is only possible before the first Read().
4490 * If @ctxt is NULL, then XML Schema validation is deactivated.
4492 * Returns 0 in case the schemas validation could be (de)activated and
4493 * -1 in case of error.
4496 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4497 xmlSchemaValidCtxtPtr ctxt,
4498 int options)
4500 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4504 * xmlTextReaderSchemaValidate:
4505 * @reader: the xmlTextReaderPtr used
4506 * @xsd: the path to a W3C XSD schema or NULL
4508 * Use W3C XSD schema to validate the document as it is processed.
4509 * Activation is only possible before the first Read().
4510 * If @xsd is NULL, then XML Schema validation is deactivated.
4512 * Returns 0 in case the schemas validation could be (de)activated and
4513 * -1 in case of error.
4516 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4518 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4522 * xmlTextReaderRelaxNGValidateCtxt:
4523 * @reader: the xmlTextReaderPtr used
4524 * @ctxt: the RelaxNG schema validation context or NULL
4525 * @options: options (not used yet)
4527 * Use RelaxNG schema context to validate the document as it is processed.
4528 * Activation is only possible before the first Read().
4529 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4531 * Returns 0 in case the schemas validation could be (de)activated and
4532 * -1 in case of error.
4535 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4536 xmlRelaxNGValidCtxtPtr ctxt,
4537 int options)
4539 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4543 * xmlTextReaderRelaxNGValidate:
4544 * @reader: the xmlTextReaderPtr used
4545 * @rng: the path to a RelaxNG schema or NULL
4547 * Use RelaxNG schema to validate the document as it is processed.
4548 * Activation is only possible before the first Read().
4549 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4551 * Returns 0 in case the schemas validation could be (de)activated and
4552 * -1 in case of error.
4555 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4557 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4560 #endif
4563 * xmlTextReaderIsNamespaceDecl:
4564 * @reader: the xmlTextReaderPtr used
4566 * Determine whether the current node is a namespace declaration
4567 * rather than a regular attribute.
4569 * Returns 1 if the current node is a namespace declaration, 0 if it
4570 * is a regular attribute or other type of node, or -1 in case of
4571 * error.
4574 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4575 xmlNodePtr node;
4576 if (reader == NULL)
4577 return(-1);
4578 if (reader->node == NULL)
4579 return(-1);
4580 if (reader->curnode != NULL)
4581 node = reader->curnode;
4582 else
4583 node = reader->node;
4585 if (XML_NAMESPACE_DECL == node->type)
4586 return(1);
4587 else
4588 return(0);
4592 * xmlTextReaderConstXmlVersion:
4593 * @reader: the xmlTextReaderPtr used
4595 * Determine the XML version of the document being read.
4597 * Returns a string containing the XML version of the document or NULL
4598 * in case of error. The string is deallocated with the reader.
4600 const xmlChar *
4601 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4602 xmlDocPtr doc = NULL;
4603 if (reader == NULL)
4604 return(NULL);
4605 if (reader->doc != NULL)
4606 doc = reader->doc;
4607 else if (reader->ctxt != NULL)
4608 doc = reader->ctxt->myDoc;
4609 if (doc == NULL)
4610 return(NULL);
4612 if (doc->version == NULL)
4613 return(NULL);
4614 else
4615 return(CONSTSTR(doc->version));
4619 * xmlTextReaderStandalone:
4620 * @reader: the xmlTextReaderPtr used
4622 * Determine the standalone status of the document being read.
4624 * Returns 1 if the document was declared to be standalone, 0 if it
4625 * was declared to be not standalone, or -1 if the document did not
4626 * specify its standalone status or in case of error.
4629 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4630 xmlDocPtr doc = NULL;
4631 if (reader == NULL)
4632 return(-1);
4633 if (reader->doc != NULL)
4634 doc = reader->doc;
4635 else if (reader->ctxt != NULL)
4636 doc = reader->ctxt->myDoc;
4637 if (doc == NULL)
4638 return(-1);
4640 return(doc->standalone);
4643 /************************************************************************
4645 * Error Handling Extensions *
4647 ************************************************************************/
4649 /* helper to build a xmlMalloc'ed string from a format and va_list */
4650 static char *
4651 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4652 int size = 0;
4653 int chars;
4654 char *larger;
4655 char *str = NULL;
4656 va_list aq;
4658 while (1) {
4659 VA_COPY(aq, ap);
4660 chars = vsnprintf(str, size, msg, aq);
4661 va_end(aq);
4662 if (chars < 0) {
4663 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4664 if (str)
4665 xmlFree(str);
4666 return NULL;
4668 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4669 break;
4670 if (chars < MAX_ERR_MSG_SIZE)
4671 size = chars + 1;
4672 else
4673 size = MAX_ERR_MSG_SIZE;
4674 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4675 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4676 if (str)
4677 xmlFree(str);
4678 return NULL;
4680 str = larger;
4683 return str;
4687 * xmlTextReaderLocatorLineNumber:
4688 * @locator: the xmlTextReaderLocatorPtr used
4690 * Obtain the line number for the given locator.
4692 * Returns the line number or -1 in case of error.
4695 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4696 /* we know that locator is a xmlParserCtxtPtr */
4697 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4698 int ret = -1;
4700 if (locator == NULL)
4701 return(-1);
4702 if (ctx->node != NULL) {
4703 ret = xmlGetLineNo(ctx->node);
4705 else {
4706 /* inspired from error.c */
4707 xmlParserInputPtr input;
4708 input = ctx->input;
4709 if ((input->filename == NULL) && (ctx->inputNr > 1))
4710 input = ctx->inputTab[ctx->inputNr - 2];
4711 if (input != NULL) {
4712 ret = input->line;
4714 else {
4715 ret = -1;
4719 return ret;
4723 * xmlTextReaderLocatorBaseURI:
4724 * @locator: the xmlTextReaderLocatorPtr used
4726 * Obtain the base URI for the given locator.
4728 * Returns the base URI or NULL in case of error,
4729 * if non NULL it need to be freed by the caller.
4731 xmlChar *
4732 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4733 /* we know that locator is a xmlParserCtxtPtr */
4734 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4735 xmlChar *ret = NULL;
4737 if (locator == NULL)
4738 return(NULL);
4739 if (ctx->node != NULL) {
4740 ret = xmlNodeGetBase(NULL,ctx->node);
4742 else {
4743 /* inspired from error.c */
4744 xmlParserInputPtr input;
4745 input = ctx->input;
4746 if ((input->filename == NULL) && (ctx->inputNr > 1))
4747 input = ctx->inputTab[ctx->inputNr - 2];
4748 if (input != NULL) {
4749 ret = xmlStrdup(BAD_CAST input->filename);
4751 else {
4752 ret = NULL;
4756 return ret;
4759 static void
4760 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4761 char *str)
4763 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4765 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4767 if (str != NULL) {
4768 if (reader->errorFunc)
4769 reader->errorFunc(reader->errorFuncArg, str, severity,
4770 (xmlTextReaderLocatorPtr) ctx);
4771 xmlFree(str);
4775 static void
4776 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4778 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4780 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4782 if (error && reader->sErrorFunc) {
4783 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4787 static void LIBXML_ATTR_FORMAT(2,3)
4788 xmlTextReaderError(void *ctxt, const char *msg, ...)
4790 va_list ap;
4792 va_start(ap, msg);
4793 xmlTextReaderGenericError(ctxt,
4794 XML_PARSER_SEVERITY_ERROR,
4795 xmlTextReaderBuildMessage(msg, ap));
4796 va_end(ap);
4800 static void LIBXML_ATTR_FORMAT(2,3)
4801 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4803 va_list ap;
4805 va_start(ap, msg);
4806 xmlTextReaderGenericError(ctxt,
4807 XML_PARSER_SEVERITY_WARNING,
4808 xmlTextReaderBuildMessage(msg, ap));
4809 va_end(ap);
4812 static void
4813 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4815 va_list ap;
4817 int len = xmlStrlen((const xmlChar *) msg);
4819 if ((len > 1) && (msg[len - 2] != ':')) {
4821 * some callbacks only report locator information:
4822 * skip them (mimicking behaviour in error.c)
4824 va_start(ap, msg);
4825 xmlTextReaderGenericError(ctxt,
4826 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4827 xmlTextReaderBuildMessage(msg, ap));
4828 va_end(ap);
4832 static void
4833 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4835 va_list ap;
4837 int len = xmlStrlen((const xmlChar *) msg);
4839 if ((len != 0) && (msg[len - 1] != ':')) {
4841 * some callbacks only report locator information:
4842 * skip them (mimicking behaviour in error.c)
4844 va_start(ap, msg);
4845 xmlTextReaderGenericError(ctxt,
4846 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4847 xmlTextReaderBuildMessage(msg, ap));
4848 va_end(ap);
4853 * xmlTextReaderSetErrorHandler:
4854 * @reader: the xmlTextReaderPtr used
4855 * @f: the callback function to call on error and warnings
4856 * @arg: a user argument to pass to the callback function
4858 * Register a callback function that will be called on error and warnings.
4860 * If @f is NULL, the default error and warning handlers are restored.
4862 void
4863 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4864 xmlTextReaderErrorFunc f, void *arg)
4866 if (f != NULL) {
4867 reader->ctxt->sax->error = xmlTextReaderError;
4868 reader->ctxt->sax->serror = NULL;
4869 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4870 reader->ctxt->sax->warning = xmlTextReaderWarning;
4871 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4872 reader->errorFunc = f;
4873 reader->sErrorFunc = NULL;
4874 reader->errorFuncArg = arg;
4875 #ifdef LIBXML_SCHEMAS_ENABLED
4876 if (reader->rngValidCtxt) {
4877 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4878 xmlTextReaderValidityErrorRelay,
4879 xmlTextReaderValidityWarningRelay,
4880 reader);
4881 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4882 reader);
4884 if (reader->xsdValidCtxt) {
4885 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4886 xmlTextReaderValidityErrorRelay,
4887 xmlTextReaderValidityWarningRelay,
4888 reader);
4889 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4890 reader);
4892 #endif
4893 } else {
4894 /* restore defaults */
4895 reader->ctxt->sax->error = xmlParserError;
4896 reader->ctxt->vctxt.error = xmlParserValidityError;
4897 reader->ctxt->sax->warning = xmlParserWarning;
4898 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4899 reader->errorFunc = NULL;
4900 reader->sErrorFunc = NULL;
4901 reader->errorFuncArg = NULL;
4902 #ifdef LIBXML_SCHEMAS_ENABLED
4903 if (reader->rngValidCtxt) {
4904 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4905 reader);
4906 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4907 reader);
4909 if (reader->xsdValidCtxt) {
4910 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4911 reader);
4912 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4913 reader);
4915 #endif
4920 * xmlTextReaderSetStructuredErrorHandler:
4921 * @reader: the xmlTextReaderPtr used
4922 * @f: the callback function to call on error and warnings
4923 * @arg: a user argument to pass to the callback function
4925 * Register a callback function that will be called on error and warnings.
4927 * If @f is NULL, the default error and warning handlers are restored.
4929 void
4930 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4931 xmlStructuredErrorFunc f, void *arg)
4933 if (f != NULL) {
4934 reader->ctxt->sax->error = NULL;
4935 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4936 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4937 reader->ctxt->sax->warning = xmlTextReaderWarning;
4938 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4939 reader->sErrorFunc = f;
4940 reader->errorFunc = NULL;
4941 reader->errorFuncArg = arg;
4942 #ifdef LIBXML_SCHEMAS_ENABLED
4943 if (reader->rngValidCtxt) {
4944 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4945 reader);
4946 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4947 xmlTextReaderValidityStructuredRelay,
4948 reader);
4950 if (reader->xsdValidCtxt) {
4951 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4952 reader);
4953 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4954 xmlTextReaderValidityStructuredRelay,
4955 reader);
4957 #endif
4958 } else {
4959 /* restore defaults */
4960 reader->ctxt->sax->error = xmlParserError;
4961 reader->ctxt->sax->serror = NULL;
4962 reader->ctxt->vctxt.error = xmlParserValidityError;
4963 reader->ctxt->sax->warning = xmlParserWarning;
4964 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4965 reader->errorFunc = NULL;
4966 reader->sErrorFunc = NULL;
4967 reader->errorFuncArg = NULL;
4968 #ifdef LIBXML_SCHEMAS_ENABLED
4969 if (reader->rngValidCtxt) {
4970 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4971 reader);
4972 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4973 reader);
4975 if (reader->xsdValidCtxt) {
4976 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4977 reader);
4978 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4979 reader);
4981 #endif
4986 * xmlTextReaderIsValid:
4987 * @reader: the xmlTextReaderPtr used
4989 * Retrieve the validity status from the parser context
4991 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4994 xmlTextReaderIsValid(xmlTextReaderPtr reader)
4996 if (reader == NULL)
4997 return (-1);
4998 #ifdef LIBXML_SCHEMAS_ENABLED
4999 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5000 return (reader->rngValidErrors == 0);
5001 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5002 return (reader->xsdValidErrors == 0);
5003 #endif
5004 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5005 return (reader->ctxt->valid);
5006 return (0);
5010 * xmlTextReaderGetErrorHandler:
5011 * @reader: the xmlTextReaderPtr used
5012 * @f: the callback function or NULL is no callback has been registered
5013 * @arg: a user argument
5015 * Retrieve the error callback function and user argument.
5017 void
5018 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5019 xmlTextReaderErrorFunc * f, void **arg)
5021 if (f != NULL)
5022 *f = reader->errorFunc;
5023 if (arg != NULL)
5024 *arg = reader->errorFuncArg;
5026 /************************************************************************
5028 * New set (2.6.0) of simpler and more flexible APIs *
5030 ************************************************************************/
5033 * xmlTextReaderSetup:
5034 * @reader: an XML reader
5035 * @input: xmlParserInputBufferPtr used to feed the reader, will
5036 * be destroyed with it.
5037 * @URL: the base URL to use for the document
5038 * @encoding: the document encoding, or NULL
5039 * @options: a combination of xmlParserOption
5041 * Setup an XML reader with new options
5043 * Returns 0 in case of success and -1 in case of error.
5046 xmlTextReaderSetup(xmlTextReaderPtr reader,
5047 xmlParserInputBufferPtr input, const char *URL,
5048 const char *encoding, int options)
5050 if (reader == NULL) {
5051 if (input != NULL)
5052 xmlFreeParserInputBuffer(input);
5053 return (-1);
5057 * we force the generation of compact text nodes on the reader
5058 * since usr applications should never modify the tree
5060 options |= XML_PARSE_COMPACT;
5062 reader->doc = NULL;
5063 reader->entNr = 0;
5064 reader->parserFlags = options;
5065 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5066 if ((input != NULL) && (reader->input != NULL) &&
5067 (reader->allocs & XML_TEXTREADER_INPUT)) {
5068 xmlFreeParserInputBuffer(reader->input);
5069 reader->input = NULL;
5070 reader->allocs -= XML_TEXTREADER_INPUT;
5072 if (input != NULL) {
5073 reader->input = input;
5074 reader->allocs |= XML_TEXTREADER_INPUT;
5076 if (reader->buffer == NULL)
5077 reader->buffer = xmlBufCreateSize(100);
5078 if (reader->buffer == NULL) {
5079 xmlGenericError(xmlGenericErrorContext,
5080 "xmlTextReaderSetup : malloc failed\n");
5081 return (-1);
5083 /* no operation on a reader should require a huge buffer */
5084 xmlBufSetAllocationScheme(reader->buffer,
5085 XML_BUFFER_ALLOC_DOUBLEIT);
5086 if (reader->sax == NULL)
5087 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5088 if (reader->sax == NULL) {
5089 xmlGenericError(xmlGenericErrorContext,
5090 "xmlTextReaderSetup : malloc failed\n");
5091 return (-1);
5093 xmlSAXVersion(reader->sax, 2);
5094 reader->startElement = reader->sax->startElement;
5095 reader->sax->startElement = xmlTextReaderStartElement;
5096 reader->endElement = reader->sax->endElement;
5097 reader->sax->endElement = xmlTextReaderEndElement;
5098 #ifdef LIBXML_SAX1_ENABLED
5099 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5100 #endif /* LIBXML_SAX1_ENABLED */
5101 reader->startElementNs = reader->sax->startElementNs;
5102 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5103 reader->endElementNs = reader->sax->endElementNs;
5104 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5105 #ifdef LIBXML_SAX1_ENABLED
5106 } else {
5107 reader->startElementNs = NULL;
5108 reader->endElementNs = NULL;
5110 #endif /* LIBXML_SAX1_ENABLED */
5111 reader->characters = reader->sax->characters;
5112 reader->sax->characters = xmlTextReaderCharacters;
5113 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5114 reader->cdataBlock = reader->sax->cdataBlock;
5115 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5117 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5118 reader->node = NULL;
5119 reader->curnode = NULL;
5120 if (input != NULL) {
5121 if (xmlBufUse(reader->input->buffer) < 4) {
5122 xmlParserInputBufferRead(input, 4);
5124 if (reader->ctxt == NULL) {
5125 if (xmlBufUse(reader->input->buffer) >= 4) {
5126 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5127 (const char *) xmlBufContent(reader->input->buffer),
5128 4, URL);
5129 reader->base = 0;
5130 reader->cur = 4;
5131 } else {
5132 reader->ctxt =
5133 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5134 reader->base = 0;
5135 reader->cur = 0;
5137 } else {
5138 xmlParserInputPtr inputStream;
5139 xmlParserInputBufferPtr buf;
5140 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5142 xmlCtxtReset(reader->ctxt);
5143 buf = xmlAllocParserInputBuffer(enc);
5144 if (buf == NULL) return(-1);
5145 inputStream = xmlNewInputStream(reader->ctxt);
5146 if (inputStream == NULL) {
5147 xmlFreeParserInputBuffer(buf);
5148 return(-1);
5151 if (URL == NULL)
5152 inputStream->filename = NULL;
5153 else
5154 inputStream->filename = (char *)
5155 xmlCanonicPath((const xmlChar *) URL);
5156 inputStream->buf = buf;
5157 xmlBufResetInput(buf->buffer, inputStream);
5159 inputPush(reader->ctxt, inputStream);
5160 reader->cur = 0;
5162 if (reader->ctxt == NULL) {
5163 xmlGenericError(xmlGenericErrorContext,
5164 "xmlTextReaderSetup : malloc failed\n");
5165 return (-1);
5168 if (reader->dict != NULL) {
5169 if (reader->ctxt->dict != NULL) {
5170 if (reader->dict != reader->ctxt->dict) {
5171 xmlDictFree(reader->dict);
5172 reader->dict = reader->ctxt->dict;
5174 } else {
5175 reader->ctxt->dict = reader->dict;
5177 } else {
5178 if (reader->ctxt->dict == NULL)
5179 reader->ctxt->dict = xmlDictCreate();
5180 reader->dict = reader->ctxt->dict;
5182 reader->ctxt->_private = reader;
5183 reader->ctxt->linenumbers = 1;
5184 reader->ctxt->dictNames = 1;
5186 * use the parser dictionary to allocate all elements and attributes names
5188 reader->ctxt->docdict = 1;
5189 reader->ctxt->parseMode = XML_PARSE_READER;
5191 #ifdef LIBXML_XINCLUDE_ENABLED
5192 if (reader->xincctxt != NULL) {
5193 xmlXIncludeFreeContext(reader->xincctxt);
5194 reader->xincctxt = NULL;
5196 if (options & XML_PARSE_XINCLUDE) {
5197 reader->xinclude = 1;
5198 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5199 options -= XML_PARSE_XINCLUDE;
5200 } else
5201 reader->xinclude = 0;
5202 reader->in_xinclude = 0;
5203 #endif
5204 #ifdef LIBXML_PATTERN_ENABLED
5205 if (reader->patternTab == NULL) {
5206 reader->patternNr = 0;
5207 reader->patternMax = 0;
5209 while (reader->patternNr > 0) {
5210 reader->patternNr--;
5211 if (reader->patternTab[reader->patternNr] != NULL) {
5212 xmlFreePattern(reader->patternTab[reader->patternNr]);
5213 reader->patternTab[reader->patternNr] = NULL;
5216 #endif
5218 if (options & XML_PARSE_DTDVALID)
5219 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5221 xmlCtxtUseOptions(reader->ctxt, options);
5222 if (encoding != NULL) {
5223 xmlCharEncodingHandlerPtr hdlr;
5225 hdlr = xmlFindCharEncodingHandler(encoding);
5226 if (hdlr != NULL)
5227 xmlSwitchToEncoding(reader->ctxt, hdlr);
5229 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5230 (reader->ctxt->input->filename == NULL))
5231 reader->ctxt->input->filename = (char *)
5232 xmlStrdup((const xmlChar *) URL);
5234 reader->doc = NULL;
5236 return (0);
5240 * xmlTextReaderByteConsumed:
5241 * @reader: an XML reader
5243 * This function provides the current index of the parser used
5244 * by the reader, relative to the start of the current entity.
5245 * This function actually just wraps a call to xmlBytesConsumed()
5246 * for the parser context associated with the reader.
5247 * See xmlBytesConsumed() for more information.
5249 * Returns the index in bytes from the beginning of the entity or -1
5250 * in case the index could not be computed.
5252 long
5253 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5254 if ((reader == NULL) || (reader->ctxt == NULL))
5255 return(-1);
5256 return(xmlByteConsumed(reader->ctxt));
5261 * xmlReaderWalker:
5262 * @doc: a preparsed document
5264 * Create an xmltextReader for a preparsed document.
5266 * Returns the new reader or NULL in case of error.
5268 xmlTextReaderPtr
5269 xmlReaderWalker(xmlDocPtr doc)
5271 xmlTextReaderPtr ret;
5273 if (doc == NULL)
5274 return(NULL);
5276 ret = xmlMalloc(sizeof(xmlTextReader));
5277 if (ret == NULL) {
5278 xmlGenericError(xmlGenericErrorContext,
5279 "xmlNewTextReader : malloc failed\n");
5280 return(NULL);
5282 memset(ret, 0, sizeof(xmlTextReader));
5283 ret->entNr = 0;
5284 ret->input = NULL;
5285 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5286 ret->node = NULL;
5287 ret->curnode = NULL;
5288 ret->base = 0;
5289 ret->cur = 0;
5290 ret->allocs = XML_TEXTREADER_CTXT;
5291 ret->doc = doc;
5292 ret->state = XML_TEXTREADER_START;
5293 ret->dict = xmlDictCreate();
5294 return(ret);
5298 * xmlReaderForDoc:
5299 * @cur: a pointer to a zero terminated string
5300 * @URL: the base URL to use for the document
5301 * @encoding: the document encoding, or NULL
5302 * @options: a combination of xmlParserOption
5304 * Create an xmltextReader for an XML in-memory document.
5305 * The parsing flags @options are a combination of xmlParserOption.
5307 * Returns the new reader or NULL in case of error.
5309 xmlTextReaderPtr
5310 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5311 int options)
5313 int len;
5315 if (cur == NULL)
5316 return (NULL);
5317 len = xmlStrlen(cur);
5319 return (xmlReaderForMemory
5320 ((const char *) cur, len, URL, encoding, options));
5324 * xmlReaderForFile:
5325 * @filename: a file or URL
5326 * @encoding: the document encoding, or NULL
5327 * @options: a combination of xmlParserOption
5329 * parse an XML file from the filesystem or the network.
5330 * The parsing flags @options are a combination of xmlParserOption.
5332 * Returns the new reader or NULL in case of error.
5334 xmlTextReaderPtr
5335 xmlReaderForFile(const char *filename, const char *encoding, int options)
5337 xmlTextReaderPtr reader;
5339 reader = xmlNewTextReaderFilename(filename);
5340 if (reader == NULL)
5341 return (NULL);
5342 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5343 return (reader);
5347 * xmlReaderForMemory:
5348 * @buffer: a pointer to a char array
5349 * @size: the size of the array
5350 * @URL: the base URL to use for the document
5351 * @encoding: the document encoding, or NULL
5352 * @options: a combination of xmlParserOption
5354 * Create an xmltextReader for an XML in-memory document.
5355 * The parsing flags @options are a combination of xmlParserOption.
5357 * Returns the new reader or NULL in case of error.
5359 xmlTextReaderPtr
5360 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5361 const char *encoding, int options)
5363 xmlTextReaderPtr reader;
5364 xmlParserInputBufferPtr buf;
5366 buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
5367 if (buf == NULL) {
5368 return (NULL);
5370 reader = xmlNewTextReader(buf, URL);
5371 if (reader == NULL) {
5372 xmlFreeParserInputBuffer(buf);
5373 return (NULL);
5375 reader->allocs |= XML_TEXTREADER_INPUT;
5376 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5377 return (reader);
5381 * xmlReaderForFd:
5382 * @fd: an open file descriptor
5383 * @URL: the base URL to use for the document
5384 * @encoding: the document encoding, or NULL
5385 * @options: a combination of xmlParserOption
5387 * Create an xmltextReader for an XML from a file descriptor.
5388 * The parsing flags @options are a combination of xmlParserOption.
5389 * NOTE that the file descriptor will not be closed when the
5390 * reader is closed or reset.
5392 * Returns the new reader or NULL in case of error.
5394 xmlTextReaderPtr
5395 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5397 xmlTextReaderPtr reader;
5398 xmlParserInputBufferPtr input;
5400 if (fd < 0)
5401 return (NULL);
5403 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5404 if (input == NULL)
5405 return (NULL);
5406 input->closecallback = NULL;
5407 reader = xmlNewTextReader(input, URL);
5408 if (reader == NULL) {
5409 xmlFreeParserInputBuffer(input);
5410 return (NULL);
5412 reader->allocs |= XML_TEXTREADER_INPUT;
5413 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5414 return (reader);
5418 * xmlReaderForIO:
5419 * @ioread: an I/O read function
5420 * @ioclose: an I/O close function
5421 * @ioctx: an I/O handler
5422 * @URL: the base URL to use for the document
5423 * @encoding: the document encoding, or NULL
5424 * @options: a combination of xmlParserOption
5426 * Create an xmltextReader for an XML document from I/O functions and source.
5427 * The parsing flags @options are a combination of xmlParserOption.
5429 * Returns the new reader or NULL in case of error.
5431 xmlTextReaderPtr
5432 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5433 void *ioctx, const char *URL, const char *encoding,
5434 int options)
5436 xmlTextReaderPtr reader;
5437 xmlParserInputBufferPtr input;
5439 if (ioread == NULL)
5440 return (NULL);
5442 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5443 XML_CHAR_ENCODING_NONE);
5444 if (input == NULL) {
5445 if (ioclose != NULL)
5446 ioclose(ioctx);
5447 return (NULL);
5449 reader = xmlNewTextReader(input, URL);
5450 if (reader == NULL) {
5451 xmlFreeParserInputBuffer(input);
5452 return (NULL);
5454 reader->allocs |= XML_TEXTREADER_INPUT;
5455 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5456 return (reader);
5460 * xmlReaderNewWalker:
5461 * @reader: an XML reader
5462 * @doc: a preparsed document
5464 * Setup an xmltextReader to parse a preparsed XML document.
5465 * This reuses the existing @reader xmlTextReader.
5467 * Returns 0 in case of success and -1 in case of error
5470 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5472 if (doc == NULL)
5473 return (-1);
5474 if (reader == NULL)
5475 return (-1);
5477 if (reader->input != NULL) {
5478 xmlFreeParserInputBuffer(reader->input);
5480 if (reader->ctxt != NULL) {
5481 xmlCtxtReset(reader->ctxt);
5484 reader->entNr = 0;
5485 reader->input = NULL;
5486 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5487 reader->node = NULL;
5488 reader->curnode = NULL;
5489 reader->base = 0;
5490 reader->cur = 0;
5491 reader->allocs = XML_TEXTREADER_CTXT;
5492 reader->doc = doc;
5493 reader->state = XML_TEXTREADER_START;
5494 if (reader->dict == NULL) {
5495 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5496 reader->dict = reader->ctxt->dict;
5497 else
5498 reader->dict = xmlDictCreate();
5500 return(0);
5504 * xmlReaderNewDoc:
5505 * @reader: an XML reader
5506 * @cur: a pointer to a zero terminated string
5507 * @URL: the base URL to use for the document
5508 * @encoding: the document encoding, or NULL
5509 * @options: a combination of xmlParserOption
5511 * Setup an xmltextReader to parse an XML in-memory document.
5512 * The parsing flags @options are a combination of xmlParserOption.
5513 * This reuses the existing @reader xmlTextReader.
5515 * Returns 0 in case of success and -1 in case of error
5518 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5519 const char *URL, const char *encoding, int options)
5522 int len;
5524 if (cur == NULL)
5525 return (-1);
5526 if (reader == NULL)
5527 return (-1);
5529 len = xmlStrlen(cur);
5530 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5531 URL, encoding, options));
5535 * xmlReaderNewFile:
5536 * @reader: an XML reader
5537 * @filename: a file or URL
5538 * @encoding: the document encoding, or NULL
5539 * @options: a combination of xmlParserOption
5541 * parse an XML file from the filesystem or the network.
5542 * The parsing flags @options are a combination of xmlParserOption.
5543 * This reuses the existing @reader xmlTextReader.
5545 * Returns 0 in case of success and -1 in case of error
5548 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5549 const char *encoding, int options)
5551 xmlParserInputBufferPtr input;
5553 if (filename == NULL)
5554 return (-1);
5555 if (reader == NULL)
5556 return (-1);
5558 input =
5559 xmlParserInputBufferCreateFilename(filename,
5560 XML_CHAR_ENCODING_NONE);
5561 if (input == NULL)
5562 return (-1);
5563 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5567 * xmlReaderNewMemory:
5568 * @reader: an XML reader
5569 * @buffer: a pointer to a char array
5570 * @size: the size of the array
5571 * @URL: the base URL to use for the document
5572 * @encoding: the document encoding, or NULL
5573 * @options: a combination of xmlParserOption
5575 * Setup an xmltextReader to parse an XML in-memory document.
5576 * The parsing flags @options are a combination of xmlParserOption.
5577 * This reuses the existing @reader xmlTextReader.
5579 * Returns 0 in case of success and -1 in case of error
5582 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5583 const char *URL, const char *encoding, int options)
5585 xmlParserInputBufferPtr input;
5587 if (reader == NULL)
5588 return (-1);
5589 if (buffer == NULL)
5590 return (-1);
5592 input = xmlParserInputBufferCreateMem(buffer, size,
5593 XML_CHAR_ENCODING_NONE);
5594 if (input == NULL) {
5595 return (-1);
5597 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5601 * xmlReaderNewFd:
5602 * @reader: an XML reader
5603 * @fd: an open file descriptor
5604 * @URL: the base URL to use for the document
5605 * @encoding: the document encoding, or NULL
5606 * @options: a combination of xmlParserOption
5608 * Setup an xmltextReader to parse an XML from a file descriptor.
5609 * NOTE that the file descriptor will not be closed when the
5610 * reader is closed or reset.
5611 * The parsing flags @options are a combination of xmlParserOption.
5612 * This reuses the existing @reader xmlTextReader.
5614 * Returns 0 in case of success and -1 in case of error
5617 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5618 const char *URL, const char *encoding, int options)
5620 xmlParserInputBufferPtr input;
5622 if (fd < 0)
5623 return (-1);
5624 if (reader == NULL)
5625 return (-1);
5627 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5628 if (input == NULL)
5629 return (-1);
5630 input->closecallback = NULL;
5631 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5635 * xmlReaderNewIO:
5636 * @reader: an XML reader
5637 * @ioread: an I/O read function
5638 * @ioclose: an I/O close function
5639 * @ioctx: an I/O handler
5640 * @URL: the base URL to use for the document
5641 * @encoding: the document encoding, or NULL
5642 * @options: a combination of xmlParserOption
5644 * Setup an xmltextReader to parse an XML document from I/O functions
5645 * and source.
5646 * The parsing flags @options are a combination of xmlParserOption.
5647 * This reuses the existing @reader xmlTextReader.
5649 * Returns 0 in case of success and -1 in case of error
5652 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5653 xmlInputCloseCallback ioclose, void *ioctx,
5654 const char *URL, const char *encoding, int options)
5656 xmlParserInputBufferPtr input;
5658 if (ioread == NULL)
5659 return (-1);
5660 if (reader == NULL)
5661 return (-1);
5663 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5664 XML_CHAR_ENCODING_NONE);
5665 if (input == NULL) {
5666 if (ioclose != NULL)
5667 ioclose(ioctx);
5668 return (-1);
5670 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5673 /************************************************************************
5675 * Utilities *
5677 ************************************************************************/
5678 #ifdef NOT_USED_YET
5681 * xmlBase64Decode:
5682 * @in: the input buffer
5683 * @inlen: the size of the input (in), the size read from it (out)
5684 * @to: the output buffer
5685 * @tolen: the size of the output (in), the size written to (out)
5687 * Base64 decoder, reads from @in and save in @to
5688 * TODO: tell jody when this is actually exported
5690 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5691 * 2 if there wasn't enough space on the output or -1 in case of error.
5693 static int
5694 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5695 unsigned char *to, unsigned long *tolen)
5697 unsigned long incur; /* current index in in[] */
5699 unsigned long inblk; /* last block index in in[] */
5701 unsigned long outcur; /* current index in out[] */
5703 unsigned long inmax; /* size of in[] */
5705 unsigned long outmax; /* size of out[] */
5707 unsigned char cur; /* the current value read from in[] */
5709 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5711 int nbintmp; /* number of byte in intmp[] */
5713 int is_ignore; /* cur should be ignored */
5715 int is_end = 0; /* the end of the base64 was found */
5717 int retval = 1;
5719 int i;
5721 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5722 return (-1);
5724 incur = 0;
5725 inblk = 0;
5726 outcur = 0;
5727 inmax = *inlen;
5728 outmax = *tolen;
5729 nbintmp = 0;
5731 while (1) {
5732 if (incur >= inmax)
5733 break;
5734 cur = in[incur++];
5735 is_ignore = 0;
5736 if ((cur >= 'A') && (cur <= 'Z'))
5737 cur = cur - 'A';
5738 else if ((cur >= 'a') && (cur <= 'z'))
5739 cur = cur - 'a' + 26;
5740 else if ((cur >= '0') && (cur <= '9'))
5741 cur = cur - '0' + 52;
5742 else if (cur == '+')
5743 cur = 62;
5744 else if (cur == '/')
5745 cur = 63;
5746 else if (cur == '.')
5747 cur = 0;
5748 else if (cur == '=') /*no op , end of the base64 stream */
5749 is_end = 1;
5750 else {
5751 is_ignore = 1;
5752 if (nbintmp == 0)
5753 inblk = incur;
5756 if (!is_ignore) {
5757 int nbouttmp = 3;
5759 int is_break = 0;
5761 if (is_end) {
5762 if (nbintmp == 0)
5763 break;
5764 if ((nbintmp == 1) || (nbintmp == 2))
5765 nbouttmp = 1;
5766 else
5767 nbouttmp = 2;
5768 nbintmp = 3;
5769 is_break = 1;
5771 intmp[nbintmp++] = cur;
5773 * if intmp is full, push the 4byte sequence as a 3 byte
5774 * sequence out
5776 if (nbintmp == 4) {
5777 nbintmp = 0;
5778 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5779 outtmp[1] =
5780 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5781 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5782 if (outcur + 3 >= outmax) {
5783 retval = 2;
5784 break;
5787 for (i = 0; i < nbouttmp; i++)
5788 to[outcur++] = outtmp[i];
5789 inblk = incur;
5792 if (is_break) {
5793 retval = 0;
5794 break;
5799 *tolen = outcur;
5800 *inlen = inblk;
5801 return (retval);
5805 * Test routine for the xmlBase64Decode function
5807 #if 0
5809 main(int argc, char **argv)
5811 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5813 char output[100];
5815 char output2[100];
5817 char output3[100];
5819 unsigned long inlen = strlen(input);
5821 unsigned long outlen = 100;
5823 int ret;
5825 unsigned long cons, tmp, tmp2, prod;
5828 * Direct
5830 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5832 output[outlen] = 0;
5833 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5834 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5838 * output chunking
5840 cons = 0;
5841 prod = 0;
5842 while (cons < inlen) {
5843 tmp = 5;
5844 tmp2 = inlen - cons;
5846 printf("%ld %ld\n", cons, prod);
5847 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5848 cons += tmp2;
5849 prod += tmp;
5850 printf("%ld %ld\n", cons, prod);
5852 output2[outlen] = 0;
5853 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5854 prod, output2);
5857 * input chunking
5859 cons = 0;
5860 prod = 0;
5861 while (cons < inlen) {
5862 tmp = 100 - prod;
5863 tmp2 = inlen - cons;
5864 if (tmp2 > 5)
5865 tmp2 = 5;
5867 printf("%ld %ld\n", cons, prod);
5868 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5869 cons += tmp2;
5870 prod += tmp;
5871 printf("%ld %ld\n", cons, prod);
5873 output3[outlen] = 0;
5874 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5875 prod, output3);
5876 return (0);
5879 #endif
5880 #endif /* NOT_USED_YET */
5882 #endif /* LIBXML_READER_ENABLED */