dnsmasq: stay close as possible to master branch
[tomato.git] / release / src-rt-6.x.4708 / router / libxml2 / xmlreader.c
blob00083d0e433bb8c9cf658c0da5422b3ce88e2b40
1 /*
2 * xmlreader.c: implements the xmlTextReader streaming node API
4 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
8 * See Copyright for the status of this software.
10 * daniel@veillard.com
14 * TODOs:
15 * - XML Schemas validation
17 #define IN_LIBXML
18 #include "libxml.h"
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
24 #ifdef HAVE_CTYPE_H
25 #include <ctype.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
31 #include <libxml/xmlmemory.h>
32 #include <libxml/xmlIO.h>
33 #include <libxml/xmlreader.h>
34 #include <libxml/parserInternals.h>
35 #ifdef LIBXML_SCHEMAS_ENABLED
36 #include <libxml/relaxng.h>
37 #include <libxml/xmlschemas.h>
38 #endif
39 #include <libxml/uri.h>
40 #ifdef LIBXML_XINCLUDE_ENABLED
41 #include <libxml/xinclude.h>
42 #endif
43 #ifdef LIBXML_PATTERN_ENABLED
44 #include <libxml/pattern.h>
45 #endif
47 #include "buf.h"
49 #define MAX_ERR_MSG_SIZE 64000
52 * The following VA_COPY was coded following an example in
53 * the Samba project. It may not be sufficient for some
54 * esoteric implementations of va_list (i.e. it may need
55 * something involving a memcpy) but (hopefully) will be
56 * sufficient for libxml2.
58 #ifndef VA_COPY
59 #ifdef HAVE_VA_COPY
60 #define VA_COPY(dest, src) va_copy(dest, src)
61 #else
62 #ifdef HAVE___VA_COPY
63 #define VA_COPY(dest,src) __va_copy(dest, src)
64 #else
65 #define VA_COPY(dest,src) (dest) = (src)
66 #endif
67 #endif
68 #endif
70 /* #define DEBUG_CALLBACKS */
71 /* #define DEBUG_READER */
73 /**
74 * TODO:
76 * macro to flag unimplemented blocks
78 #define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
83 #ifdef DEBUG_READER
84 #define DUMP_READER xmlTextReaderDebug(reader);
85 #else
86 #define DUMP_READER
87 #endif
89 #define CHUNK_SIZE 512
90 /************************************************************************
91 * *
92 * The parser: maps the Text Reader API on top of the existing *
93 * parsing routines building a tree *
94 * *
95 ************************************************************************/
97 #define XML_TEXTREADER_INPUT 1
98 #define XML_TEXTREADER_CTXT 2
100 typedef enum {
101 XML_TEXTREADER_NONE = -1,
102 XML_TEXTREADER_START= 0,
103 XML_TEXTREADER_ELEMENT= 1,
104 XML_TEXTREADER_END= 2,
105 XML_TEXTREADER_EMPTY= 3,
106 XML_TEXTREADER_BACKTRACK= 4,
107 XML_TEXTREADER_DONE= 5,
108 XML_TEXTREADER_ERROR= 6
109 } xmlTextReaderState;
111 typedef enum {
112 XML_TEXTREADER_NOT_VALIDATE = 0,
113 XML_TEXTREADER_VALIDATE_DTD = 1,
114 XML_TEXTREADER_VALIDATE_RNG = 2,
115 XML_TEXTREADER_VALIDATE_XSD = 4
116 } xmlTextReaderValidate;
118 struct _xmlTextReader {
119 int mode; /* the parsing mode */
120 xmlDocPtr doc; /* when walking an existing doc */
121 xmlTextReaderValidate validate;/* is there any validation */
122 int allocs; /* what structure were deallocated */
123 xmlTextReaderState state;
124 xmlParserCtxtPtr ctxt; /* the parser context */
125 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
126 xmlParserInputBufferPtr input; /* the input */
127 startElementSAXFunc startElement;/* initial SAX callbacks */
128 endElementSAXFunc endElement; /* idem */
129 startElementNsSAX2Func startElementNs;/* idem */
130 endElementNsSAX2Func endElementNs; /* idem */
131 charactersSAXFunc characters;
132 cdataBlockSAXFunc cdataBlock;
133 unsigned int base; /* base of the segment in the input */
134 unsigned int cur; /* current position in the input */
135 xmlNodePtr node; /* current node */
136 xmlNodePtr curnode;/* current attribute node */
137 int depth; /* depth of the current node */
138 xmlNodePtr faketext;/* fake xmlNs chld */
139 int preserve;/* preserve the resulting document */
140 xmlBufPtr buffer; /* used to return const xmlChar * */
141 xmlDictPtr dict; /* the context dictionnary */
143 /* entity stack when traversing entities content */
144 xmlNodePtr ent; /* Current Entity Ref Node */
145 int entNr; /* Depth of the entities stack */
146 int entMax; /* Max depth of the entities stack */
147 xmlNodePtr *entTab; /* array of entities */
149 /* error handling */
150 xmlTextReaderErrorFunc errorFunc; /* callback function */
151 void *errorFuncArg; /* callback function user argument */
153 #ifdef LIBXML_SCHEMAS_ENABLED
154 /* Handling of RelaxNG validation */
155 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
156 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
157 int rngPreserveCtxt; /* 1 if the context was provided by the user */
158 int rngValidErrors;/* The number of errors detected */
159 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
160 /* Handling of Schemas validation */
161 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
162 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
163 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
164 int xsdValidErrors;/* The number of errors detected */
165 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
166 #endif
167 #ifdef LIBXML_XINCLUDE_ENABLED
168 /* Handling of XInclude processing */
169 int xinclude; /* is xinclude asked for */
170 const xmlChar * xinclude_name; /* the xinclude name from dict */
171 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
172 int in_xinclude; /* counts for xinclude */
173 #endif
174 #ifdef LIBXML_PATTERN_ENABLED
175 int patternNr; /* number of preserve patterns */
176 int patternMax; /* max preserve patterns */
177 xmlPatternPtr *patternTab; /* array of preserve patterns */
178 #endif
179 int preserves; /* level of preserves */
180 int parserFlags; /* the set of options set */
181 /* Structured error handling */
182 xmlStructuredErrorFunc sErrorFunc; /* callback function */
185 #define NODE_IS_EMPTY 0x1
186 #define NODE_IS_PRESERVED 0x2
187 #define NODE_IS_SPRESERVED 0x4
190 * CONSTSTR:
192 * Macro used to return an interned string
194 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
195 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
197 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
198 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
200 /************************************************************************
202 * Our own version of the freeing routines as we recycle nodes *
204 ************************************************************************/
206 * DICT_FREE:
207 * @str: a string
209 * Free a string if it is not owned by the "dict" dictionnary in the
210 * current scope
212 #define DICT_FREE(str) \
213 if ((str) && ((!dict) || \
214 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
215 xmlFree((char *)(str));
217 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
218 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
221 * xmlFreeID:
222 * @not: A id
224 * Deallocate the memory used by an id definition
226 static void
227 xmlFreeID(xmlIDPtr id) {
228 xmlDictPtr dict = NULL;
230 if (id == NULL) return;
232 if (id->doc != NULL)
233 dict = id->doc->dict;
235 if (id->value != NULL)
236 DICT_FREE(id->value)
237 xmlFree(id);
241 * xmlTextReaderRemoveID:
242 * @doc: the document
243 * @attr: the attribute
245 * Remove the given attribute from the ID table maintained internally.
247 * Returns -1 if the lookup failed and 0 otherwise
249 static int
250 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
251 xmlIDTablePtr table;
252 xmlIDPtr id;
253 xmlChar *ID;
255 if (doc == NULL) return(-1);
256 if (attr == NULL) return(-1);
257 table = (xmlIDTablePtr) doc->ids;
258 if (table == NULL)
259 return(-1);
261 ID = xmlNodeListGetString(doc, attr->children, 1);
262 if (ID == NULL)
263 return(-1);
264 id = xmlHashLookup(table, ID);
265 xmlFree(ID);
266 if (id == NULL || id->attr != attr) {
267 return(-1);
269 id->name = attr->name;
270 id->attr = NULL;
271 return(0);
275 * xmlTextReaderFreeProp:
276 * @reader: the xmlTextReaderPtr used
277 * @cur: the node
279 * Free a node.
281 static void
282 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
283 xmlDictPtr dict;
285 dict = reader->ctxt->dict;
286 if (cur == NULL) return;
288 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
289 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
291 /* Check for ID removal -> leading to invalid references ! */
292 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
293 ((cur->parent->doc->intSubset != NULL) ||
294 (cur->parent->doc->extSubset != NULL))) {
295 if (xmlIsID(cur->parent->doc, cur->parent, cur))
296 xmlTextReaderRemoveID(cur->parent->doc, cur);
298 if (cur->children != NULL)
299 xmlTextReaderFreeNodeList(reader, cur->children);
301 DICT_FREE(cur->name);
302 if ((reader != NULL) && (reader->ctxt != NULL) &&
303 (reader->ctxt->freeAttrsNr < 100)) {
304 cur->next = reader->ctxt->freeAttrs;
305 reader->ctxt->freeAttrs = cur;
306 reader->ctxt->freeAttrsNr++;
307 } else {
308 xmlFree(cur);
313 * xmlTextReaderFreePropList:
314 * @reader: the xmlTextReaderPtr used
315 * @cur: the first property in the list
317 * Free a property and all its siblings, all the children are freed too.
319 static void
320 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
321 xmlAttrPtr next;
322 if (cur == NULL) return;
323 while (cur != NULL) {
324 next = cur->next;
325 xmlTextReaderFreeProp(reader, cur);
326 cur = next;
331 * xmlTextReaderFreeNodeList:
332 * @reader: the xmlTextReaderPtr used
333 * @cur: the first node in the list
335 * Free a node and all its siblings, this is a recursive behaviour, all
336 * the children are freed too.
338 static void
339 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
340 xmlNodePtr next;
341 xmlDictPtr dict;
343 dict = reader->ctxt->dict;
344 if (cur == NULL) return;
345 if (cur->type == XML_NAMESPACE_DECL) {
346 xmlFreeNsList((xmlNsPtr) cur);
347 return;
349 if ((cur->type == XML_DOCUMENT_NODE) ||
350 (cur->type == XML_HTML_DOCUMENT_NODE)) {
351 xmlFreeDoc((xmlDocPtr) cur);
352 return;
354 while (cur != NULL) {
355 next = cur->next;
356 /* unroll to speed up freeing the document */
357 if (cur->type != XML_DTD_NODE) {
359 if ((cur->children != NULL) &&
360 (cur->type != XML_ENTITY_REF_NODE)) {
361 if (cur->children->parent == cur)
362 xmlTextReaderFreeNodeList(reader, cur->children);
363 cur->children = NULL;
366 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
367 xmlDeregisterNodeDefaultValue(cur);
369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_XINCLUDE_START) ||
371 (cur->type == XML_XINCLUDE_END)) &&
372 (cur->properties != NULL))
373 xmlTextReaderFreePropList(reader, cur->properties);
374 if ((cur->content != (xmlChar *) &(cur->properties)) &&
375 (cur->type != XML_ELEMENT_NODE) &&
376 (cur->type != XML_XINCLUDE_START) &&
377 (cur->type != XML_XINCLUDE_END) &&
378 (cur->type != XML_ENTITY_REF_NODE)) {
379 DICT_FREE(cur->content);
381 if (((cur->type == XML_ELEMENT_NODE) ||
382 (cur->type == XML_XINCLUDE_START) ||
383 (cur->type == XML_XINCLUDE_END)) &&
384 (cur->nsDef != NULL))
385 xmlFreeNsList(cur->nsDef);
388 * we don't free element names here they are interned now
390 if ((cur->type != XML_TEXT_NODE) &&
391 (cur->type != XML_COMMENT_NODE))
392 DICT_FREE(cur->name);
393 if (((cur->type == XML_ELEMENT_NODE) ||
394 (cur->type == XML_TEXT_NODE)) &&
395 (reader != NULL) && (reader->ctxt != NULL) &&
396 (reader->ctxt->freeElemsNr < 100)) {
397 cur->next = reader->ctxt->freeElems;
398 reader->ctxt->freeElems = cur;
399 reader->ctxt->freeElemsNr++;
400 } else {
401 xmlFree(cur);
404 cur = next;
409 * xmlTextReaderFreeNode:
410 * @reader: the xmlTextReaderPtr used
411 * @cur: the node
413 * Free a node, this is a recursive behaviour, all the children are freed too.
414 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
416 static void
417 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
418 xmlDictPtr dict;
420 dict = reader->ctxt->dict;
421 if (cur->type == XML_DTD_NODE) {
422 xmlFreeDtd((xmlDtdPtr) cur);
423 return;
425 if (cur->type == XML_NAMESPACE_DECL) {
426 xmlFreeNs((xmlNsPtr) cur);
427 return;
429 if (cur->type == XML_ATTRIBUTE_NODE) {
430 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
431 return;
434 if ((cur->children != NULL) &&
435 (cur->type != XML_ENTITY_REF_NODE)) {
436 if (cur->children->parent == cur)
437 xmlTextReaderFreeNodeList(reader, cur->children);
438 cur->children = NULL;
441 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
442 xmlDeregisterNodeDefaultValue(cur);
444 if (((cur->type == XML_ELEMENT_NODE) ||
445 (cur->type == XML_XINCLUDE_START) ||
446 (cur->type == XML_XINCLUDE_END)) &&
447 (cur->properties != NULL))
448 xmlTextReaderFreePropList(reader, cur->properties);
449 if ((cur->content != (xmlChar *) &(cur->properties)) &&
450 (cur->type != XML_ELEMENT_NODE) &&
451 (cur->type != XML_XINCLUDE_START) &&
452 (cur->type != XML_XINCLUDE_END) &&
453 (cur->type != XML_ENTITY_REF_NODE)) {
454 DICT_FREE(cur->content);
456 if (((cur->type == XML_ELEMENT_NODE) ||
457 (cur->type == XML_XINCLUDE_START) ||
458 (cur->type == XML_XINCLUDE_END)) &&
459 (cur->nsDef != NULL))
460 xmlFreeNsList(cur->nsDef);
463 * we don't free names here they are interned now
465 if ((cur->type != XML_TEXT_NODE) &&
466 (cur->type != XML_COMMENT_NODE))
467 DICT_FREE(cur->name);
469 if (((cur->type == XML_ELEMENT_NODE) ||
470 (cur->type == XML_TEXT_NODE)) &&
471 (reader != NULL) && (reader->ctxt != NULL) &&
472 (reader->ctxt->freeElemsNr < 100)) {
473 cur->next = reader->ctxt->freeElems;
474 reader->ctxt->freeElems = cur;
475 reader->ctxt->freeElemsNr++;
476 } else {
477 xmlFree(cur);
482 * xmlTextReaderFreeIDTable:
483 * @table: An id table
485 * Deallocate the memory used by an ID hash table.
487 static void
488 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
489 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
493 * xmlTextReaderFreeDoc:
494 * @reader: the xmlTextReaderPtr used
495 * @cur: pointer to the document
497 * Free up all the structures used by a document, tree included.
499 static void
500 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
501 xmlDtdPtr extSubset, intSubset;
503 if (cur == NULL) return;
505 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
506 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
509 * Do this before freeing the children list to avoid ID lookups
511 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
512 cur->ids = NULL;
513 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
514 cur->refs = NULL;
515 extSubset = cur->extSubset;
516 intSubset = cur->intSubset;
517 if (intSubset == extSubset)
518 extSubset = NULL;
519 if (extSubset != NULL) {
520 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
521 cur->extSubset = NULL;
522 xmlFreeDtd(extSubset);
524 if (intSubset != NULL) {
525 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
526 cur->intSubset = NULL;
527 xmlFreeDtd(intSubset);
530 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
532 if (cur->version != NULL) xmlFree((char *) cur->version);
533 if (cur->name != NULL) xmlFree((char *) cur->name);
534 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
535 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
536 if (cur->URL != NULL) xmlFree((char *) cur->URL);
537 if (cur->dict != NULL) xmlDictFree(cur->dict);
539 xmlFree(cur);
542 /************************************************************************
544 * The reader core parser *
546 ************************************************************************/
547 #ifdef DEBUG_READER
548 static void
549 xmlTextReaderDebug(xmlTextReaderPtr reader) {
550 if ((reader == NULL) || (reader->ctxt == NULL)) {
551 fprintf(stderr, "xmlTextReader NULL\n");
552 return;
554 fprintf(stderr, "xmlTextReader: state %d depth %d ",
555 reader->state, reader->depth);
556 if (reader->node == NULL) {
557 fprintf(stderr, "node = NULL\n");
558 } else {
559 fprintf(stderr, "node %s\n", reader->node->name);
561 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
562 reader->base, reader->cur, reader->ctxt->nodeNr);
563 if (reader->input->buffer == NULL) {
564 fprintf(stderr, "buffer is NULL\n");
565 } else {
566 #ifdef LIBXML_DEBUG_ENABLED
567 xmlDebugDumpString(stderr,
568 &reader->input->buffer->content[reader->cur]);
569 #endif
570 fprintf(stderr, "\n");
573 #endif
576 * xmlTextReaderEntPush:
577 * @reader: the xmlTextReaderPtr used
578 * @value: the entity reference node
580 * Pushes a new entity reference node on top of the entities stack
582 * Returns 0 in case of error, the index in the stack otherwise
584 static int
585 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
587 if (reader->entMax <= 0) {
588 reader->entMax = 10;
589 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
590 sizeof(reader->entTab[0]));
591 if (reader->entTab == NULL) {
592 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
593 return (0);
596 if (reader->entNr >= reader->entMax) {
597 reader->entMax *= 2;
598 reader->entTab =
599 (xmlNodePtr *) xmlRealloc(reader->entTab,
600 reader->entMax *
601 sizeof(reader->entTab[0]));
602 if (reader->entTab == NULL) {
603 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
604 return (0);
607 reader->entTab[reader->entNr] = value;
608 reader->ent = value;
609 return (reader->entNr++);
613 * xmlTextReaderEntPop:
614 * @reader: the xmlTextReaderPtr used
616 * Pops the top element entity from the entities stack
618 * Returns the entity just removed
620 static xmlNodePtr
621 xmlTextReaderEntPop(xmlTextReaderPtr reader)
623 xmlNodePtr ret;
625 if (reader->entNr <= 0)
626 return (NULL);
627 reader->entNr--;
628 if (reader->entNr > 0)
629 reader->ent = reader->entTab[reader->entNr - 1];
630 else
631 reader->ent = NULL;
632 ret = reader->entTab[reader->entNr];
633 reader->entTab[reader->entNr] = NULL;
634 return (ret);
638 * xmlTextReaderStartElement:
639 * @ctx: the user data (XML parser context)
640 * @fullname: The element name, including namespace prefix
641 * @atts: An array of name/value attributes pairs, NULL terminated
643 * called when an opening tag has been processed.
645 static void
646 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
647 const xmlChar **atts) {
648 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
649 xmlTextReaderPtr reader = ctxt->_private;
651 #ifdef DEBUG_CALLBACKS
652 printf("xmlTextReaderStartElement(%s)\n", fullname);
653 #endif
654 if ((reader != NULL) && (reader->startElement != NULL)) {
655 reader->startElement(ctx, fullname, atts);
656 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
657 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
658 (ctxt->input->cur[1] == '>'))
659 ctxt->node->extra = NODE_IS_EMPTY;
661 if (reader != NULL)
662 reader->state = XML_TEXTREADER_ELEMENT;
666 * xmlTextReaderEndElement:
667 * @ctx: the user data (XML parser context)
668 * @fullname: The element name, including namespace prefix
670 * called when an ending tag has been processed.
672 static void
673 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
674 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
675 xmlTextReaderPtr reader = ctxt->_private;
677 #ifdef DEBUG_CALLBACKS
678 printf("xmlTextReaderEndElement(%s)\n", fullname);
679 #endif
680 if ((reader != NULL) && (reader->endElement != NULL)) {
681 reader->endElement(ctx, fullname);
686 * xmlTextReaderStartElementNs:
687 * @ctx: the user data (XML parser context)
688 * @localname: the local name of the element
689 * @prefix: the element namespace prefix if available
690 * @URI: the element namespace name if available
691 * @nb_namespaces: number of namespace definitions on that node
692 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
693 * @nb_attributes: the number of attributes on that node
694 * nb_defaulted: the number of defaulted attributes.
695 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
696 * attribute values.
698 * called when an opening tag has been processed.
700 static void
701 xmlTextReaderStartElementNs(void *ctx,
702 const xmlChar *localname,
703 const xmlChar *prefix,
704 const xmlChar *URI,
705 int nb_namespaces,
706 const xmlChar **namespaces,
707 int nb_attributes,
708 int nb_defaulted,
709 const xmlChar **attributes)
711 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
712 xmlTextReaderPtr reader = ctxt->_private;
714 #ifdef DEBUG_CALLBACKS
715 printf("xmlTextReaderStartElementNs(%s)\n", localname);
716 #endif
717 if ((reader != NULL) && (reader->startElementNs != NULL)) {
718 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
719 namespaces, nb_attributes, nb_defaulted,
720 attributes);
721 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
722 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
723 (ctxt->input->cur[1] == '>'))
724 ctxt->node->extra = NODE_IS_EMPTY;
726 if (reader != NULL)
727 reader->state = XML_TEXTREADER_ELEMENT;
731 * xmlTextReaderEndElementNs:
732 * @ctx: the user data (XML parser context)
733 * @localname: the local name of the element
734 * @prefix: the element namespace prefix if available
735 * @URI: the element namespace name if available
737 * called when an ending tag has been processed.
739 static void
740 xmlTextReaderEndElementNs(void *ctx,
741 const xmlChar * localname,
742 const xmlChar * prefix,
743 const xmlChar * URI)
745 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
746 xmlTextReaderPtr reader = ctxt->_private;
748 #ifdef DEBUG_CALLBACKS
749 printf("xmlTextReaderEndElementNs(%s)\n", localname);
750 #endif
751 if ((reader != NULL) && (reader->endElementNs != NULL)) {
752 reader->endElementNs(ctx, localname, prefix, URI);
758 * xmlTextReaderCharacters:
759 * @ctx: the user data (XML parser context)
760 * @ch: a xmlChar string
761 * @len: the number of xmlChar
763 * receiving some chars from the parser.
765 static void
766 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
768 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
769 xmlTextReaderPtr reader = ctxt->_private;
771 #ifdef DEBUG_CALLBACKS
772 printf("xmlTextReaderCharacters()\n");
773 #endif
774 if ((reader != NULL) && (reader->characters != NULL)) {
775 reader->characters(ctx, ch, len);
780 * xmlTextReaderCDataBlock:
781 * @ctx: the user data (XML parser context)
782 * @value: The pcdata content
783 * @len: the block length
785 * called when a pcdata block has been parsed
787 static void
788 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
790 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
791 xmlTextReaderPtr reader = ctxt->_private;
793 #ifdef DEBUG_CALLBACKS
794 printf("xmlTextReaderCDataBlock()\n");
795 #endif
796 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
797 reader->cdataBlock(ctx, ch, len);
802 * xmlTextReaderPushData:
803 * @reader: the xmlTextReaderPtr used
805 * Push data down the progressive parser until a significant callback
806 * got raised.
808 * Returns -1 in case of failure, 0 otherwise
810 static int
811 xmlTextReaderPushData(xmlTextReaderPtr reader) {
812 xmlBufPtr inbuf;
813 int val, s;
814 xmlTextReaderState oldstate;
815 int alloc;
817 if ((reader->input == NULL) || (reader->input->buffer == NULL))
818 return(-1);
820 oldstate = reader->state;
821 reader->state = XML_TEXTREADER_NONE;
822 inbuf = reader->input->buffer;
823 alloc = xmlBufGetAllocationScheme(inbuf);
825 while (reader->state == XML_TEXTREADER_NONE) {
826 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
828 * Refill the buffer unless we are at the end of the stream
830 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
831 val = xmlParserInputBufferRead(reader->input, 4096);
832 if ((val == 0) &&
833 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
834 if (xmlBufUse(inbuf) == reader->cur) {
835 reader->mode = XML_TEXTREADER_MODE_EOF;
836 reader->state = oldstate;
838 } else if (val < 0) {
839 reader->mode = XML_TEXTREADER_MODE_EOF;
840 reader->state = oldstate;
841 if ((oldstate != XML_TEXTREADER_START) ||
842 (reader->ctxt->myDoc != NULL))
843 return(val);
844 } else if (val == 0) {
845 /* mark the end of the stream and process the remains */
846 reader->mode = XML_TEXTREADER_MODE_EOF;
847 break;
850 } else
851 break;
854 * parse by block of CHUNK_SIZE bytes, various tests show that
855 * it's the best tradeoff at least on a 1.2GH Duron
857 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
858 val = xmlParseChunk(reader->ctxt,
859 (const char *) xmlBufContent(inbuf) + reader->cur,
860 CHUNK_SIZE, 0);
861 reader->cur += CHUNK_SIZE;
862 if (val != 0)
863 reader->ctxt->wellFormed = 0;
864 if (reader->ctxt->wellFormed == 0)
865 break;
866 } else {
867 s = xmlBufUse(inbuf) - reader->cur;
868 val = xmlParseChunk(reader->ctxt,
869 (const char *) xmlBufContent(inbuf) + reader->cur,
870 s, 0);
871 reader->cur += s;
872 if (val != 0)
873 reader->ctxt->wellFormed = 0;
874 break;
879 * Discard the consumed input when needed and possible
881 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
882 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
883 if ((reader->cur >= 4096) &&
884 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
885 val = xmlBufShrink(inbuf, reader->cur);
886 if (val >= 0) {
887 reader->cur -= val;
894 * At the end of the stream signal that the work is done to the Push
895 * parser.
897 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
898 if (reader->state != XML_TEXTREADER_DONE) {
899 s = xmlBufUse(inbuf) - reader->cur;
900 val = xmlParseChunk(reader->ctxt,
901 (const char *) xmlBufContent(inbuf) + reader->cur,
902 s, 1);
903 reader->cur = xmlBufUse(inbuf);
904 reader->state = XML_TEXTREADER_DONE;
905 if (val != 0) {
906 if (reader->ctxt->wellFormed)
907 reader->ctxt->wellFormed = 0;
908 else
909 return(-1);
913 reader->state = oldstate;
914 if (reader->ctxt->wellFormed == 0) {
915 reader->mode = XML_TEXTREADER_MODE_EOF;
916 return(-1);
919 return(0);
922 #ifdef LIBXML_REGEXP_ENABLED
924 * xmlTextReaderValidatePush:
925 * @reader: the xmlTextReaderPtr used
927 * Push the current node for validation
929 static void
930 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
931 xmlNodePtr node = reader->node;
933 #ifdef LIBXML_VALID_ENABLED
934 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
935 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
936 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
937 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
938 reader->ctxt->myDoc, node, node->name);
939 } else {
940 /* TODO use the BuildQName interface */
941 xmlChar *qname;
943 qname = xmlStrdup(node->ns->prefix);
944 qname = xmlStrcat(qname, BAD_CAST ":");
945 qname = xmlStrcat(qname, node->name);
946 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
947 reader->ctxt->myDoc, node, qname);
948 if (qname != NULL)
949 xmlFree(qname);
952 #endif /* LIBXML_VALID_ENABLED */
953 #ifdef LIBXML_SCHEMAS_ENABLED
954 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
955 (reader->rngValidCtxt != NULL)) {
956 int ret;
958 if (reader->rngFullNode != NULL) return;
959 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
960 reader->ctxt->myDoc,
961 node);
962 if (ret == 0) {
964 * this element requires a full tree
966 node = xmlTextReaderExpand(reader);
967 if (node == NULL) {
968 printf("Expand failed !\n");
969 ret = -1;
970 } else {
971 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
972 reader->ctxt->myDoc,
973 node);
974 reader->rngFullNode = node;
977 if (ret != 1)
978 reader->rngValidErrors++;
980 #endif
984 * xmlTextReaderValidateCData:
985 * @reader: the xmlTextReaderPtr used
986 * @data: pointer to the CData
987 * @len: length of the CData block in bytes.
989 * Push some CData for validation
991 static void
992 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
993 const xmlChar *data, int len) {
994 #ifdef LIBXML_VALID_ENABLED
995 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
996 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
997 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
998 data, len);
1000 #endif /* LIBXML_VALID_ENABLED */
1001 #ifdef LIBXML_SCHEMAS_ENABLED
1002 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1003 (reader->rngValidCtxt != NULL)) {
1004 int ret;
1006 if (reader->rngFullNode != NULL) return;
1007 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1008 if (ret != 1)
1009 reader->rngValidErrors++;
1011 #endif
1015 * xmlTextReaderValidatePop:
1016 * @reader: the xmlTextReaderPtr used
1018 * Pop the current node from validation
1020 static void
1021 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1022 xmlNodePtr node = reader->node;
1024 #ifdef LIBXML_VALID_ENABLED
1025 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1026 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1027 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1028 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1029 reader->ctxt->myDoc, node, node->name);
1030 } else {
1031 /* TODO use the BuildQName interface */
1032 xmlChar *qname;
1034 qname = xmlStrdup(node->ns->prefix);
1035 qname = xmlStrcat(qname, BAD_CAST ":");
1036 qname = xmlStrcat(qname, node->name);
1037 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1038 reader->ctxt->myDoc, node, qname);
1039 if (qname != NULL)
1040 xmlFree(qname);
1043 #endif /* LIBXML_VALID_ENABLED */
1044 #ifdef LIBXML_SCHEMAS_ENABLED
1045 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1046 (reader->rngValidCtxt != NULL)) {
1047 int ret;
1049 if (reader->rngFullNode != NULL) {
1050 if (node == reader->rngFullNode)
1051 reader->rngFullNode = NULL;
1052 return;
1054 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1055 reader->ctxt->myDoc,
1056 node);
1057 if (ret != 1)
1058 reader->rngValidErrors++;
1060 #endif
1064 * xmlTextReaderValidateEntity:
1065 * @reader: the xmlTextReaderPtr used
1067 * Handle the validation when an entity reference is encountered and
1068 * entity substitution is not activated. As a result the parser interface
1069 * must walk through the entity and do the validation calls
1071 static void
1072 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1073 xmlNodePtr oldnode = reader->node;
1074 xmlNodePtr node = reader->node;
1075 xmlParserCtxtPtr ctxt = reader->ctxt;
1077 do {
1078 if (node->type == XML_ENTITY_REF_NODE) {
1080 * Case where the underlying tree is not availble, lookup the entity
1081 * and walk it.
1083 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1084 (ctxt->sax->getEntity != NULL)) {
1085 node->children = (xmlNodePtr)
1086 ctxt->sax->getEntity(ctxt, node->name);
1089 if ((node->children != NULL) &&
1090 (node->children->type == XML_ENTITY_DECL) &&
1091 (node->children->children != NULL)) {
1092 xmlTextReaderEntPush(reader, node);
1093 node = node->children->children;
1094 continue;
1095 } else {
1097 * The error has probably be raised already.
1099 if (node == oldnode)
1100 break;
1101 node = node->next;
1103 #ifdef LIBXML_REGEXP_ENABLED
1104 } else if (node->type == XML_ELEMENT_NODE) {
1105 reader->node = node;
1106 xmlTextReaderValidatePush(reader);
1107 } else if ((node->type == XML_TEXT_NODE) ||
1108 (node->type == XML_CDATA_SECTION_NODE)) {
1109 xmlTextReaderValidateCData(reader, node->content,
1110 xmlStrlen(node->content));
1111 #endif
1115 * go to next node
1117 if (node->children != NULL) {
1118 node = node->children;
1119 continue;
1120 } else if (node->type == XML_ELEMENT_NODE) {
1121 xmlTextReaderValidatePop(reader);
1123 if (node->next != NULL) {
1124 node = node->next;
1125 continue;
1127 do {
1128 node = node->parent;
1129 if (node->type == XML_ELEMENT_NODE) {
1130 xmlNodePtr tmp;
1131 if (reader->entNr == 0) {
1132 while ((tmp = node->last) != NULL) {
1133 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1134 xmlUnlinkNode(tmp);
1135 xmlTextReaderFreeNode(reader, tmp);
1136 } else
1137 break;
1140 reader->node = node;
1141 xmlTextReaderValidatePop(reader);
1143 if ((node->type == XML_ENTITY_DECL) &&
1144 (reader->ent != NULL) && (reader->ent->children == node)) {
1145 node = xmlTextReaderEntPop(reader);
1147 if (node == oldnode)
1148 break;
1149 if (node->next != NULL) {
1150 node = node->next;
1151 break;
1153 } while ((node != NULL) && (node != oldnode));
1154 } while ((node != NULL) && (node != oldnode));
1155 reader->node = oldnode;
1157 #endif /* LIBXML_REGEXP_ENABLED */
1161 * xmlTextReaderGetSuccessor:
1162 * @cur: the current node
1164 * Get the successor of a node if available.
1166 * Returns the successor node or NULL
1168 static xmlNodePtr
1169 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1170 if (cur == NULL) return(NULL) ; /* ERROR */
1171 if (cur->next != NULL) return(cur->next) ;
1172 do {
1173 cur = cur->parent;
1174 if (cur == NULL) break;
1175 if (cur->next != NULL) return(cur->next);
1176 } while (cur != NULL);
1177 return(cur);
1181 * xmlTextReaderDoExpand:
1182 * @reader: the xmlTextReaderPtr used
1184 * Makes sure that the current node is fully read as well as all its
1185 * descendant. It means the full DOM subtree must be available at the
1186 * end of the call.
1188 * Returns 1 if the node was expanded successfully, 0 if there is no more
1189 * nodes to read, or -1 in case of error
1191 static int
1192 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1193 int val;
1195 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1196 return(-1);
1197 do {
1198 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1200 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1201 return(1);
1202 if (reader->ctxt->nodeNr < reader->depth)
1203 return(1);
1204 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1205 return(1);
1206 val = xmlTextReaderPushData(reader);
1207 if (val < 0){
1208 reader->mode = XML_TEXTREADER_MODE_ERROR;
1209 return(-1);
1211 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1212 return(1);
1216 * xmlTextReaderCollectSiblings:
1217 * @node: the first child
1219 * Traverse depth-first through all sibling nodes and their children
1220 * nodes and concatenate their content. This is an auxiliary function
1221 * to xmlTextReaderReadString.
1223 * Returns a string containing the content, or NULL in case of error.
1225 static xmlChar *
1226 xmlTextReaderCollectSiblings(xmlNodePtr node)
1228 xmlBufferPtr buffer;
1229 xmlChar *ret;
1231 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1232 return(NULL);
1234 buffer = xmlBufferCreate();
1235 if (buffer == NULL)
1236 return NULL;
1238 for ( ; node != NULL; node = node->next) {
1239 switch (node->type) {
1240 case XML_TEXT_NODE:
1241 case XML_CDATA_SECTION_NODE:
1242 xmlBufferCat(buffer, node->content);
1243 break;
1244 case XML_ELEMENT_NODE: {
1245 xmlChar *tmp;
1247 tmp = xmlTextReaderCollectSiblings(node->children);
1248 xmlBufferCat(buffer, tmp);
1249 xmlFree(tmp);
1250 break;
1252 default:
1253 break;
1256 ret = buffer->content;
1257 buffer->content = NULL;
1258 xmlBufferFree(buffer);
1259 return(ret);
1263 * xmlTextReaderRead:
1264 * @reader: the xmlTextReaderPtr used
1266 * Moves the position of the current instance to the next node in
1267 * the stream, exposing its properties.
1269 * Returns 1 if the node was read successfully, 0 if there is no more
1270 * nodes to read, or -1 in case of error
1273 xmlTextReaderRead(xmlTextReaderPtr reader) {
1274 int val, olddepth = 0;
1275 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1276 xmlNodePtr oldnode = NULL;
1279 if (reader == NULL)
1280 return(-1);
1281 reader->curnode = NULL;
1282 if (reader->doc != NULL)
1283 return(xmlTextReaderReadTree(reader));
1284 if (reader->ctxt == NULL)
1285 return(-1);
1287 #ifdef DEBUG_READER
1288 fprintf(stderr, "\nREAD ");
1289 DUMP_READER
1290 #endif
1291 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1292 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1294 * Initial state
1296 do {
1297 val = xmlTextReaderPushData(reader);
1298 if (val < 0){
1299 reader->mode = XML_TEXTREADER_MODE_ERROR;
1300 reader->state = XML_TEXTREADER_ERROR;
1301 return(-1);
1303 } while ((reader->ctxt->node == NULL) &&
1304 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1305 (reader->state != XML_TEXTREADER_DONE)));
1306 if (reader->ctxt->node == NULL) {
1307 if (reader->ctxt->myDoc != NULL) {
1308 reader->node = reader->ctxt->myDoc->children;
1310 if (reader->node == NULL){
1311 reader->mode = XML_TEXTREADER_MODE_ERROR;
1312 reader->state = XML_TEXTREADER_ERROR;
1313 return(-1);
1315 reader->state = XML_TEXTREADER_ELEMENT;
1316 } else {
1317 if (reader->ctxt->myDoc != NULL) {
1318 reader->node = reader->ctxt->myDoc->children;
1320 if (reader->node == NULL)
1321 reader->node = reader->ctxt->nodeTab[0];
1322 reader->state = XML_TEXTREADER_ELEMENT;
1324 reader->depth = 0;
1325 reader->ctxt->parseMode = XML_PARSE_READER;
1326 goto node_found;
1328 oldstate = reader->state;
1329 olddepth = reader->ctxt->nodeNr;
1330 oldnode = reader->node;
1332 get_next_node:
1333 if (reader->node == NULL) {
1334 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1335 return(0);
1336 else
1337 return(-1);
1341 * If we are not backtracking on ancestors or examined nodes,
1342 * that the parser didn't finished or that we arent at the end
1343 * of stream, continue processing.
1345 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1346 (reader->ctxt->nodeNr == olddepth) &&
1347 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1348 (reader->node->children == NULL) ||
1349 (reader->node->type == XML_ENTITY_REF_NODE) ||
1350 ((reader->node->children != NULL) &&
1351 (reader->node->children->type == XML_TEXT_NODE) &&
1352 (reader->node->children->next == NULL)) ||
1353 (reader->node->type == XML_DTD_NODE) ||
1354 (reader->node->type == XML_DOCUMENT_NODE) ||
1355 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1356 ((reader->ctxt->node == NULL) ||
1357 (reader->ctxt->node == reader->node) ||
1358 (reader->ctxt->node == reader->node->parent)) &&
1359 (reader->ctxt->instate != XML_PARSER_EOF)) {
1360 val = xmlTextReaderPushData(reader);
1361 if (val < 0){
1362 reader->mode = XML_TEXTREADER_MODE_ERROR;
1363 reader->state = XML_TEXTREADER_ERROR;
1364 return(-1);
1366 if (reader->node == NULL)
1367 goto node_end;
1369 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1370 if ((reader->node->children != NULL) &&
1371 (reader->node->type != XML_ENTITY_REF_NODE) &&
1372 (reader->node->type != XML_XINCLUDE_START) &&
1373 (reader->node->type != XML_DTD_NODE)) {
1374 reader->node = reader->node->children;
1375 reader->depth++;
1376 reader->state = XML_TEXTREADER_ELEMENT;
1377 goto node_found;
1380 if (reader->node->next != NULL) {
1381 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1382 (reader->node->type == XML_ELEMENT_NODE) &&
1383 (reader->node->children == NULL) &&
1384 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1385 #ifdef LIBXML_XINCLUDE_ENABLED
1386 && (reader->in_xinclude <= 0)
1387 #endif
1389 reader->state = XML_TEXTREADER_END;
1390 goto node_found;
1392 #ifdef LIBXML_REGEXP_ENABLED
1393 if ((reader->validate) &&
1394 (reader->node->type == XML_ELEMENT_NODE))
1395 xmlTextReaderValidatePop(reader);
1396 #endif /* LIBXML_REGEXP_ENABLED */
1397 if ((reader->preserves > 0) &&
1398 (reader->node->extra & NODE_IS_SPRESERVED))
1399 reader->preserves--;
1400 reader->node = reader->node->next;
1401 reader->state = XML_TEXTREADER_ELEMENT;
1404 * Cleanup of the old node
1406 if ((reader->preserves == 0) &&
1407 #ifdef LIBXML_XINCLUDE_ENABLED
1408 (reader->in_xinclude == 0) &&
1409 #endif
1410 (reader->entNr == 0) &&
1411 (reader->node->prev != NULL) &&
1412 (reader->node->prev->type != XML_DTD_NODE)) {
1413 xmlNodePtr tmp = reader->node->prev;
1414 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1415 xmlUnlinkNode(tmp);
1416 xmlTextReaderFreeNode(reader, tmp);
1420 goto node_found;
1422 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1423 (reader->node->type == XML_ELEMENT_NODE) &&
1424 (reader->node->children == NULL) &&
1425 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1426 reader->state = XML_TEXTREADER_END;
1427 goto node_found;
1429 #ifdef LIBXML_REGEXP_ENABLED
1430 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
1431 xmlTextReaderValidatePop(reader);
1432 #endif /* LIBXML_REGEXP_ENABLED */
1433 if ((reader->preserves > 0) &&
1434 (reader->node->extra & NODE_IS_SPRESERVED))
1435 reader->preserves--;
1436 reader->node = reader->node->parent;
1437 if ((reader->node == NULL) ||
1438 (reader->node->type == XML_DOCUMENT_NODE) ||
1439 #ifdef LIBXML_DOCB_ENABLED
1440 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1441 #endif
1442 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1443 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1444 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1445 reader->state = XML_TEXTREADER_DONE;
1446 if (val != 0)
1447 return(-1);
1449 reader->node = NULL;
1450 reader->depth = -1;
1453 * Cleanup of the old node
1455 if ((oldnode != NULL) && (reader->preserves == 0) &&
1456 #ifdef LIBXML_XINCLUDE_ENABLED
1457 (reader->in_xinclude == 0) &&
1458 #endif
1459 (reader->entNr == 0) &&
1460 (oldnode->type != XML_DTD_NODE) &&
1461 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1462 xmlUnlinkNode(oldnode);
1463 xmlTextReaderFreeNode(reader, oldnode);
1466 goto node_end;
1468 if ((reader->preserves == 0) &&
1469 #ifdef LIBXML_XINCLUDE_ENABLED
1470 (reader->in_xinclude == 0) &&
1471 #endif
1472 (reader->entNr == 0) &&
1473 (reader->node->last != NULL) &&
1474 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1475 xmlNodePtr tmp = reader->node->last;
1476 xmlUnlinkNode(tmp);
1477 xmlTextReaderFreeNode(reader, tmp);
1479 reader->depth--;
1480 reader->state = XML_TEXTREADER_BACKTRACK;
1482 node_found:
1483 DUMP_READER
1486 * If we are in the middle of a piece of CDATA make sure it's finished
1488 if ((reader->node != NULL) &&
1489 (reader->node->next == NULL) &&
1490 ((reader->node->type == XML_TEXT_NODE) ||
1491 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1492 if (xmlTextReaderExpand(reader) == NULL)
1493 return -1;
1496 #ifdef LIBXML_XINCLUDE_ENABLED
1498 * Handle XInclude if asked for
1500 if ((reader->xinclude) && (reader->node != NULL) &&
1501 (reader->node->type == XML_ELEMENT_NODE) &&
1502 (reader->node->ns != NULL) &&
1503 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1504 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1505 if (reader->xincctxt == NULL) {
1506 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1507 xmlXIncludeSetFlags(reader->xincctxt,
1508 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1511 * expand that node and process it
1513 if (xmlTextReaderExpand(reader) == NULL)
1514 return -1;
1515 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1517 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1518 reader->in_xinclude++;
1519 goto get_next_node;
1521 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1522 reader->in_xinclude--;
1523 goto get_next_node;
1525 #endif
1527 * Handle entities enter and exit when in entity replacement mode
1529 if ((reader->node != NULL) &&
1530 (reader->node->type == XML_ENTITY_REF_NODE) &&
1531 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1533 * Case where the underlying tree is not availble, lookup the entity
1534 * and walk it.
1536 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1537 (reader->ctxt->sax->getEntity != NULL)) {
1538 reader->node->children = (xmlNodePtr)
1539 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1542 if ((reader->node->children != NULL) &&
1543 (reader->node->children->type == XML_ENTITY_DECL) &&
1544 (reader->node->children->children != NULL)) {
1545 xmlTextReaderEntPush(reader, reader->node);
1546 reader->node = reader->node->children->children;
1548 #ifdef LIBXML_REGEXP_ENABLED
1549 } else if ((reader->node != NULL) &&
1550 (reader->node->type == XML_ENTITY_REF_NODE) &&
1551 (reader->ctxt != NULL) && (reader->validate)) {
1552 xmlTextReaderValidateEntity(reader);
1553 #endif /* LIBXML_REGEXP_ENABLED */
1555 if ((reader->node != NULL) &&
1556 (reader->node->type == XML_ENTITY_DECL) &&
1557 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1558 reader->node = xmlTextReaderEntPop(reader);
1559 reader->depth++;
1560 goto get_next_node;
1562 #ifdef LIBXML_REGEXP_ENABLED
1563 if ((reader->validate) && (reader->node != NULL)) {
1564 xmlNodePtr node = reader->node;
1566 if ((node->type == XML_ELEMENT_NODE) &&
1567 ((reader->state != XML_TEXTREADER_END) &&
1568 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1569 xmlTextReaderValidatePush(reader);
1570 } else if ((node->type == XML_TEXT_NODE) ||
1571 (node->type == XML_CDATA_SECTION_NODE)) {
1572 xmlTextReaderValidateCData(reader, node->content,
1573 xmlStrlen(node->content));
1576 #endif /* LIBXML_REGEXP_ENABLED */
1577 #ifdef LIBXML_PATTERN_ENABLED
1578 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1579 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1580 int i;
1581 for (i = 0;i < reader->patternNr;i++) {
1582 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1583 xmlTextReaderPreserve(reader);
1584 break;
1588 #endif /* LIBXML_PATTERN_ENABLED */
1589 #ifdef LIBXML_SCHEMAS_ENABLED
1590 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1591 (reader->xsdValidErrors == 0) &&
1592 (reader->xsdValidCtxt != NULL)) {
1593 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1595 #endif /* LIBXML_PATTERN_ENABLED */
1596 return(1);
1597 node_end:
1598 reader->state = XML_TEXTREADER_DONE;
1599 return(0);
1603 * xmlTextReaderReadState:
1604 * @reader: the xmlTextReaderPtr used
1606 * Gets the read state of the reader.
1608 * Returns the state value, or -1 in case of error
1611 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1612 if (reader == NULL)
1613 return(-1);
1614 return(reader->mode);
1618 * xmlTextReaderExpand:
1619 * @reader: the xmlTextReaderPtr used
1621 * Reads the contents of the current node and the full subtree. It then makes
1622 * the subtree available until the next xmlTextReaderRead() call
1624 * Returns a node pointer valid until the next xmlTextReaderRead() call
1625 * or NULL in case of error.
1627 xmlNodePtr
1628 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1629 if ((reader == NULL) || (reader->node == NULL))
1630 return(NULL);
1631 if (reader->doc != NULL)
1632 return(reader->node);
1633 if (reader->ctxt == NULL)
1634 return(NULL);
1635 if (xmlTextReaderDoExpand(reader) < 0)
1636 return(NULL);
1637 return(reader->node);
1641 * xmlTextReaderNext:
1642 * @reader: the xmlTextReaderPtr used
1644 * Skip to the node following the current one in document order while
1645 * avoiding the subtree if any.
1647 * Returns 1 if the node was read successfully, 0 if there is no more
1648 * nodes to read, or -1 in case of error
1651 xmlTextReaderNext(xmlTextReaderPtr reader) {
1652 int ret;
1653 xmlNodePtr cur;
1655 if (reader == NULL)
1656 return(-1);
1657 if (reader->doc != NULL)
1658 return(xmlTextReaderNextTree(reader));
1659 cur = reader->node;
1660 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1661 return(xmlTextReaderRead(reader));
1662 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1663 return(xmlTextReaderRead(reader));
1664 if (cur->extra & NODE_IS_EMPTY)
1665 return(xmlTextReaderRead(reader));
1666 do {
1667 ret = xmlTextReaderRead(reader);
1668 if (ret != 1)
1669 return(ret);
1670 } while (reader->node != cur);
1671 return(xmlTextReaderRead(reader));
1674 #ifdef LIBXML_WRITER_ENABLED
1676 * xmlTextReaderReadInnerXml:
1677 * @reader: the xmlTextReaderPtr used
1679 * Reads the contents of the current node, including child nodes and markup.
1681 * Returns a string containing the XML content, or NULL if the current node
1682 * is neither an element nor attribute, or has no child nodes. The
1683 * string must be deallocated by the caller.
1685 xmlChar *
1686 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1688 xmlChar *resbuf;
1689 xmlNodePtr node, cur_node;
1690 xmlBufferPtr buff, buff2;
1691 xmlDocPtr doc;
1693 if (xmlTextReaderExpand(reader) == NULL) {
1694 return NULL;
1696 doc = reader->doc;
1697 buff = xmlBufferCreate();
1698 for (cur_node = reader->node->children; cur_node != NULL;
1699 cur_node = cur_node->next) {
1700 node = xmlDocCopyNode(cur_node, doc, 1);
1701 buff2 = xmlBufferCreate();
1702 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1703 xmlFreeNode(node);
1704 xmlBufferFree(buff2);
1705 xmlBufferFree(buff);
1706 return NULL;
1708 xmlBufferCat(buff, buff2->content);
1709 xmlFreeNode(node);
1710 xmlBufferFree(buff2);
1712 resbuf = buff->content;
1713 buff->content = NULL;
1715 xmlBufferFree(buff);
1716 return resbuf;
1718 #endif
1720 #ifdef LIBXML_WRITER_ENABLED
1722 * xmlTextReaderReadOuterXml:
1723 * @reader: the xmlTextReaderPtr used
1725 * Reads the contents of the current node, including child nodes and markup.
1727 * Returns a string containing the node and any XML content, or NULL if the
1728 * current node cannot be serialized. The string must be deallocated
1729 * by the caller.
1731 xmlChar *
1732 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1734 xmlChar *resbuf;
1735 xmlNodePtr node;
1736 xmlBufferPtr buff;
1737 xmlDocPtr doc;
1739 node = reader->node;
1740 doc = reader->doc;
1741 if (xmlTextReaderExpand(reader) == NULL) {
1742 return NULL;
1744 if (node->type == XML_DTD_NODE) {
1745 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1746 } else {
1747 node = xmlDocCopyNode(node, doc, 1);
1749 buff = xmlBufferCreate();
1750 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1751 xmlFreeNode(node);
1752 xmlBufferFree(buff);
1753 return NULL;
1756 resbuf = buff->content;
1757 buff->content = NULL;
1759 xmlFreeNode(node);
1760 xmlBufferFree(buff);
1761 return resbuf;
1763 #endif
1766 * xmlTextReaderReadString:
1767 * @reader: the xmlTextReaderPtr used
1769 * Reads the contents of an element or a text node as a string.
1771 * Returns a string containing the contents of the Element or Text node,
1772 * or NULL if the reader is positioned on any other type of node.
1773 * The string must be deallocated by the caller.
1775 xmlChar *
1776 xmlTextReaderReadString(xmlTextReaderPtr reader)
1778 xmlNodePtr node;
1780 if ((reader == NULL) || (reader->node == NULL))
1781 return(NULL);
1783 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1784 switch (node->type) {
1785 case XML_TEXT_NODE:
1786 if (node->content != NULL)
1787 return(xmlStrdup(node->content));
1788 break;
1789 case XML_ELEMENT_NODE:
1790 if (xmlTextReaderDoExpand(reader) != -1) {
1791 return xmlTextReaderCollectSiblings(node->children);
1793 case XML_ATTRIBUTE_NODE:
1794 TODO
1795 break;
1796 default:
1797 break;
1799 return(NULL);
1802 #if 0
1804 * xmlTextReaderReadBase64:
1805 * @reader: the xmlTextReaderPtr used
1806 * @array: a byte array to store the content.
1807 * @offset: the zero-based index into array where the method should
1808 * begin to write.
1809 * @len: the number of bytes to write.
1811 * Reads and decodes the Base64 encoded contents of an element and
1812 * stores the result in a byte buffer.
1814 * Returns the number of bytes written to array, or zero if the current
1815 * instance is not positioned on an element or -1 in case of error.
1818 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1819 unsigned char *array ATTRIBUTE_UNUSED,
1820 int offset ATTRIBUTE_UNUSED,
1821 int len ATTRIBUTE_UNUSED) {
1822 if ((reader == NULL) || (reader->ctxt == NULL))
1823 return(-1);
1824 if (reader->ctxt->wellFormed != 1)
1825 return(-1);
1827 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1828 return(0);
1829 TODO
1830 return(0);
1834 * xmlTextReaderReadBinHex:
1835 * @reader: the xmlTextReaderPtr used
1836 * @array: a byte array to store the content.
1837 * @offset: the zero-based index into array where the method should
1838 * begin to write.
1839 * @len: the number of bytes to write.
1841 * Reads and decodes the BinHex encoded contents of an element and
1842 * stores the result in a byte buffer.
1844 * Returns the number of bytes written to array, or zero if the current
1845 * instance is not positioned on an element or -1 in case of error.
1848 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1849 unsigned char *array ATTRIBUTE_UNUSED,
1850 int offset ATTRIBUTE_UNUSED,
1851 int len ATTRIBUTE_UNUSED) {
1852 if ((reader == NULL) || (reader->ctxt == NULL))
1853 return(-1);
1854 if (reader->ctxt->wellFormed != 1)
1855 return(-1);
1857 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1858 return(0);
1859 TODO
1860 return(0);
1862 #endif
1864 /************************************************************************
1866 * Operating on a preparsed tree *
1868 ************************************************************************/
1869 static int
1870 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1872 if (reader == NULL)
1873 return(-1);
1875 if (reader->state == XML_TEXTREADER_END)
1876 return(0);
1878 if (reader->node == NULL) {
1879 if (reader->doc->children == NULL) {
1880 reader->state = XML_TEXTREADER_END;
1881 return(0);
1884 reader->node = reader->doc->children;
1885 reader->state = XML_TEXTREADER_START;
1886 return(1);
1889 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1890 /* Here removed traversal to child, because we want to skip the subtree,
1891 replace with traversal to sibling to skip subtree */
1892 if (reader->node->next != 0) {
1893 /* Move to sibling if present,skipping sub-tree */
1894 reader->node = reader->node->next;
1895 reader->state = XML_TEXTREADER_START;
1896 return(1);
1899 /* if reader->node->next is NULL mean no subtree for current node,
1900 so need to move to sibling of parent node if present */
1901 if ((reader->node->type == XML_ELEMENT_NODE) ||
1902 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1903 reader->state = XML_TEXTREADER_BACKTRACK;
1904 /* This will move to parent if present */
1905 xmlTextReaderRead(reader);
1909 if (reader->node->next != 0) {
1910 reader->node = reader->node->next;
1911 reader->state = XML_TEXTREADER_START;
1912 return(1);
1915 if (reader->node->parent != 0) {
1916 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1917 reader->state = XML_TEXTREADER_END;
1918 return(0);
1921 reader->node = reader->node->parent;
1922 reader->depth--;
1923 reader->state = XML_TEXTREADER_BACKTRACK;
1924 /* Repeat process to move to sibling of parent node if present */
1925 xmlTextReaderNextTree(reader);
1928 reader->state = XML_TEXTREADER_END;
1930 return(1);
1934 * xmlTextReaderReadTree:
1935 * @reader: the xmlTextReaderPtr used
1937 * Moves the position of the current instance to the next node in
1938 * the stream, exposing its properties.
1940 * Returns 1 if the node was read successfully, 0 if there is no more
1941 * nodes to read, or -1 in case of error
1943 static int
1944 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1945 if (reader->state == XML_TEXTREADER_END)
1946 return(0);
1948 next_node:
1949 if (reader->node == NULL) {
1950 if (reader->doc->children == NULL) {
1951 reader->state = XML_TEXTREADER_END;
1952 return(0);
1955 reader->node = reader->doc->children;
1956 reader->state = XML_TEXTREADER_START;
1957 goto found_node;
1960 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1961 (reader->node->type != XML_DTD_NODE) &&
1962 (reader->node->type != XML_XINCLUDE_START) &&
1963 (reader->node->type != XML_ENTITY_REF_NODE)) {
1964 if (reader->node->children != NULL) {
1965 reader->node = reader->node->children;
1966 reader->depth++;
1967 reader->state = XML_TEXTREADER_START;
1968 goto found_node;
1971 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1972 reader->state = XML_TEXTREADER_BACKTRACK;
1973 goto found_node;
1977 if (reader->node->next != NULL) {
1978 reader->node = reader->node->next;
1979 reader->state = XML_TEXTREADER_START;
1980 goto found_node;
1983 if (reader->node->parent != NULL) {
1984 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1985 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1986 reader->state = XML_TEXTREADER_END;
1987 return(0);
1990 reader->node = reader->node->parent;
1991 reader->depth--;
1992 reader->state = XML_TEXTREADER_BACKTRACK;
1993 goto found_node;
1996 reader->state = XML_TEXTREADER_END;
1998 found_node:
1999 if ((reader->node->type == XML_XINCLUDE_START) ||
2000 (reader->node->type == XML_XINCLUDE_END))
2001 goto next_node;
2003 return(1);
2007 * xmlTextReaderNextSibling:
2008 * @reader: the xmlTextReaderPtr used
2010 * Skip to the node following the current one in document order while
2011 * avoiding the subtree if any.
2012 * Currently implemented only for Readers built on a document
2014 * Returns 1 if the node was read successfully, 0 if there is no more
2015 * nodes to read, or -1 in case of error
2018 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2019 if (reader == NULL)
2020 return(-1);
2021 if (reader->doc == NULL) {
2022 /* TODO */
2023 return(-1);
2026 if (reader->state == XML_TEXTREADER_END)
2027 return(0);
2029 if (reader->node == NULL)
2030 return(xmlTextReaderNextTree(reader));
2032 if (reader->node->next != NULL) {
2033 reader->node = reader->node->next;
2034 reader->state = XML_TEXTREADER_START;
2035 return(1);
2038 return(0);
2041 /************************************************************************
2043 * Constructor and destructors *
2045 ************************************************************************/
2047 * xmlNewTextReader:
2048 * @input: the xmlParserInputBufferPtr used to read data
2049 * @URI: the URI information for the source if available
2051 * Create an xmlTextReader structure fed with @input
2053 * Returns the new xmlTextReaderPtr or NULL in case of error
2055 xmlTextReaderPtr
2056 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2057 xmlTextReaderPtr ret;
2059 if (input == NULL)
2060 return(NULL);
2061 ret = xmlMalloc(sizeof(xmlTextReader));
2062 if (ret == NULL) {
2063 xmlGenericError(xmlGenericErrorContext,
2064 "xmlNewTextReader : malloc failed\n");
2065 return(NULL);
2067 memset(ret, 0, sizeof(xmlTextReader));
2068 ret->doc = NULL;
2069 ret->entTab = NULL;
2070 ret->entMax = 0;
2071 ret->entNr = 0;
2072 ret->input = input;
2073 ret->buffer = xmlBufCreateSize(100);
2074 if (ret->buffer == NULL) {
2075 xmlFree(ret);
2076 xmlGenericError(xmlGenericErrorContext,
2077 "xmlNewTextReader : malloc failed\n");
2078 return(NULL);
2080 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2081 if (ret->sax == NULL) {
2082 xmlBufFree(ret->buffer);
2083 xmlFree(ret);
2084 xmlGenericError(xmlGenericErrorContext,
2085 "xmlNewTextReader : malloc failed\n");
2086 return(NULL);
2088 xmlSAXVersion(ret->sax, 2);
2089 ret->startElement = ret->sax->startElement;
2090 ret->sax->startElement = xmlTextReaderStartElement;
2091 ret->endElement = ret->sax->endElement;
2092 ret->sax->endElement = xmlTextReaderEndElement;
2093 #ifdef LIBXML_SAX1_ENABLED
2094 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2095 #endif /* LIBXML_SAX1_ENABLED */
2096 ret->startElementNs = ret->sax->startElementNs;
2097 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2098 ret->endElementNs = ret->sax->endElementNs;
2099 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2100 #ifdef LIBXML_SAX1_ENABLED
2101 } else {
2102 ret->startElementNs = NULL;
2103 ret->endElementNs = NULL;
2105 #endif /* LIBXML_SAX1_ENABLED */
2106 ret->characters = ret->sax->characters;
2107 ret->sax->characters = xmlTextReaderCharacters;
2108 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2109 ret->cdataBlock = ret->sax->cdataBlock;
2110 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2112 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2113 ret->node = NULL;
2114 ret->curnode = NULL;
2115 if (xmlBufUse(ret->input->buffer) < 4) {
2116 xmlParserInputBufferRead(input, 4);
2118 if (xmlBufUse(ret->input->buffer) >= 4) {
2119 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2120 (const char *) xmlBufContent(ret->input->buffer),
2121 4, URI);
2122 ret->base = 0;
2123 ret->cur = 4;
2124 } else {
2125 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2126 ret->base = 0;
2127 ret->cur = 0;
2130 if (ret->ctxt == NULL) {
2131 xmlGenericError(xmlGenericErrorContext,
2132 "xmlNewTextReader : malloc failed\n");
2133 xmlBufFree(ret->buffer);
2134 xmlFree(ret->sax);
2135 xmlFree(ret);
2136 return(NULL);
2138 ret->ctxt->parseMode = XML_PARSE_READER;
2139 ret->ctxt->_private = ret;
2140 ret->ctxt->linenumbers = 1;
2141 ret->ctxt->dictNames = 1;
2142 ret->allocs = XML_TEXTREADER_CTXT;
2144 * use the parser dictionnary to allocate all elements and attributes names
2146 ret->ctxt->docdict = 1;
2147 ret->dict = ret->ctxt->dict;
2148 #ifdef LIBXML_XINCLUDE_ENABLED
2149 ret->xinclude = 0;
2150 #endif
2151 #ifdef LIBXML_PATTERN_ENABLED
2152 ret->patternMax = 0;
2153 ret->patternTab = NULL;
2154 #endif
2155 return(ret);
2159 * xmlNewTextReaderFilename:
2160 * @URI: the URI of the resource to process
2162 * Create an xmlTextReader structure fed with the resource at @URI
2164 * Returns the new xmlTextReaderPtr or NULL in case of error
2166 xmlTextReaderPtr
2167 xmlNewTextReaderFilename(const char *URI) {
2168 xmlParserInputBufferPtr input;
2169 xmlTextReaderPtr ret;
2170 char *directory = NULL;
2172 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2173 if (input == NULL)
2174 return(NULL);
2175 ret = xmlNewTextReader(input, URI);
2176 if (ret == NULL) {
2177 xmlFreeParserInputBuffer(input);
2178 return(NULL);
2180 ret->allocs |= XML_TEXTREADER_INPUT;
2181 if (ret->ctxt->directory == NULL)
2182 directory = xmlParserGetDirectory(URI);
2183 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2184 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2185 if (directory != NULL)
2186 xmlFree(directory);
2187 return(ret);
2191 * xmlFreeTextReader:
2192 * @reader: the xmlTextReaderPtr
2194 * Deallocate all the resources associated to the reader
2196 void
2197 xmlFreeTextReader(xmlTextReaderPtr reader) {
2198 if (reader == NULL)
2199 return;
2200 #ifdef LIBXML_SCHEMAS_ENABLED
2201 if (reader->rngSchemas != NULL) {
2202 xmlRelaxNGFree(reader->rngSchemas);
2203 reader->rngSchemas = NULL;
2205 if (reader->rngValidCtxt != NULL) {
2206 if (! reader->rngPreserveCtxt)
2207 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2208 reader->rngValidCtxt = NULL;
2210 if (reader->xsdPlug != NULL) {
2211 xmlSchemaSAXUnplug(reader->xsdPlug);
2212 reader->xsdPlug = NULL;
2214 if (reader->xsdValidCtxt != NULL) {
2215 if (! reader->xsdPreserveCtxt)
2216 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2217 reader->xsdValidCtxt = NULL;
2219 if (reader->xsdSchemas != NULL) {
2220 xmlSchemaFree(reader->xsdSchemas);
2221 reader->xsdSchemas = NULL;
2223 #endif
2224 #ifdef LIBXML_XINCLUDE_ENABLED
2225 if (reader->xincctxt != NULL)
2226 xmlXIncludeFreeContext(reader->xincctxt);
2227 #endif
2228 #ifdef LIBXML_PATTERN_ENABLED
2229 if (reader->patternTab != NULL) {
2230 int i;
2231 for (i = 0;i < reader->patternNr;i++) {
2232 if (reader->patternTab[i] != NULL)
2233 xmlFreePattern(reader->patternTab[i]);
2235 xmlFree(reader->patternTab);
2237 #endif
2238 if (reader->faketext != NULL) {
2239 xmlFreeNode(reader->faketext);
2241 if (reader->ctxt != NULL) {
2242 if (reader->dict == reader->ctxt->dict)
2243 reader->dict = NULL;
2244 if (reader->ctxt->myDoc != NULL) {
2245 if (reader->preserve == 0)
2246 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2247 reader->ctxt->myDoc = NULL;
2249 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2250 (reader->ctxt->vctxt.vstateMax > 0)){
2251 xmlFree(reader->ctxt->vctxt.vstateTab);
2252 reader->ctxt->vctxt.vstateTab = NULL;
2253 reader->ctxt->vctxt.vstateMax = 0;
2255 if (reader->allocs & XML_TEXTREADER_CTXT)
2256 xmlFreeParserCtxt(reader->ctxt);
2258 if (reader->sax != NULL)
2259 xmlFree(reader->sax);
2260 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2261 xmlFreeParserInputBuffer(reader->input);
2262 if (reader->buffer != NULL)
2263 xmlBufFree(reader->buffer);
2264 if (reader->entTab != NULL)
2265 xmlFree(reader->entTab);
2266 if (reader->dict != NULL)
2267 xmlDictFree(reader->dict);
2268 xmlFree(reader);
2271 /************************************************************************
2273 * Methods for XmlTextReader *
2275 ************************************************************************/
2277 * xmlTextReaderClose:
2278 * @reader: the xmlTextReaderPtr used
2280 * This method releases any resources allocated by the current instance
2281 * changes the state to Closed and close any underlying input.
2283 * Returns 0 or -1 in case of error
2286 xmlTextReaderClose(xmlTextReaderPtr reader) {
2287 if (reader == NULL)
2288 return(-1);
2289 reader->node = NULL;
2290 reader->curnode = NULL;
2291 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2292 if (reader->ctxt != NULL) {
2293 xmlStopParser(reader->ctxt);
2294 if (reader->ctxt->myDoc != NULL) {
2295 if (reader->preserve == 0)
2296 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2297 reader->ctxt->myDoc = NULL;
2300 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2301 xmlFreeParserInputBuffer(reader->input);
2302 reader->allocs -= XML_TEXTREADER_INPUT;
2304 return(0);
2308 * xmlTextReaderGetAttributeNo:
2309 * @reader: the xmlTextReaderPtr used
2310 * @no: the zero-based index of the attribute relative to the containing element
2312 * Provides the value of the attribute with the specified index relative
2313 * to the containing element.
2315 * Returns a string containing the value of the specified attribute, or NULL
2316 * in case of error. The string must be deallocated by the caller.
2318 xmlChar *
2319 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2320 xmlChar *ret;
2321 int i;
2322 xmlAttrPtr cur;
2323 xmlNsPtr ns;
2325 if (reader == NULL)
2326 return(NULL);
2327 if (reader->node == NULL)
2328 return(NULL);
2329 if (reader->curnode != NULL)
2330 return(NULL);
2331 /* TODO: handle the xmlDecl */
2332 if (reader->node->type != XML_ELEMENT_NODE)
2333 return(NULL);
2335 ns = reader->node->nsDef;
2336 for (i = 0;(i < no) && (ns != NULL);i++) {
2337 ns = ns->next;
2339 if (ns != NULL)
2340 return(xmlStrdup(ns->href));
2342 cur = reader->node->properties;
2343 if (cur == NULL)
2344 return(NULL);
2345 for (;i < no;i++) {
2346 cur = cur->next;
2347 if (cur == NULL)
2348 return(NULL);
2350 /* TODO walk the DTD if present */
2352 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2353 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2354 return(ret);
2358 * xmlTextReaderGetAttribute:
2359 * @reader: the xmlTextReaderPtr used
2360 * @name: the qualified name of the attribute.
2362 * Provides the value of the attribute with the specified qualified name.
2364 * Returns a string containing the value of the specified attribute, or NULL
2365 * in case of error. The string must be deallocated by the caller.
2367 xmlChar *
2368 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2369 xmlChar *prefix = NULL;
2370 xmlChar *localname;
2371 xmlNsPtr ns;
2372 xmlChar *ret = NULL;
2374 if ((reader == NULL) || (name == NULL))
2375 return(NULL);
2376 if (reader->node == NULL)
2377 return(NULL);
2378 if (reader->curnode != NULL)
2379 return(NULL);
2381 /* TODO: handle the xmlDecl */
2382 if (reader->node->type != XML_ELEMENT_NODE)
2383 return(NULL);
2385 localname = xmlSplitQName2(name, &prefix);
2386 if (localname == NULL) {
2388 * Namespace default decl
2390 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2391 ns = reader->node->nsDef;
2392 while (ns != NULL) {
2393 if (ns->prefix == NULL) {
2394 return(xmlStrdup(ns->href));
2396 ns = ns->next;
2398 return NULL;
2400 return(xmlGetNoNsProp(reader->node, name));
2404 * Namespace default decl
2406 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2407 ns = reader->node->nsDef;
2408 while (ns != NULL) {
2409 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2410 ret = xmlStrdup(ns->href);
2411 break;
2413 ns = ns->next;
2415 } else {
2416 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2417 if (ns != NULL)
2418 ret = xmlGetNsProp(reader->node, localname, ns->href);
2421 xmlFree(localname);
2422 if (prefix != NULL)
2423 xmlFree(prefix);
2424 return(ret);
2429 * xmlTextReaderGetAttributeNs:
2430 * @reader: the xmlTextReaderPtr used
2431 * @localName: the local name of the attribute.
2432 * @namespaceURI: the namespace URI of the attribute.
2434 * Provides the value of the specified attribute
2436 * Returns a string containing the value of the specified attribute, or NULL
2437 * in case of error. The string must be deallocated by the caller.
2439 xmlChar *
2440 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2441 const xmlChar *namespaceURI) {
2442 xmlChar *prefix = NULL;
2443 xmlNsPtr ns;
2445 if ((reader == NULL) || (localName == NULL))
2446 return(NULL);
2447 if (reader->node == NULL)
2448 return(NULL);
2449 if (reader->curnode != NULL)
2450 return(NULL);
2452 /* TODO: handle the xmlDecl */
2453 if (reader->node->type != XML_ELEMENT_NODE)
2454 return(NULL);
2456 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2457 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2458 prefix = BAD_CAST localName;
2460 ns = reader->node->nsDef;
2461 while (ns != NULL) {
2462 if ((prefix == NULL && ns->prefix == NULL) ||
2463 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2464 return xmlStrdup(ns->href);
2466 ns = ns->next;
2468 return NULL;
2471 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2475 * xmlTextReaderGetRemainder:
2476 * @reader: the xmlTextReaderPtr used
2478 * Method to get the remainder of the buffered XML. this method stops the
2479 * parser, set its state to End Of File and return the input stream with
2480 * what is left that the parser did not use.
2482 * The implementation is not good, the parser certainly procgressed past
2483 * what's left in reader->input, and there is an allocation problem. Best
2484 * would be to rewrite it differently.
2486 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2487 * in case of error.
2489 xmlParserInputBufferPtr
2490 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2491 xmlParserInputBufferPtr ret = NULL;
2493 if (reader == NULL)
2494 return(NULL);
2495 if (reader->node == NULL)
2496 return(NULL);
2498 reader->node = NULL;
2499 reader->curnode = NULL;
2500 reader->mode = XML_TEXTREADER_MODE_EOF;
2501 if (reader->ctxt != NULL) {
2502 xmlStopParser(reader->ctxt);
2503 if (reader->ctxt->myDoc != NULL) {
2504 if (reader->preserve == 0)
2505 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2506 reader->ctxt->myDoc = NULL;
2509 if (reader->allocs & XML_TEXTREADER_INPUT) {
2510 ret = reader->input;
2511 reader->input = NULL;
2512 reader->allocs -= XML_TEXTREADER_INPUT;
2513 } else {
2515 * Hum, one may need to duplicate the data structure because
2516 * without reference counting the input may be freed twice:
2517 * - by the layer which allocated it.
2518 * - by the layer to which would have been returned to.
2520 TODO
2521 return(NULL);
2523 return(ret);
2527 * xmlTextReaderLookupNamespace:
2528 * @reader: the xmlTextReaderPtr used
2529 * @prefix: the prefix whose namespace URI is to be resolved. To return
2530 * the default namespace, specify NULL
2532 * Resolves a namespace prefix in the scope of the current element.
2534 * Returns a string containing the namespace URI to which the prefix maps
2535 * or NULL in case of error. The string must be deallocated by the caller.
2537 xmlChar *
2538 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2539 xmlNsPtr ns;
2541 if (reader == NULL)
2542 return(NULL);
2543 if (reader->node == NULL)
2544 return(NULL);
2546 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2547 if (ns == NULL)
2548 return(NULL);
2549 return(xmlStrdup(ns->href));
2553 * xmlTextReaderMoveToAttributeNo:
2554 * @reader: the xmlTextReaderPtr used
2555 * @no: the zero-based index of the attribute relative to the containing
2556 * element.
2558 * Moves the position of the current instance to the attribute with
2559 * the specified index relative to the containing element.
2561 * Returns 1 in case of success, -1 in case of error, 0 if not found
2564 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2565 int i;
2566 xmlAttrPtr cur;
2567 xmlNsPtr ns;
2569 if (reader == NULL)
2570 return(-1);
2571 if (reader->node == NULL)
2572 return(-1);
2573 /* TODO: handle the xmlDecl */
2574 if (reader->node->type != XML_ELEMENT_NODE)
2575 return(-1);
2577 reader->curnode = NULL;
2579 ns = reader->node->nsDef;
2580 for (i = 0;(i < no) && (ns != NULL);i++) {
2581 ns = ns->next;
2583 if (ns != NULL) {
2584 reader->curnode = (xmlNodePtr) ns;
2585 return(1);
2588 cur = reader->node->properties;
2589 if (cur == NULL)
2590 return(0);
2591 for (;i < no;i++) {
2592 cur = cur->next;
2593 if (cur == NULL)
2594 return(0);
2596 /* TODO walk the DTD if present */
2598 reader->curnode = (xmlNodePtr) cur;
2599 return(1);
2603 * xmlTextReaderMoveToAttribute:
2604 * @reader: the xmlTextReaderPtr used
2605 * @name: the qualified name of the attribute.
2607 * Moves the position of the current instance to the attribute with
2608 * the specified qualified name.
2610 * Returns 1 in case of success, -1 in case of error, 0 if not found
2613 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2614 xmlChar *prefix = NULL;
2615 xmlChar *localname;
2616 xmlNsPtr ns;
2617 xmlAttrPtr prop;
2619 if ((reader == NULL) || (name == NULL))
2620 return(-1);
2621 if (reader->node == NULL)
2622 return(-1);
2624 /* TODO: handle the xmlDecl */
2625 if (reader->node->type != XML_ELEMENT_NODE)
2626 return(0);
2628 localname = xmlSplitQName2(name, &prefix);
2629 if (localname == NULL) {
2631 * Namespace default decl
2633 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2634 ns = reader->node->nsDef;
2635 while (ns != NULL) {
2636 if (ns->prefix == NULL) {
2637 reader->curnode = (xmlNodePtr) ns;
2638 return(1);
2640 ns = ns->next;
2642 return(0);
2645 prop = reader->node->properties;
2646 while (prop != NULL) {
2648 * One need to have
2649 * - same attribute names
2650 * - and the attribute carrying that namespace
2652 if ((xmlStrEqual(prop->name, name)) &&
2653 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2654 reader->curnode = (xmlNodePtr) prop;
2655 return(1);
2657 prop = prop->next;
2659 return(0);
2663 * Namespace default decl
2665 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2666 ns = reader->node->nsDef;
2667 while (ns != NULL) {
2668 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2669 reader->curnode = (xmlNodePtr) ns;
2670 goto found;
2672 ns = ns->next;
2674 goto not_found;
2676 prop = reader->node->properties;
2677 while (prop != NULL) {
2679 * One need to have
2680 * - same attribute names
2681 * - and the attribute carrying that namespace
2683 if ((xmlStrEqual(prop->name, localname)) &&
2684 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2685 reader->curnode = (xmlNodePtr) prop;
2686 goto found;
2688 prop = prop->next;
2690 not_found:
2691 if (localname != NULL)
2692 xmlFree(localname);
2693 if (prefix != NULL)
2694 xmlFree(prefix);
2695 return(0);
2697 found:
2698 if (localname != NULL)
2699 xmlFree(localname);
2700 if (prefix != NULL)
2701 xmlFree(prefix);
2702 return(1);
2706 * xmlTextReaderMoveToAttributeNs:
2707 * @reader: the xmlTextReaderPtr used
2708 * @localName: the local name of the attribute.
2709 * @namespaceURI: the namespace URI of the attribute.
2711 * Moves the position of the current instance to the attribute with the
2712 * specified local name and namespace URI.
2714 * Returns 1 in case of success, -1 in case of error, 0 if not found
2717 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2718 const xmlChar *localName, const xmlChar *namespaceURI) {
2719 xmlAttrPtr prop;
2720 xmlNodePtr node;
2721 xmlNsPtr ns;
2722 xmlChar *prefix = NULL;
2724 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2725 return(-1);
2726 if (reader->node == NULL)
2727 return(-1);
2728 if (reader->node->type != XML_ELEMENT_NODE)
2729 return(0);
2730 node = reader->node;
2732 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2733 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2734 prefix = BAD_CAST localName;
2736 ns = reader->node->nsDef;
2737 while (ns != NULL) {
2738 if ((prefix == NULL && ns->prefix == NULL) ||
2739 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2740 reader->curnode = (xmlNodePtr) ns;
2741 return(1);
2743 ns = ns->next;
2745 return(0);
2748 prop = node->properties;
2749 while (prop != NULL) {
2751 * One need to have
2752 * - same attribute names
2753 * - and the attribute carrying that namespace
2755 if (xmlStrEqual(prop->name, localName) &&
2756 ((prop->ns != NULL) &&
2757 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2758 reader->curnode = (xmlNodePtr) prop;
2759 return(1);
2761 prop = prop->next;
2763 return(0);
2767 * xmlTextReaderMoveToFirstAttribute:
2768 * @reader: the xmlTextReaderPtr used
2770 * Moves the position of the current instance to the first attribute
2771 * associated with the current node.
2773 * Returns 1 in case of success, -1 in case of error, 0 if not found
2776 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2777 if (reader == NULL)
2778 return(-1);
2779 if (reader->node == NULL)
2780 return(-1);
2781 if (reader->node->type != XML_ELEMENT_NODE)
2782 return(0);
2784 if (reader->node->nsDef != NULL) {
2785 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2786 return(1);
2788 if (reader->node->properties != NULL) {
2789 reader->curnode = (xmlNodePtr) reader->node->properties;
2790 return(1);
2792 return(0);
2796 * xmlTextReaderMoveToNextAttribute:
2797 * @reader: the xmlTextReaderPtr used
2799 * Moves the position of the current instance to the next attribute
2800 * associated with the current node.
2802 * Returns 1 in case of success, -1 in case of error, 0 if not found
2805 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2806 if (reader == NULL)
2807 return(-1);
2808 if (reader->node == NULL)
2809 return(-1);
2810 if (reader->node->type != XML_ELEMENT_NODE)
2811 return(0);
2812 if (reader->curnode == NULL)
2813 return(xmlTextReaderMoveToFirstAttribute(reader));
2815 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2816 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2817 if (ns->next != NULL) {
2818 reader->curnode = (xmlNodePtr) ns->next;
2819 return(1);
2821 if (reader->node->properties != NULL) {
2822 reader->curnode = (xmlNodePtr) reader->node->properties;
2823 return(1);
2825 return(0);
2826 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2827 (reader->curnode->next != NULL)) {
2828 reader->curnode = reader->curnode->next;
2829 return(1);
2831 return(0);
2835 * xmlTextReaderMoveToElement:
2836 * @reader: the xmlTextReaderPtr used
2838 * Moves the position of the current instance to the node that
2839 * contains the current Attribute node.
2841 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2844 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2845 if (reader == NULL)
2846 return(-1);
2847 if (reader->node == NULL)
2848 return(-1);
2849 if (reader->node->type != XML_ELEMENT_NODE)
2850 return(0);
2851 if (reader->curnode != NULL) {
2852 reader->curnode = NULL;
2853 return(1);
2855 return(0);
2859 * xmlTextReaderReadAttributeValue:
2860 * @reader: the xmlTextReaderPtr used
2862 * Parses an attribute value into one or more Text and EntityReference nodes.
2864 * Returns 1 in case of success, 0 if the reader was not positionned on an
2865 * ttribute node or all the attribute values have been read, or -1
2866 * in case of error.
2869 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2870 if (reader == NULL)
2871 return(-1);
2872 if (reader->node == NULL)
2873 return(-1);
2874 if (reader->curnode == NULL)
2875 return(0);
2876 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2877 if (reader->curnode->children == NULL)
2878 return(0);
2879 reader->curnode = reader->curnode->children;
2880 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2881 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2883 if (reader->faketext == NULL) {
2884 reader->faketext = xmlNewDocText(reader->node->doc,
2885 ns->href);
2886 } else {
2887 if ((reader->faketext->content != NULL) &&
2888 (reader->faketext->content !=
2889 (xmlChar *) &(reader->faketext->properties)))
2890 xmlFree(reader->faketext->content);
2891 reader->faketext->content = xmlStrdup(ns->href);
2893 reader->curnode = reader->faketext;
2894 } else {
2895 if (reader->curnode->next == NULL)
2896 return(0);
2897 reader->curnode = reader->curnode->next;
2899 return(1);
2903 * xmlTextReaderConstEncoding:
2904 * @reader: the xmlTextReaderPtr used
2906 * Determine the encoding of the document being read.
2908 * Returns a string containing the encoding of the document or NULL in
2909 * case of error. The string is deallocated with the reader.
2911 const xmlChar *
2912 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2913 xmlDocPtr doc = NULL;
2914 if (reader == NULL)
2915 return(NULL);
2916 if (reader->doc != NULL)
2917 doc = reader->doc;
2918 else if (reader->ctxt != NULL)
2919 doc = reader->ctxt->myDoc;
2920 if (doc == NULL)
2921 return(NULL);
2923 if (doc->encoding == NULL)
2924 return(NULL);
2925 else
2926 return(CONSTSTR(doc->encoding));
2930 /************************************************************************
2932 * Acces API to the current node *
2934 ************************************************************************/
2936 * xmlTextReaderAttributeCount:
2937 * @reader: the xmlTextReaderPtr used
2939 * Provides the number of attributes of the current node
2941 * Returns 0 i no attributes, -1 in case of error or the attribute count
2944 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2945 int ret;
2946 xmlAttrPtr attr;
2947 xmlNsPtr ns;
2948 xmlNodePtr node;
2950 if (reader == NULL)
2951 return(-1);
2952 if (reader->node == NULL)
2953 return(0);
2955 if (reader->curnode != NULL)
2956 node = reader->curnode;
2957 else
2958 node = reader->node;
2960 if (node->type != XML_ELEMENT_NODE)
2961 return(0);
2962 if ((reader->state == XML_TEXTREADER_END) ||
2963 (reader->state == XML_TEXTREADER_BACKTRACK))
2964 return(0);
2965 ret = 0;
2966 attr = node->properties;
2967 while (attr != NULL) {
2968 ret++;
2969 attr = attr->next;
2971 ns = node->nsDef;
2972 while (ns != NULL) {
2973 ret++;
2974 ns = ns->next;
2976 return(ret);
2980 * xmlTextReaderNodeType:
2981 * @reader: the xmlTextReaderPtr used
2983 * Get the node type of the current node
2984 * Reference:
2985 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
2987 * Returns the xmlNodeType of the current node or -1 in case of error
2990 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2991 xmlNodePtr node;
2993 if (reader == NULL)
2994 return(-1);
2995 if (reader->node == NULL)
2996 return(XML_READER_TYPE_NONE);
2997 if (reader->curnode != NULL)
2998 node = reader->curnode;
2999 else
3000 node = reader->node;
3001 switch (node->type) {
3002 case XML_ELEMENT_NODE:
3003 if ((reader->state == XML_TEXTREADER_END) ||
3004 (reader->state == XML_TEXTREADER_BACKTRACK))
3005 return(XML_READER_TYPE_END_ELEMENT);
3006 return(XML_READER_TYPE_ELEMENT);
3007 case XML_NAMESPACE_DECL:
3008 case XML_ATTRIBUTE_NODE:
3009 return(XML_READER_TYPE_ATTRIBUTE);
3010 case XML_TEXT_NODE:
3011 if (xmlIsBlankNode(reader->node)) {
3012 if (xmlNodeGetSpacePreserve(reader->node))
3013 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3014 else
3015 return(XML_READER_TYPE_WHITESPACE);
3016 } else {
3017 return(XML_READER_TYPE_TEXT);
3019 case XML_CDATA_SECTION_NODE:
3020 return(XML_READER_TYPE_CDATA);
3021 case XML_ENTITY_REF_NODE:
3022 return(XML_READER_TYPE_ENTITY_REFERENCE);
3023 case XML_ENTITY_NODE:
3024 return(XML_READER_TYPE_ENTITY);
3025 case XML_PI_NODE:
3026 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3027 case XML_COMMENT_NODE:
3028 return(XML_READER_TYPE_COMMENT);
3029 case XML_DOCUMENT_NODE:
3030 case XML_HTML_DOCUMENT_NODE:
3031 #ifdef LIBXML_DOCB_ENABLED
3032 case XML_DOCB_DOCUMENT_NODE:
3033 #endif
3034 return(XML_READER_TYPE_DOCUMENT);
3035 case XML_DOCUMENT_FRAG_NODE:
3036 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3037 case XML_NOTATION_NODE:
3038 return(XML_READER_TYPE_NOTATION);
3039 case XML_DOCUMENT_TYPE_NODE:
3040 case XML_DTD_NODE:
3041 return(XML_READER_TYPE_DOCUMENT_TYPE);
3043 case XML_ELEMENT_DECL:
3044 case XML_ATTRIBUTE_DECL:
3045 case XML_ENTITY_DECL:
3046 case XML_XINCLUDE_START:
3047 case XML_XINCLUDE_END:
3048 return(XML_READER_TYPE_NONE);
3050 return(-1);
3054 * xmlTextReaderIsEmptyElement:
3055 * @reader: the xmlTextReaderPtr used
3057 * Check if the current node is empty
3059 * Returns 1 if empty, 0 if not and -1 in case of error
3062 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3063 if ((reader == NULL) || (reader->node == NULL))
3064 return(-1);
3065 if (reader->node->type != XML_ELEMENT_NODE)
3066 return(0);
3067 if (reader->curnode != NULL)
3068 return(0);
3069 if (reader->node->children != NULL)
3070 return(0);
3071 if (reader->state == XML_TEXTREADER_END)
3072 return(0);
3073 if (reader->doc != NULL)
3074 return(1);
3075 #ifdef LIBXML_XINCLUDE_ENABLED
3076 if (reader->in_xinclude > 0)
3077 return(1);
3078 #endif
3079 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3083 * xmlTextReaderLocalName:
3084 * @reader: the xmlTextReaderPtr used
3086 * The local name of the node.
3088 * Returns the local name or NULL if not available,
3089 * if non NULL it need to be freed by the caller.
3091 xmlChar *
3092 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3093 xmlNodePtr node;
3094 if ((reader == NULL) || (reader->node == NULL))
3095 return(NULL);
3096 if (reader->curnode != NULL)
3097 node = reader->curnode;
3098 else
3099 node = reader->node;
3100 if (node->type == XML_NAMESPACE_DECL) {
3101 xmlNsPtr ns = (xmlNsPtr) node;
3102 if (ns->prefix == NULL)
3103 return(xmlStrdup(BAD_CAST "xmlns"));
3104 else
3105 return(xmlStrdup(ns->prefix));
3107 if ((node->type != XML_ELEMENT_NODE) &&
3108 (node->type != XML_ATTRIBUTE_NODE))
3109 return(xmlTextReaderName(reader));
3110 return(xmlStrdup(node->name));
3114 * xmlTextReaderConstLocalName:
3115 * @reader: the xmlTextReaderPtr used
3117 * The local name of the node.
3119 * Returns the local name or NULL if not available, the
3120 * string will be deallocated with the reader.
3122 const xmlChar *
3123 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3124 xmlNodePtr node;
3125 if ((reader == NULL) || (reader->node == NULL))
3126 return(NULL);
3127 if (reader->curnode != NULL)
3128 node = reader->curnode;
3129 else
3130 node = reader->node;
3131 if (node->type == XML_NAMESPACE_DECL) {
3132 xmlNsPtr ns = (xmlNsPtr) node;
3133 if (ns->prefix == NULL)
3134 return(CONSTSTR(BAD_CAST "xmlns"));
3135 else
3136 return(ns->prefix);
3138 if ((node->type != XML_ELEMENT_NODE) &&
3139 (node->type != XML_ATTRIBUTE_NODE))
3140 return(xmlTextReaderConstName(reader));
3141 return(node->name);
3145 * xmlTextReaderName:
3146 * @reader: the xmlTextReaderPtr used
3148 * The qualified name of the node, equal to Prefix :LocalName.
3150 * Returns the local name or NULL if not available,
3151 * if non NULL it need to be freed by the caller.
3153 xmlChar *
3154 xmlTextReaderName(xmlTextReaderPtr reader) {
3155 xmlNodePtr node;
3156 xmlChar *ret;
3158 if ((reader == NULL) || (reader->node == NULL))
3159 return(NULL);
3160 if (reader->curnode != NULL)
3161 node = reader->curnode;
3162 else
3163 node = reader->node;
3164 switch (node->type) {
3165 case XML_ELEMENT_NODE:
3166 case XML_ATTRIBUTE_NODE:
3167 if ((node->ns == NULL) ||
3168 (node->ns->prefix == NULL))
3169 return(xmlStrdup(node->name));
3171 ret = xmlStrdup(node->ns->prefix);
3172 ret = xmlStrcat(ret, BAD_CAST ":");
3173 ret = xmlStrcat(ret, node->name);
3174 return(ret);
3175 case XML_TEXT_NODE:
3176 return(xmlStrdup(BAD_CAST "#text"));
3177 case XML_CDATA_SECTION_NODE:
3178 return(xmlStrdup(BAD_CAST "#cdata-section"));
3179 case XML_ENTITY_NODE:
3180 case XML_ENTITY_REF_NODE:
3181 return(xmlStrdup(node->name));
3182 case XML_PI_NODE:
3183 return(xmlStrdup(node->name));
3184 case XML_COMMENT_NODE:
3185 return(xmlStrdup(BAD_CAST "#comment"));
3186 case XML_DOCUMENT_NODE:
3187 case XML_HTML_DOCUMENT_NODE:
3188 #ifdef LIBXML_DOCB_ENABLED
3189 case XML_DOCB_DOCUMENT_NODE:
3190 #endif
3191 return(xmlStrdup(BAD_CAST "#document"));
3192 case XML_DOCUMENT_FRAG_NODE:
3193 return(xmlStrdup(BAD_CAST "#document-fragment"));
3194 case XML_NOTATION_NODE:
3195 return(xmlStrdup(node->name));
3196 case XML_DOCUMENT_TYPE_NODE:
3197 case XML_DTD_NODE:
3198 return(xmlStrdup(node->name));
3199 case XML_NAMESPACE_DECL: {
3200 xmlNsPtr ns = (xmlNsPtr) node;
3202 ret = xmlStrdup(BAD_CAST "xmlns");
3203 if (ns->prefix == NULL)
3204 return(ret);
3205 ret = xmlStrcat(ret, BAD_CAST ":");
3206 ret = xmlStrcat(ret, ns->prefix);
3207 return(ret);
3210 case XML_ELEMENT_DECL:
3211 case XML_ATTRIBUTE_DECL:
3212 case XML_ENTITY_DECL:
3213 case XML_XINCLUDE_START:
3214 case XML_XINCLUDE_END:
3215 return(NULL);
3217 return(NULL);
3221 * xmlTextReaderConstName:
3222 * @reader: the xmlTextReaderPtr used
3224 * The qualified name of the node, equal to Prefix :LocalName.
3226 * Returns the local name or NULL if not available, the string is
3227 * deallocated with the reader.
3229 const xmlChar *
3230 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3231 xmlNodePtr node;
3233 if ((reader == NULL) || (reader->node == NULL))
3234 return(NULL);
3235 if (reader->curnode != NULL)
3236 node = reader->curnode;
3237 else
3238 node = reader->node;
3239 switch (node->type) {
3240 case XML_ELEMENT_NODE:
3241 case XML_ATTRIBUTE_NODE:
3242 if ((node->ns == NULL) ||
3243 (node->ns->prefix == NULL))
3244 return(node->name);
3245 return(CONSTQSTR(node->ns->prefix, node->name));
3246 case XML_TEXT_NODE:
3247 return(CONSTSTR(BAD_CAST "#text"));
3248 case XML_CDATA_SECTION_NODE:
3249 return(CONSTSTR(BAD_CAST "#cdata-section"));
3250 case XML_ENTITY_NODE:
3251 case XML_ENTITY_REF_NODE:
3252 return(CONSTSTR(node->name));
3253 case XML_PI_NODE:
3254 return(CONSTSTR(node->name));
3255 case XML_COMMENT_NODE:
3256 return(CONSTSTR(BAD_CAST "#comment"));
3257 case XML_DOCUMENT_NODE:
3258 case XML_HTML_DOCUMENT_NODE:
3259 #ifdef LIBXML_DOCB_ENABLED
3260 case XML_DOCB_DOCUMENT_NODE:
3261 #endif
3262 return(CONSTSTR(BAD_CAST "#document"));
3263 case XML_DOCUMENT_FRAG_NODE:
3264 return(CONSTSTR(BAD_CAST "#document-fragment"));
3265 case XML_NOTATION_NODE:
3266 return(CONSTSTR(node->name));
3267 case XML_DOCUMENT_TYPE_NODE:
3268 case XML_DTD_NODE:
3269 return(CONSTSTR(node->name));
3270 case XML_NAMESPACE_DECL: {
3271 xmlNsPtr ns = (xmlNsPtr) node;
3273 if (ns->prefix == NULL)
3274 return(CONSTSTR(BAD_CAST "xmlns"));
3275 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3278 case XML_ELEMENT_DECL:
3279 case XML_ATTRIBUTE_DECL:
3280 case XML_ENTITY_DECL:
3281 case XML_XINCLUDE_START:
3282 case XML_XINCLUDE_END:
3283 return(NULL);
3285 return(NULL);
3289 * xmlTextReaderPrefix:
3290 * @reader: the xmlTextReaderPtr used
3292 * A shorthand reference to the namespace associated with the node.
3294 * Returns the prefix or NULL if not available,
3295 * if non NULL it need to be freed by the caller.
3297 xmlChar *
3298 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3299 xmlNodePtr node;
3300 if ((reader == NULL) || (reader->node == NULL))
3301 return(NULL);
3302 if (reader->curnode != NULL)
3303 node = reader->curnode;
3304 else
3305 node = reader->node;
3306 if (node->type == XML_NAMESPACE_DECL) {
3307 xmlNsPtr ns = (xmlNsPtr) node;
3308 if (ns->prefix == NULL)
3309 return(NULL);
3310 return(xmlStrdup(BAD_CAST "xmlns"));
3312 if ((node->type != XML_ELEMENT_NODE) &&
3313 (node->type != XML_ATTRIBUTE_NODE))
3314 return(NULL);
3315 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3316 return(xmlStrdup(node->ns->prefix));
3317 return(NULL);
3321 * xmlTextReaderConstPrefix:
3322 * @reader: the xmlTextReaderPtr used
3324 * A shorthand reference to the namespace associated with the node.
3326 * Returns the prefix or NULL if not available, the string is deallocated
3327 * with the reader.
3329 const xmlChar *
3330 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3331 xmlNodePtr node;
3332 if ((reader == NULL) || (reader->node == NULL))
3333 return(NULL);
3334 if (reader->curnode != NULL)
3335 node = reader->curnode;
3336 else
3337 node = reader->node;
3338 if (node->type == XML_NAMESPACE_DECL) {
3339 xmlNsPtr ns = (xmlNsPtr) node;
3340 if (ns->prefix == NULL)
3341 return(NULL);
3342 return(CONSTSTR(BAD_CAST "xmlns"));
3344 if ((node->type != XML_ELEMENT_NODE) &&
3345 (node->type != XML_ATTRIBUTE_NODE))
3346 return(NULL);
3347 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3348 return(CONSTSTR(node->ns->prefix));
3349 return(NULL);
3353 * xmlTextReaderNamespaceUri:
3354 * @reader: the xmlTextReaderPtr used
3356 * The URI defining the namespace associated with the node.
3358 * Returns the namespace URI or NULL if not available,
3359 * if non NULL it need to be freed by the caller.
3361 xmlChar *
3362 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3363 xmlNodePtr node;
3364 if ((reader == NULL) || (reader->node == NULL))
3365 return(NULL);
3366 if (reader->curnode != NULL)
3367 node = reader->curnode;
3368 else
3369 node = reader->node;
3370 if (node->type == XML_NAMESPACE_DECL)
3371 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3372 if ((node->type != XML_ELEMENT_NODE) &&
3373 (node->type != XML_ATTRIBUTE_NODE))
3374 return(NULL);
3375 if (node->ns != NULL)
3376 return(xmlStrdup(node->ns->href));
3377 return(NULL);
3381 * xmlTextReaderConstNamespaceUri:
3382 * @reader: the xmlTextReaderPtr used
3384 * The URI defining the namespace associated with the node.
3386 * Returns the namespace URI or NULL if not available, the string
3387 * will be deallocated with the reader
3389 const xmlChar *
3390 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3391 xmlNodePtr node;
3392 if ((reader == NULL) || (reader->node == NULL))
3393 return(NULL);
3394 if (reader->curnode != NULL)
3395 node = reader->curnode;
3396 else
3397 node = reader->node;
3398 if (node->type == XML_NAMESPACE_DECL)
3399 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3400 if ((node->type != XML_ELEMENT_NODE) &&
3401 (node->type != XML_ATTRIBUTE_NODE))
3402 return(NULL);
3403 if (node->ns != NULL)
3404 return(CONSTSTR(node->ns->href));
3405 return(NULL);
3409 * xmlTextReaderBaseUri:
3410 * @reader: the xmlTextReaderPtr used
3412 * The base URI of the node.
3414 * Returns the base URI or NULL if not available,
3415 * if non NULL it need to be freed by the caller.
3417 xmlChar *
3418 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3419 if ((reader == NULL) || (reader->node == NULL))
3420 return(NULL);
3421 return(xmlNodeGetBase(NULL, reader->node));
3425 * xmlTextReaderConstBaseUri:
3426 * @reader: the xmlTextReaderPtr used
3428 * The base URI of the node.
3430 * Returns the base URI or NULL if not available, the string
3431 * will be deallocated with the reader
3433 const xmlChar *
3434 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3435 xmlChar *tmp;
3436 const xmlChar *ret;
3438 if ((reader == NULL) || (reader->node == NULL))
3439 return(NULL);
3440 tmp = xmlNodeGetBase(NULL, reader->node);
3441 if (tmp == NULL)
3442 return(NULL);
3443 ret = CONSTSTR(tmp);
3444 xmlFree(tmp);
3445 return(ret);
3449 * xmlTextReaderDepth:
3450 * @reader: the xmlTextReaderPtr used
3452 * The depth of the node in the tree.
3454 * Returns the depth or -1 in case of error
3457 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3458 if (reader == NULL)
3459 return(-1);
3460 if (reader->node == NULL)
3461 return(0);
3463 if (reader->curnode != NULL) {
3464 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3465 (reader->curnode->type == XML_NAMESPACE_DECL))
3466 return(reader->depth + 1);
3467 return(reader->depth + 2);
3469 return(reader->depth);
3473 * xmlTextReaderHasAttributes:
3474 * @reader: the xmlTextReaderPtr used
3476 * Whether the node has attributes.
3478 * Returns 1 if true, 0 if false, and -1 in case or error
3481 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3482 xmlNodePtr node;
3483 if (reader == NULL)
3484 return(-1);
3485 if (reader->node == NULL)
3486 return(0);
3487 if (reader->curnode != NULL)
3488 node = reader->curnode;
3489 else
3490 node = reader->node;
3492 if ((node->type == XML_ELEMENT_NODE) &&
3493 ((node->properties != NULL) || (node->nsDef != NULL)))
3494 return(1);
3495 /* TODO: handle the xmlDecl */
3496 return(0);
3500 * xmlTextReaderHasValue:
3501 * @reader: the xmlTextReaderPtr used
3503 * Whether the node can have a text value.
3505 * Returns 1 if true, 0 if false, and -1 in case or error
3508 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3509 xmlNodePtr node;
3510 if (reader == NULL)
3511 return(-1);
3512 if (reader->node == NULL)
3513 return(0);
3514 if (reader->curnode != NULL)
3515 node = reader->curnode;
3516 else
3517 node = reader->node;
3519 switch (node->type) {
3520 case XML_ATTRIBUTE_NODE:
3521 case XML_TEXT_NODE:
3522 case XML_CDATA_SECTION_NODE:
3523 case XML_PI_NODE:
3524 case XML_COMMENT_NODE:
3525 case XML_NAMESPACE_DECL:
3526 return(1);
3527 default:
3528 break;
3530 return(0);
3534 * xmlTextReaderValue:
3535 * @reader: the xmlTextReaderPtr used
3537 * Provides the text value of the node if present
3539 * Returns the string or NULL if not available. The result must be deallocated
3540 * with xmlFree()
3542 xmlChar *
3543 xmlTextReaderValue(xmlTextReaderPtr reader) {
3544 xmlNodePtr node;
3545 if (reader == NULL)
3546 return(NULL);
3547 if (reader->node == NULL)
3548 return(NULL);
3549 if (reader->curnode != NULL)
3550 node = reader->curnode;
3551 else
3552 node = reader->node;
3554 switch (node->type) {
3555 case XML_NAMESPACE_DECL:
3556 return(xmlStrdup(((xmlNsPtr) node)->href));
3557 case XML_ATTRIBUTE_NODE:{
3558 xmlAttrPtr attr = (xmlAttrPtr) node;
3560 if (attr->parent != NULL)
3561 return (xmlNodeListGetString
3562 (attr->parent->doc, attr->children, 1));
3563 else
3564 return (xmlNodeListGetString(NULL, attr->children, 1));
3565 break;
3567 case XML_TEXT_NODE:
3568 case XML_CDATA_SECTION_NODE:
3569 case XML_PI_NODE:
3570 case XML_COMMENT_NODE:
3571 if (node->content != NULL)
3572 return (xmlStrdup(node->content));
3573 default:
3574 break;
3576 return(NULL);
3580 * xmlTextReaderConstValue:
3581 * @reader: the xmlTextReaderPtr used
3583 * Provides the text value of the node if present
3585 * Returns the string or NULL if not available. The result will be
3586 * deallocated on the next Read() operation.
3588 const xmlChar *
3589 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3590 xmlNodePtr node;
3591 if (reader == NULL)
3592 return(NULL);
3593 if (reader->node == NULL)
3594 return(NULL);
3595 if (reader->curnode != NULL)
3596 node = reader->curnode;
3597 else
3598 node = reader->node;
3600 switch (node->type) {
3601 case XML_NAMESPACE_DECL:
3602 return(((xmlNsPtr) node)->href);
3603 case XML_ATTRIBUTE_NODE:{
3604 xmlAttrPtr attr = (xmlAttrPtr) node;
3606 if ((attr->children != NULL) &&
3607 (attr->children->type == XML_TEXT_NODE) &&
3608 (attr->children->next == NULL))
3609 return(attr->children->content);
3610 else {
3611 if (reader->buffer == NULL) {
3612 reader->buffer = xmlBufCreateSize(100);
3613 if (reader->buffer == NULL) {
3614 xmlGenericError(xmlGenericErrorContext,
3615 "xmlTextReaderSetup : malloc failed\n");
3616 return (NULL);
3618 } else
3619 xmlBufEmpty(reader->buffer);
3620 xmlBufGetNodeContent(reader->buffer, node);
3621 return(xmlBufContent(reader->buffer));
3623 break;
3625 case XML_TEXT_NODE:
3626 case XML_CDATA_SECTION_NODE:
3627 case XML_PI_NODE:
3628 case XML_COMMENT_NODE:
3629 return(node->content);
3630 default:
3631 break;
3633 return(NULL);
3637 * xmlTextReaderIsDefault:
3638 * @reader: the xmlTextReaderPtr used
3640 * Whether an Attribute node was generated from the default value
3641 * defined in the DTD or schema.
3643 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3646 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3647 if (reader == NULL)
3648 return(-1);
3649 return(0);
3653 * xmlTextReaderQuoteChar:
3654 * @reader: the xmlTextReaderPtr used
3656 * The quotation mark character used to enclose the value of an attribute.
3658 * Returns " or ' and -1 in case of error
3661 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3662 if (reader == NULL)
3663 return(-1);
3664 /* TODO maybe lookup the attribute value for " first */
3665 return((int) '"');
3669 * xmlTextReaderXmlLang:
3670 * @reader: the xmlTextReaderPtr used
3672 * The xml:lang scope within which the node resides.
3674 * Returns the xml:lang value or NULL if none exists.,
3675 * if non NULL it need to be freed by the caller.
3677 xmlChar *
3678 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3679 if (reader == NULL)
3680 return(NULL);
3681 if (reader->node == NULL)
3682 return(NULL);
3683 return(xmlNodeGetLang(reader->node));
3687 * xmlTextReaderConstXmlLang:
3688 * @reader: the xmlTextReaderPtr used
3690 * The xml:lang scope within which the node resides.
3692 * Returns the xml:lang value or NULL if none exists.
3694 const xmlChar *
3695 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3696 xmlChar *tmp;
3697 const xmlChar *ret;
3699 if (reader == NULL)
3700 return(NULL);
3701 if (reader->node == NULL)
3702 return(NULL);
3703 tmp = xmlNodeGetLang(reader->node);
3704 if (tmp == NULL)
3705 return(NULL);
3706 ret = CONSTSTR(tmp);
3707 xmlFree(tmp);
3708 return(ret);
3712 * xmlTextReaderConstString:
3713 * @reader: the xmlTextReaderPtr used
3714 * @str: the string to intern.
3716 * Get an interned string from the reader, allows for example to
3717 * speedup string name comparisons
3719 * Returns an interned copy of the string or NULL in case of error. The
3720 * string will be deallocated with the reader.
3722 const xmlChar *
3723 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3724 if (reader == NULL)
3725 return(NULL);
3726 return(CONSTSTR(str));
3730 * xmlTextReaderNormalization:
3731 * @reader: the xmlTextReaderPtr used
3733 * The value indicating whether to normalize white space and attribute values.
3734 * Since attribute value and end of line normalizations are a MUST in the XML
3735 * specification only the value true is accepted. The broken bahaviour of
3736 * accepting out of range character entities like &#0; is of course not
3737 * supported either.
3739 * Returns 1 or -1 in case of error.
3742 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3743 if (reader == NULL)
3744 return(-1);
3745 return(1);
3748 /************************************************************************
3750 * Extensions to the base APIs *
3752 ************************************************************************/
3755 * xmlTextReaderSetParserProp:
3756 * @reader: the xmlTextReaderPtr used
3757 * @prop: the xmlParserProperties to set
3758 * @value: usually 0 or 1 to (de)activate it
3760 * Change the parser processing behaviour by changing some of its internal
3761 * properties. Note that some properties can only be changed before any
3762 * read has been done.
3764 * Returns 0 if the call was successful, or -1 in case of error
3767 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3768 xmlParserProperties p = (xmlParserProperties) prop;
3769 xmlParserCtxtPtr ctxt;
3771 if ((reader == NULL) || (reader->ctxt == NULL))
3772 return(-1);
3773 ctxt = reader->ctxt;
3775 switch (p) {
3776 case XML_PARSER_LOADDTD:
3777 if (value != 0) {
3778 if (ctxt->loadsubset == 0) {
3779 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3780 return(-1);
3781 ctxt->loadsubset = XML_DETECT_IDS;
3783 } else {
3784 ctxt->loadsubset = 0;
3786 return(0);
3787 case XML_PARSER_DEFAULTATTRS:
3788 if (value != 0) {
3789 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3790 } else {
3791 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3792 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3794 return(0);
3795 case XML_PARSER_VALIDATE:
3796 if (value != 0) {
3797 ctxt->validate = 1;
3798 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3799 } else {
3800 ctxt->validate = 0;
3802 return(0);
3803 case XML_PARSER_SUBST_ENTITIES:
3804 if (value != 0) {
3805 ctxt->replaceEntities = 1;
3806 } else {
3807 ctxt->replaceEntities = 0;
3809 return(0);
3811 return(-1);
3815 * xmlTextReaderGetParserProp:
3816 * @reader: the xmlTextReaderPtr used
3817 * @prop: the xmlParserProperties to get
3819 * Read the parser internal property.
3821 * Returns the value, usually 0 or 1, or -1 in case of error.
3824 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3825 xmlParserProperties p = (xmlParserProperties) prop;
3826 xmlParserCtxtPtr ctxt;
3828 if ((reader == NULL) || (reader->ctxt == NULL))
3829 return(-1);
3830 ctxt = reader->ctxt;
3832 switch (p) {
3833 case XML_PARSER_LOADDTD:
3834 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3835 return(1);
3836 return(0);
3837 case XML_PARSER_DEFAULTATTRS:
3838 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3839 return(1);
3840 return(0);
3841 case XML_PARSER_VALIDATE:
3842 return(reader->validate);
3843 case XML_PARSER_SUBST_ENTITIES:
3844 return(ctxt->replaceEntities);
3846 return(-1);
3851 * xmlTextReaderGetParserLineNumber:
3852 * @reader: the user data (XML reader context)
3854 * Provide the line number of the current parsing point.
3856 * Returns an int or 0 if not available
3859 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3861 if ((reader == NULL) || (reader->ctxt == NULL) ||
3862 (reader->ctxt->input == NULL)) {
3863 return (0);
3865 return (reader->ctxt->input->line);
3869 * xmlTextReaderGetParserColumnNumber:
3870 * @reader: the user data (XML reader context)
3872 * Provide the column number of the current parsing point.
3874 * Returns an int or 0 if not available
3877 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3879 if ((reader == NULL) || (reader->ctxt == NULL) ||
3880 (reader->ctxt->input == NULL)) {
3881 return (0);
3883 return (reader->ctxt->input->col);
3887 * xmlTextReaderCurrentNode:
3888 * @reader: the xmlTextReaderPtr used
3890 * Hacking interface allowing to get the xmlNodePtr correponding to the
3891 * current node being accessed by the xmlTextReader. This is dangerous
3892 * because the underlying node may be destroyed on the next Reads.
3894 * Returns the xmlNodePtr or NULL in case of error.
3896 xmlNodePtr
3897 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3898 if (reader == NULL)
3899 return(NULL);
3901 if (reader->curnode != NULL)
3902 return(reader->curnode);
3903 return(reader->node);
3907 * xmlTextReaderPreserve:
3908 * @reader: the xmlTextReaderPtr used
3910 * This tells the XML Reader to preserve the current node.
3911 * The caller must also use xmlTextReaderCurrentDoc() to
3912 * keep an handle on the resulting document once parsing has finished
3914 * Returns the xmlNodePtr or NULL in case of error.
3916 xmlNodePtr
3917 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3918 xmlNodePtr cur, parent;
3920 if (reader == NULL)
3921 return(NULL);
3923 if (reader->curnode != NULL)
3924 cur = reader->curnode;
3925 else
3926 cur = reader->node;
3927 if (cur == NULL)
3928 return(NULL);
3930 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3931 cur->extra |= NODE_IS_PRESERVED;
3932 cur->extra |= NODE_IS_SPRESERVED;
3934 reader->preserves++;
3936 parent = cur->parent;;
3937 while (parent != NULL) {
3938 if (parent->type == XML_ELEMENT_NODE)
3939 parent->extra |= NODE_IS_PRESERVED;
3940 parent = parent->parent;
3942 return(cur);
3945 #ifdef LIBXML_PATTERN_ENABLED
3947 * xmlTextReaderPreservePattern:
3948 * @reader: the xmlTextReaderPtr used
3949 * @pattern: an XPath subset pattern
3950 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3952 * This tells the XML Reader to preserve all nodes matched by the
3953 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3954 * keep an handle on the resulting document once parsing has finished
3956 * Returns a positive number in case of success and -1 in case of error
3959 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3960 const xmlChar **namespaces)
3962 xmlPatternPtr comp;
3964 if ((reader == NULL) || (pattern == NULL))
3965 return(-1);
3967 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3968 if (comp == NULL)
3969 return(-1);
3971 if (reader->patternMax <= 0) {
3972 reader->patternMax = 4;
3973 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3974 sizeof(reader->patternTab[0]));
3975 if (reader->patternTab == NULL) {
3976 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3977 return (-1);
3980 if (reader->patternNr >= reader->patternMax) {
3981 xmlPatternPtr *tmp;
3982 reader->patternMax *= 2;
3983 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3984 reader->patternMax *
3985 sizeof(reader->patternTab[0]));
3986 if (tmp == NULL) {
3987 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3988 reader->patternMax /= 2;
3989 return (-1);
3991 reader->patternTab = tmp;
3993 reader->patternTab[reader->patternNr] = comp;
3994 return(reader->patternNr++);
3996 #endif
3999 * xmlTextReaderCurrentDoc:
4000 * @reader: the xmlTextReaderPtr used
4002 * Hacking interface allowing to get the xmlDocPtr correponding to the
4003 * current document being accessed by the xmlTextReader.
4004 * NOTE: as a result of this call, the reader will not destroy the
4005 * associated XML document and calling xmlFreeDoc() on the result
4006 * is needed once the reader parsing has finished.
4008 * Returns the xmlDocPtr or NULL in case of error.
4010 xmlDocPtr
4011 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4012 if (reader == NULL)
4013 return(NULL);
4014 if (reader->doc != NULL)
4015 return(reader->doc);
4016 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4017 return(NULL);
4019 reader->preserve = 1;
4020 return(reader->ctxt->myDoc);
4023 #ifdef LIBXML_SCHEMAS_ENABLED
4024 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
4026 static void XMLCDECL
4027 xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4029 static void XMLCDECL
4030 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4032 static void XMLCDECL
4033 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4035 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4037 char *str;
4039 va_list ap;
4041 va_start(ap, msg);
4042 str = xmlTextReaderBuildMessage(msg, ap);
4043 if (!reader->errorFunc) {
4044 xmlTextReaderValidityError(ctx, "%s", str);
4045 } else {
4046 reader->errorFunc(reader->errorFuncArg, str,
4047 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4048 NULL /* locator */ );
4050 if (str != NULL)
4051 xmlFree(str);
4052 va_end(ap);
4055 static void XMLCDECL
4056 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4058 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4060 char *str;
4062 va_list ap;
4064 va_start(ap, msg);
4065 str = xmlTextReaderBuildMessage(msg, ap);
4066 if (!reader->errorFunc) {
4067 xmlTextReaderValidityWarning(ctx, "%s", str);
4068 } else {
4069 reader->errorFunc(reader->errorFuncArg, str,
4070 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4071 NULL /* locator */ );
4073 if (str != NULL)
4074 xmlFree(str);
4075 va_end(ap);
4078 static void
4079 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4081 static void
4082 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4084 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4086 if (reader->sErrorFunc) {
4087 reader->sErrorFunc(reader->errorFuncArg, error);
4088 } else {
4089 xmlTextReaderStructuredError(reader, error);
4093 * xmlTextReaderRelaxNGSetSchema:
4094 * @reader: the xmlTextReaderPtr used
4095 * @schema: a precompiled RelaxNG schema
4097 * Use RelaxNG to validate the document as it is processed.
4098 * Activation is only possible before the first Read().
4099 * if @schema is NULL, then RelaxNG validation is desactivated.
4100 @ The @schema should not be freed until the reader is deallocated
4101 * or its use has been deactivated.
4103 * Returns 0 in case the RelaxNG validation could be (des)activated and
4104 * -1 in case of error.
4107 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4108 if (reader == NULL)
4109 return(-1);
4110 if (schema == NULL) {
4111 if (reader->rngSchemas != NULL) {
4112 xmlRelaxNGFree(reader->rngSchemas);
4113 reader->rngSchemas = NULL;
4115 if (reader->rngValidCtxt != NULL) {
4116 if (! reader->rngPreserveCtxt)
4117 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4118 reader->rngValidCtxt = NULL;
4120 reader->rngPreserveCtxt = 0;
4121 return(0);
4123 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4124 return(-1);
4125 if (reader->rngSchemas != NULL) {
4126 xmlRelaxNGFree(reader->rngSchemas);
4127 reader->rngSchemas = NULL;
4129 if (reader->rngValidCtxt != NULL) {
4130 if (! reader->rngPreserveCtxt)
4131 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4132 reader->rngValidCtxt = NULL;
4134 reader->rngPreserveCtxt = 0;
4135 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4136 if (reader->rngValidCtxt == NULL)
4137 return(-1);
4138 if (reader->errorFunc != NULL) {
4139 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4140 xmlTextReaderValidityErrorRelay,
4141 xmlTextReaderValidityWarningRelay,
4142 reader);
4144 if (reader->sErrorFunc != NULL) {
4145 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4146 xmlTextReaderValidityStructuredRelay,
4147 reader);
4149 reader->rngValidErrors = 0;
4150 reader->rngFullNode = NULL;
4151 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4152 return(0);
4156 * xmlTextReaderLocator:
4157 * @ctx: the xmlTextReaderPtr used
4158 * @file: returned file information
4159 * @line: returned line information
4161 * Internal locator function for the readers
4163 * Returns 0 in case the Schema validation could be (des)activated and
4164 * -1 in case of error.
4166 static int
4167 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4168 xmlTextReaderPtr reader;
4170 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4171 return(-1);
4173 if (file != NULL)
4174 *file = NULL;
4175 if (line != NULL)
4176 *line = 0;
4178 reader = (xmlTextReaderPtr) ctx;
4179 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4180 if (file != NULL)
4181 *file = reader->ctxt->input->filename;
4182 if (line != NULL)
4183 *line = reader->ctxt->input->line;
4184 return(0);
4186 if (reader->node != NULL) {
4187 long res;
4188 int ret = 0;
4190 if (line != NULL) {
4191 res = xmlGetLineNo(reader->node);
4192 if (res > 0)
4193 *line = (unsigned long) res;
4194 else
4195 ret = -1;
4197 if (file != NULL) {
4198 xmlDocPtr doc = reader->node->doc;
4199 if ((doc != NULL) && (doc->URL != NULL))
4200 *file = (const char *) doc->URL;
4201 else
4202 ret = -1;
4204 return(ret);
4206 return(-1);
4210 * xmlTextReaderSetSchema:
4211 * @reader: the xmlTextReaderPtr used
4212 * @schema: a precompiled Schema schema
4214 * Use XSD Schema to validate the document as it is processed.
4215 * Activation is only possible before the first Read().
4216 * if @schema is NULL, then Schema validation is desactivated.
4217 @ The @schema should not be freed until the reader is deallocated
4218 * or its use has been deactivated.
4220 * Returns 0 in case the Schema validation could be (des)activated and
4221 * -1 in case of error.
4224 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4225 if (reader == NULL)
4226 return(-1);
4227 if (schema == NULL) {
4228 if (reader->xsdPlug != NULL) {
4229 xmlSchemaSAXUnplug(reader->xsdPlug);
4230 reader->xsdPlug = NULL;
4232 if (reader->xsdValidCtxt != NULL) {
4233 if (! reader->xsdPreserveCtxt)
4234 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4235 reader->xsdValidCtxt = NULL;
4237 reader->xsdPreserveCtxt = 0;
4238 if (reader->xsdSchemas != NULL) {
4239 xmlSchemaFree(reader->xsdSchemas);
4240 reader->xsdSchemas = NULL;
4242 return(0);
4244 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4245 return(-1);
4246 if (reader->xsdPlug != NULL) {
4247 xmlSchemaSAXUnplug(reader->xsdPlug);
4248 reader->xsdPlug = NULL;
4250 if (reader->xsdValidCtxt != NULL) {
4251 if (! reader->xsdPreserveCtxt)
4252 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4253 reader->xsdValidCtxt = NULL;
4255 reader->xsdPreserveCtxt = 0;
4256 if (reader->xsdSchemas != NULL) {
4257 xmlSchemaFree(reader->xsdSchemas);
4258 reader->xsdSchemas = NULL;
4260 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4261 if (reader->xsdValidCtxt == NULL) {
4262 xmlSchemaFree(reader->xsdSchemas);
4263 reader->xsdSchemas = NULL;
4264 return(-1);
4266 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4267 &(reader->ctxt->sax),
4268 &(reader->ctxt->userData));
4269 if (reader->xsdPlug == NULL) {
4270 xmlSchemaFree(reader->xsdSchemas);
4271 reader->xsdSchemas = NULL;
4272 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4273 reader->xsdValidCtxt = NULL;
4274 return(-1);
4276 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4277 xmlTextReaderLocator,
4278 (void *) reader);
4280 if (reader->errorFunc != NULL) {
4281 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4282 xmlTextReaderValidityErrorRelay,
4283 xmlTextReaderValidityWarningRelay,
4284 reader);
4286 if (reader->sErrorFunc != NULL) {
4287 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4288 xmlTextReaderValidityStructuredRelay,
4289 reader);
4291 reader->xsdValidErrors = 0;
4292 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4293 return(0);
4297 * xmlTextReaderRelaxNGValidateInternal:
4298 * @reader: the xmlTextReaderPtr used
4299 * @rng: the path to a RelaxNG schema or NULL
4300 * @ctxt: the RelaxNG schema validation context or NULL
4301 * @options: options (not yet used)
4303 * Use RelaxNG to validate the document as it is processed.
4304 * Activation is only possible before the first Read().
4305 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4307 * Returns 0 in case the RelaxNG validation could be (de)activated and
4308 * -1 in case of error.
4310 static int
4311 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4312 const char *rng,
4313 xmlRelaxNGValidCtxtPtr ctxt,
4314 int options ATTRIBUTE_UNUSED)
4316 if (reader == NULL)
4317 return(-1);
4319 if ((rng != NULL) && (ctxt != NULL))
4320 return (-1);
4322 if (((rng != NULL) || (ctxt != NULL)) &&
4323 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4324 (reader->ctxt == NULL)))
4325 return(-1);
4327 /* Cleanup previous validation stuff. */
4328 if (reader->rngValidCtxt != NULL) {
4329 if ( !reader->rngPreserveCtxt)
4330 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4331 reader->rngValidCtxt = NULL;
4333 reader->rngPreserveCtxt = 0;
4334 if (reader->rngSchemas != NULL) {
4335 xmlRelaxNGFree(reader->rngSchemas);
4336 reader->rngSchemas = NULL;
4339 if ((rng == NULL) && (ctxt == NULL)) {
4340 /* We just want to deactivate the validation, so get out. */
4341 return(0);
4345 if (rng != NULL) {
4346 xmlRelaxNGParserCtxtPtr pctxt;
4347 /* Parse the schema and create validation environment. */
4349 pctxt = xmlRelaxNGNewParserCtxt(rng);
4350 if (reader->errorFunc != NULL) {
4351 xmlRelaxNGSetParserErrors(pctxt,
4352 xmlTextReaderValidityErrorRelay,
4353 xmlTextReaderValidityWarningRelay,
4354 reader);
4356 if (reader->sErrorFunc != NULL) {
4357 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4358 xmlTextReaderValidityStructuredRelay,
4359 reader);
4361 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4362 xmlRelaxNGFreeParserCtxt(pctxt);
4363 if (reader->rngSchemas == NULL)
4364 return(-1);
4365 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4366 if (reader->rngValidCtxt == NULL) {
4367 xmlRelaxNGFree(reader->rngSchemas);
4368 reader->rngSchemas = NULL;
4369 return(-1);
4371 } else {
4372 /* Use the given validation context. */
4373 reader->rngValidCtxt = ctxt;
4374 reader->rngPreserveCtxt = 1;
4377 * Redirect the validation context's error channels to use
4378 * the reader channels.
4379 * TODO: In case the user provides the validation context we
4380 * could make this redirection optional.
4382 if (reader->errorFunc != NULL) {
4383 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4384 xmlTextReaderValidityErrorRelay,
4385 xmlTextReaderValidityWarningRelay,
4386 reader);
4388 if (reader->sErrorFunc != NULL) {
4389 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4390 xmlTextReaderValidityStructuredRelay,
4391 reader);
4393 reader->rngValidErrors = 0;
4394 reader->rngFullNode = NULL;
4395 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4396 return(0);
4400 * xmlTextReaderSchemaValidateInternal:
4401 * @reader: the xmlTextReaderPtr used
4402 * @xsd: the path to a W3C XSD schema or NULL
4403 * @ctxt: the XML Schema validation context or NULL
4404 * @options: options (not used yet)
4406 * Validate the document as it is processed using XML Schema.
4407 * Activation is only possible before the first Read().
4408 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4410 * Returns 0 in case the schemas validation could be (de)activated and
4411 * -1 in case of error.
4413 static int
4414 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4415 const char *xsd,
4416 xmlSchemaValidCtxtPtr ctxt,
4417 int options ATTRIBUTE_UNUSED)
4419 if (reader == NULL)
4420 return(-1);
4422 if ((xsd != NULL) && (ctxt != NULL))
4423 return(-1);
4425 if (((xsd != NULL) || (ctxt != NULL)) &&
4426 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4427 (reader->ctxt == NULL)))
4428 return(-1);
4430 /* Cleanup previous validation stuff. */
4431 if (reader->xsdPlug != NULL) {
4432 xmlSchemaSAXUnplug(reader->xsdPlug);
4433 reader->xsdPlug = NULL;
4435 if (reader->xsdValidCtxt != NULL) {
4436 if (! reader->xsdPreserveCtxt)
4437 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4438 reader->xsdValidCtxt = NULL;
4440 reader->xsdPreserveCtxt = 0;
4441 if (reader->xsdSchemas != NULL) {
4442 xmlSchemaFree(reader->xsdSchemas);
4443 reader->xsdSchemas = NULL;
4446 if ((xsd == NULL) && (ctxt == NULL)) {
4447 /* We just want to deactivate the validation, so get out. */
4448 return(0);
4451 if (xsd != NULL) {
4452 xmlSchemaParserCtxtPtr pctxt;
4453 /* Parse the schema and create validation environment. */
4454 pctxt = xmlSchemaNewParserCtxt(xsd);
4455 if (reader->errorFunc != NULL) {
4456 xmlSchemaSetParserErrors(pctxt,
4457 xmlTextReaderValidityErrorRelay,
4458 xmlTextReaderValidityWarningRelay,
4459 reader);
4461 reader->xsdSchemas = xmlSchemaParse(pctxt);
4462 xmlSchemaFreeParserCtxt(pctxt);
4463 if (reader->xsdSchemas == NULL)
4464 return(-1);
4465 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4466 if (reader->xsdValidCtxt == NULL) {
4467 xmlSchemaFree(reader->xsdSchemas);
4468 reader->xsdSchemas = NULL;
4469 return(-1);
4471 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4472 &(reader->ctxt->sax),
4473 &(reader->ctxt->userData));
4474 if (reader->xsdPlug == NULL) {
4475 xmlSchemaFree(reader->xsdSchemas);
4476 reader->xsdSchemas = NULL;
4477 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4478 reader->xsdValidCtxt = NULL;
4479 return(-1);
4481 } else {
4482 /* Use the given validation context. */
4483 reader->xsdValidCtxt = ctxt;
4484 reader->xsdPreserveCtxt = 1;
4485 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4486 &(reader->ctxt->sax),
4487 &(reader->ctxt->userData));
4488 if (reader->xsdPlug == NULL) {
4489 reader->xsdValidCtxt = NULL;
4490 reader->xsdPreserveCtxt = 0;
4491 return(-1);
4494 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4495 xmlTextReaderLocator,
4496 (void *) reader);
4498 * Redirect the validation context's error channels to use
4499 * the reader channels.
4500 * TODO: In case the user provides the validation context we
4501 * could make this redirection optional.
4503 if (reader->errorFunc != NULL) {
4504 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4505 xmlTextReaderValidityErrorRelay,
4506 xmlTextReaderValidityWarningRelay,
4507 reader);
4509 if (reader->sErrorFunc != NULL) {
4510 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4511 xmlTextReaderValidityStructuredRelay,
4512 reader);
4514 reader->xsdValidErrors = 0;
4515 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4516 return(0);
4520 * xmlTextReaderSchemaValidateCtxt:
4521 * @reader: the xmlTextReaderPtr used
4522 * @ctxt: the XML Schema validation context or NULL
4523 * @options: options (not used yet)
4525 * Use W3C XSD schema context to validate the document as it is processed.
4526 * Activation is only possible before the first Read().
4527 * If @ctxt is NULL, then XML Schema validation is deactivated.
4529 * Returns 0 in case the schemas validation could be (de)activated and
4530 * -1 in case of error.
4533 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4534 xmlSchemaValidCtxtPtr ctxt,
4535 int options)
4537 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4541 * xmlTextReaderSchemaValidate:
4542 * @reader: the xmlTextReaderPtr used
4543 * @xsd: the path to a W3C XSD schema or NULL
4545 * Use W3C XSD schema to validate the document as it is processed.
4546 * Activation is only possible before the first Read().
4547 * If @xsd is NULL, then XML Schema validation is deactivated.
4549 * Returns 0 in case the schemas validation could be (de)activated and
4550 * -1 in case of error.
4553 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4555 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4559 * xmlTextReaderRelaxNGValidateCtxt:
4560 * @reader: the xmlTextReaderPtr used
4561 * @ctxt: the RelaxNG schema validation context or NULL
4562 * @options: options (not used yet)
4564 * Use RelaxNG schema context to validate the document as it is processed.
4565 * Activation is only possible before the first Read().
4566 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4568 * Returns 0 in case the schemas validation could be (de)activated and
4569 * -1 in case of error.
4572 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4573 xmlRelaxNGValidCtxtPtr ctxt,
4574 int options)
4576 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4580 * xmlTextReaderRelaxNGValidate:
4581 * @reader: the xmlTextReaderPtr used
4582 * @rng: the path to a RelaxNG schema or NULL
4584 * Use RelaxNG schema to validate the document as it is processed.
4585 * Activation is only possible before the first Read().
4586 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4588 * Returns 0 in case the schemas validation could be (de)activated and
4589 * -1 in case of error.
4592 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4594 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4597 #endif
4600 * xmlTextReaderIsNamespaceDecl:
4601 * @reader: the xmlTextReaderPtr used
4603 * Determine whether the current node is a namespace declaration
4604 * rather than a regular attribute.
4606 * Returns 1 if the current node is a namespace declaration, 0 if it
4607 * is a regular attribute or other type of node, or -1 in case of
4608 * error.
4611 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4612 xmlNodePtr node;
4613 if (reader == NULL)
4614 return(-1);
4615 if (reader->node == NULL)
4616 return(-1);
4617 if (reader->curnode != NULL)
4618 node = reader->curnode;
4619 else
4620 node = reader->node;
4622 if (XML_NAMESPACE_DECL == node->type)
4623 return(1);
4624 else
4625 return(0);
4629 * xmlTextReaderConstXmlVersion:
4630 * @reader: the xmlTextReaderPtr used
4632 * Determine the XML version of the document being read.
4634 * Returns a string containing the XML version of the document or NULL
4635 * in case of error. The string is deallocated with the reader.
4637 const xmlChar *
4638 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4639 xmlDocPtr doc = NULL;
4640 if (reader == NULL)
4641 return(NULL);
4642 if (reader->doc != NULL)
4643 doc = reader->doc;
4644 else if (reader->ctxt != NULL)
4645 doc = reader->ctxt->myDoc;
4646 if (doc == NULL)
4647 return(NULL);
4649 if (doc->version == NULL)
4650 return(NULL);
4651 else
4652 return(CONSTSTR(doc->version));
4656 * xmlTextReaderStandalone:
4657 * @reader: the xmlTextReaderPtr used
4659 * Determine the standalone status of the document being read.
4661 * Returns 1 if the document was declared to be standalone, 0 if it
4662 * was declared to be not standalone, or -1 if the document did not
4663 * specify its standalone status or in case of error.
4666 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4667 xmlDocPtr doc = NULL;
4668 if (reader == NULL)
4669 return(-1);
4670 if (reader->doc != NULL)
4671 doc = reader->doc;
4672 else if (reader->ctxt != NULL)
4673 doc = reader->ctxt->myDoc;
4674 if (doc == NULL)
4675 return(-1);
4677 return(doc->standalone);
4680 /************************************************************************
4682 * Error Handling Extensions *
4684 ************************************************************************/
4686 /* helper to build a xmlMalloc'ed string from a format and va_list */
4687 static char *
4688 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4689 int size = 0;
4690 int chars;
4691 char *larger;
4692 char *str = NULL;
4693 va_list aq;
4695 while (1) {
4696 VA_COPY(aq, ap);
4697 chars = vsnprintf(str, size, msg, aq);
4698 va_end(aq);
4699 if (chars < 0) {
4700 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4701 if (str)
4702 xmlFree(str);
4703 return NULL;
4705 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4706 break;
4707 if (chars < MAX_ERR_MSG_SIZE)
4708 size = chars + 1;
4709 else
4710 size = MAX_ERR_MSG_SIZE;
4711 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4712 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4713 if (str)
4714 xmlFree(str);
4715 return NULL;
4717 str = larger;
4720 return str;
4724 * xmlTextReaderLocatorLineNumber:
4725 * @locator: the xmlTextReaderLocatorPtr used
4727 * Obtain the line number for the given locator.
4729 * Returns the line number or -1 in case of error.
4732 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4733 /* we know that locator is a xmlParserCtxtPtr */
4734 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4735 int ret = -1;
4737 if (locator == NULL)
4738 return(-1);
4739 if (ctx->node != NULL) {
4740 ret = xmlGetLineNo(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 = input->line;
4751 else {
4752 ret = -1;
4756 return ret;
4760 * xmlTextReaderLocatorBaseURI:
4761 * @locator: the xmlTextReaderLocatorPtr used
4763 * Obtain the base URI for the given locator.
4765 * Returns the base URI or NULL in case of error,
4766 * if non NULL it need to be freed by the caller.
4768 xmlChar *
4769 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4770 /* we know that locator is a xmlParserCtxtPtr */
4771 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4772 xmlChar *ret = NULL;
4774 if (locator == NULL)
4775 return(NULL);
4776 if (ctx->node != NULL) {
4777 ret = xmlNodeGetBase(NULL,ctx->node);
4779 else {
4780 /* inspired from error.c */
4781 xmlParserInputPtr input;
4782 input = ctx->input;
4783 if ((input->filename == NULL) && (ctx->inputNr > 1))
4784 input = ctx->inputTab[ctx->inputNr - 2];
4785 if (input != NULL) {
4786 ret = xmlStrdup(BAD_CAST input->filename);
4788 else {
4789 ret = NULL;
4793 return ret;
4796 static void
4797 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4798 char *str)
4800 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4802 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4804 if (str != NULL) {
4805 if (reader->errorFunc)
4806 reader->errorFunc(reader->errorFuncArg, str, severity,
4807 (xmlTextReaderLocatorPtr) ctx);
4808 xmlFree(str);
4812 static void
4813 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4815 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4817 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4819 if (error && reader->sErrorFunc) {
4820 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4824 static void XMLCDECL
4825 xmlTextReaderError(void *ctxt, const char *msg, ...)
4827 va_list ap;
4829 va_start(ap, msg);
4830 xmlTextReaderGenericError(ctxt,
4831 XML_PARSER_SEVERITY_ERROR,
4832 xmlTextReaderBuildMessage(msg, ap));
4833 va_end(ap);
4837 static void XMLCDECL
4838 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4840 va_list ap;
4842 va_start(ap, msg);
4843 xmlTextReaderGenericError(ctxt,
4844 XML_PARSER_SEVERITY_WARNING,
4845 xmlTextReaderBuildMessage(msg, ap));
4846 va_end(ap);
4849 static void XMLCDECL
4850 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4852 va_list ap;
4854 int len = xmlStrlen((const xmlChar *) msg);
4856 if ((len > 1) && (msg[len - 2] != ':')) {
4858 * some callbacks only report locator information:
4859 * skip them (mimicking behaviour in error.c)
4861 va_start(ap, msg);
4862 xmlTextReaderGenericError(ctxt,
4863 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4864 xmlTextReaderBuildMessage(msg, ap));
4865 va_end(ap);
4869 static void XMLCDECL
4870 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4872 va_list ap;
4874 int len = xmlStrlen((const xmlChar *) msg);
4876 if ((len != 0) && (msg[len - 1] != ':')) {
4878 * some callbacks only report locator information:
4879 * skip them (mimicking behaviour in error.c)
4881 va_start(ap, msg);
4882 xmlTextReaderGenericError(ctxt,
4883 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4884 xmlTextReaderBuildMessage(msg, ap));
4885 va_end(ap);
4890 * xmlTextReaderSetErrorHandler:
4891 * @reader: the xmlTextReaderPtr used
4892 * @f: the callback function to call on error and warnings
4893 * @arg: a user argument to pass to the callback function
4895 * Register a callback function that will be called on error and warnings.
4897 * If @f is NULL, the default error and warning handlers are restored.
4899 void
4900 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4901 xmlTextReaderErrorFunc f, void *arg)
4903 if (f != NULL) {
4904 reader->ctxt->sax->error = xmlTextReaderError;
4905 reader->ctxt->sax->serror = NULL;
4906 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4907 reader->ctxt->sax->warning = xmlTextReaderWarning;
4908 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4909 reader->errorFunc = f;
4910 reader->sErrorFunc = NULL;
4911 reader->errorFuncArg = arg;
4912 #ifdef LIBXML_SCHEMAS_ENABLED
4913 if (reader->rngValidCtxt) {
4914 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4915 xmlTextReaderValidityErrorRelay,
4916 xmlTextReaderValidityWarningRelay,
4917 reader);
4918 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4919 reader);
4921 if (reader->xsdValidCtxt) {
4922 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4923 xmlTextReaderValidityErrorRelay,
4924 xmlTextReaderValidityWarningRelay,
4925 reader);
4926 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4927 reader);
4929 #endif
4930 } else {
4931 /* restore defaults */
4932 reader->ctxt->sax->error = xmlParserError;
4933 reader->ctxt->vctxt.error = xmlParserValidityError;
4934 reader->ctxt->sax->warning = xmlParserWarning;
4935 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4936 reader->errorFunc = NULL;
4937 reader->sErrorFunc = NULL;
4938 reader->errorFuncArg = NULL;
4939 #ifdef LIBXML_SCHEMAS_ENABLED
4940 if (reader->rngValidCtxt) {
4941 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4942 reader);
4943 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4944 reader);
4946 if (reader->xsdValidCtxt) {
4947 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4948 reader);
4949 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4950 reader);
4952 #endif
4957 * xmlTextReaderSetStructuredErrorHandler:
4958 * @reader: the xmlTextReaderPtr used
4959 * @f: the callback function to call on error and warnings
4960 * @arg: a user argument to pass to the callback function
4962 * Register a callback function that will be called on error and warnings.
4964 * If @f is NULL, the default error and warning handlers are restored.
4966 void
4967 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4968 xmlStructuredErrorFunc f, void *arg)
4970 if (f != NULL) {
4971 reader->ctxt->sax->error = NULL;
4972 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4973 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4974 reader->ctxt->sax->warning = xmlTextReaderWarning;
4975 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4976 reader->sErrorFunc = f;
4977 reader->errorFunc = NULL;
4978 reader->errorFuncArg = arg;
4979 #ifdef LIBXML_SCHEMAS_ENABLED
4980 if (reader->rngValidCtxt) {
4981 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4982 reader);
4983 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4984 xmlTextReaderValidityStructuredRelay,
4985 reader);
4987 if (reader->xsdValidCtxt) {
4988 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4989 reader);
4990 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4991 xmlTextReaderValidityStructuredRelay,
4992 reader);
4994 #endif
4995 } else {
4996 /* restore defaults */
4997 reader->ctxt->sax->error = xmlParserError;
4998 reader->ctxt->sax->serror = NULL;
4999 reader->ctxt->vctxt.error = xmlParserValidityError;
5000 reader->ctxt->sax->warning = xmlParserWarning;
5001 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5002 reader->errorFunc = NULL;
5003 reader->sErrorFunc = NULL;
5004 reader->errorFuncArg = NULL;
5005 #ifdef LIBXML_SCHEMAS_ENABLED
5006 if (reader->rngValidCtxt) {
5007 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5008 reader);
5009 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5010 reader);
5012 if (reader->xsdValidCtxt) {
5013 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5014 reader);
5015 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5016 reader);
5018 #endif
5023 * xmlTextReaderIsValid:
5024 * @reader: the xmlTextReaderPtr used
5026 * Retrieve the validity status from the parser context
5028 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5031 xmlTextReaderIsValid(xmlTextReaderPtr reader)
5033 if (reader == NULL)
5034 return (-1);
5035 #ifdef LIBXML_SCHEMAS_ENABLED
5036 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5037 return (reader->rngValidErrors == 0);
5038 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5039 return (reader->xsdValidErrors == 0);
5040 #endif
5041 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5042 return (reader->ctxt->valid);
5043 return (0);
5047 * xmlTextReaderGetErrorHandler:
5048 * @reader: the xmlTextReaderPtr used
5049 * @f: the callback function or NULL is no callback has been registered
5050 * @arg: a user argument
5052 * Retrieve the error callback function and user argument.
5054 void
5055 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5056 xmlTextReaderErrorFunc * f, void **arg)
5058 if (f != NULL)
5059 *f = reader->errorFunc;
5060 if (arg != NULL)
5061 *arg = reader->errorFuncArg;
5063 /************************************************************************
5065 * New set (2.6.0) of simpler and more flexible APIs *
5067 ************************************************************************/
5070 * xmlTextReaderSetup:
5071 * @reader: an XML reader
5072 * @input: xmlParserInputBufferPtr used to feed the reader, will
5073 * be destroyed with it.
5074 * @URL: the base URL to use for the document
5075 * @encoding: the document encoding, or NULL
5076 * @options: a combination of xmlParserOption
5078 * Setup an XML reader with new options
5080 * Returns 0 in case of success and -1 in case of error.
5083 xmlTextReaderSetup(xmlTextReaderPtr reader,
5084 xmlParserInputBufferPtr input, const char *URL,
5085 const char *encoding, int options)
5087 if (reader == NULL) {
5088 if (input != NULL)
5089 xmlFreeParserInputBuffer(input);
5090 return (-1);
5094 * we force the generation of compact text nodes on the reader
5095 * since usr applications should never modify the tree
5097 options |= XML_PARSE_COMPACT;
5099 reader->doc = NULL;
5100 reader->entNr = 0;
5101 reader->parserFlags = options;
5102 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5103 if ((input != NULL) && (reader->input != NULL) &&
5104 (reader->allocs & XML_TEXTREADER_INPUT)) {
5105 xmlFreeParserInputBuffer(reader->input);
5106 reader->input = NULL;
5107 reader->allocs -= XML_TEXTREADER_INPUT;
5109 if (input != NULL) {
5110 reader->input = input;
5111 reader->allocs |= XML_TEXTREADER_INPUT;
5113 if (reader->buffer == NULL)
5114 reader->buffer = xmlBufCreateSize(100);
5115 if (reader->buffer == NULL) {
5116 xmlGenericError(xmlGenericErrorContext,
5117 "xmlTextReaderSetup : malloc failed\n");
5118 return (-1);
5120 if (reader->sax == NULL)
5121 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5122 if (reader->sax == NULL) {
5123 xmlGenericError(xmlGenericErrorContext,
5124 "xmlTextReaderSetup : malloc failed\n");
5125 return (-1);
5127 xmlSAXVersion(reader->sax, 2);
5128 reader->startElement = reader->sax->startElement;
5129 reader->sax->startElement = xmlTextReaderStartElement;
5130 reader->endElement = reader->sax->endElement;
5131 reader->sax->endElement = xmlTextReaderEndElement;
5132 #ifdef LIBXML_SAX1_ENABLED
5133 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5134 #endif /* LIBXML_SAX1_ENABLED */
5135 reader->startElementNs = reader->sax->startElementNs;
5136 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5137 reader->endElementNs = reader->sax->endElementNs;
5138 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5139 #ifdef LIBXML_SAX1_ENABLED
5140 } else {
5141 reader->startElementNs = NULL;
5142 reader->endElementNs = NULL;
5144 #endif /* LIBXML_SAX1_ENABLED */
5145 reader->characters = reader->sax->characters;
5146 reader->sax->characters = xmlTextReaderCharacters;
5147 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5148 reader->cdataBlock = reader->sax->cdataBlock;
5149 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5151 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5152 reader->node = NULL;
5153 reader->curnode = NULL;
5154 if (input != NULL) {
5155 if (xmlBufUse(reader->input->buffer) < 4) {
5156 xmlParserInputBufferRead(input, 4);
5158 if (reader->ctxt == NULL) {
5159 if (xmlBufUse(reader->input->buffer) >= 4) {
5160 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5161 (const char *) xmlBufContent(reader->input->buffer),
5162 4, URL);
5163 reader->base = 0;
5164 reader->cur = 4;
5165 } else {
5166 reader->ctxt =
5167 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5168 reader->base = 0;
5169 reader->cur = 0;
5171 } else {
5172 xmlParserInputPtr inputStream;
5173 xmlParserInputBufferPtr buf;
5174 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5176 xmlCtxtReset(reader->ctxt);
5177 buf = xmlAllocParserInputBuffer(enc);
5178 if (buf == NULL) return(-1);
5179 inputStream = xmlNewInputStream(reader->ctxt);
5180 if (inputStream == NULL) {
5181 xmlFreeParserInputBuffer(buf);
5182 return(-1);
5185 if (URL == NULL)
5186 inputStream->filename = NULL;
5187 else
5188 inputStream->filename = (char *)
5189 xmlCanonicPath((const xmlChar *) URL);
5190 inputStream->buf = buf;
5191 xmlBufResetInput(buf->buffer, inputStream);
5193 inputPush(reader->ctxt, inputStream);
5194 reader->cur = 0;
5196 if (reader->ctxt == NULL) {
5197 xmlGenericError(xmlGenericErrorContext,
5198 "xmlTextReaderSetup : malloc failed\n");
5199 return (-1);
5202 if (reader->dict != NULL) {
5203 if (reader->ctxt->dict != NULL) {
5204 if (reader->dict != reader->ctxt->dict) {
5205 xmlDictFree(reader->dict);
5206 reader->dict = reader->ctxt->dict;
5208 } else {
5209 reader->ctxt->dict = reader->dict;
5211 } else {
5212 if (reader->ctxt->dict == NULL)
5213 reader->ctxt->dict = xmlDictCreate();
5214 reader->dict = reader->ctxt->dict;
5216 reader->ctxt->_private = reader;
5217 reader->ctxt->linenumbers = 1;
5218 reader->ctxt->dictNames = 1;
5220 * use the parser dictionnary to allocate all elements and attributes names
5222 reader->ctxt->docdict = 1;
5223 reader->ctxt->parseMode = XML_PARSE_READER;
5225 #ifdef LIBXML_XINCLUDE_ENABLED
5226 if (reader->xincctxt != NULL) {
5227 xmlXIncludeFreeContext(reader->xincctxt);
5228 reader->xincctxt = NULL;
5230 if (options & XML_PARSE_XINCLUDE) {
5231 reader->xinclude = 1;
5232 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5233 options -= XML_PARSE_XINCLUDE;
5234 } else
5235 reader->xinclude = 0;
5236 reader->in_xinclude = 0;
5237 #endif
5238 #ifdef LIBXML_PATTERN_ENABLED
5239 if (reader->patternTab == NULL) {
5240 reader->patternNr = 0;
5241 reader->patternMax = 0;
5243 while (reader->patternNr > 0) {
5244 reader->patternNr--;
5245 if (reader->patternTab[reader->patternNr] != NULL) {
5246 xmlFreePattern(reader->patternTab[reader->patternNr]);
5247 reader->patternTab[reader->patternNr] = NULL;
5250 #endif
5252 if (options & XML_PARSE_DTDVALID)
5253 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5255 xmlCtxtUseOptions(reader->ctxt, options);
5256 if (encoding != NULL) {
5257 xmlCharEncodingHandlerPtr hdlr;
5259 hdlr = xmlFindCharEncodingHandler(encoding);
5260 if (hdlr != NULL)
5261 xmlSwitchToEncoding(reader->ctxt, hdlr);
5263 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5264 (reader->ctxt->input->filename == NULL))
5265 reader->ctxt->input->filename = (char *)
5266 xmlStrdup((const xmlChar *) URL);
5268 reader->doc = NULL;
5270 return (0);
5274 * xmlTextReaderByteConsumed:
5275 * @reader: an XML reader
5277 * This function provides the current index of the parser used
5278 * by the reader, relative to the start of the current entity.
5279 * This function actually just wraps a call to xmlBytesConsumed()
5280 * for the parser context associated with the reader.
5281 * See xmlBytesConsumed() for more information.
5283 * Returns the index in bytes from the beginning of the entity or -1
5284 * in case the index could not be computed.
5286 long
5287 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5288 if ((reader == NULL) || (reader->ctxt == NULL))
5289 return(-1);
5290 return(xmlByteConsumed(reader->ctxt));
5295 * xmlReaderWalker:
5296 * @doc: a preparsed document
5298 * Create an xmltextReader for a preparsed document.
5300 * Returns the new reader or NULL in case of error.
5302 xmlTextReaderPtr
5303 xmlReaderWalker(xmlDocPtr doc)
5305 xmlTextReaderPtr ret;
5307 if (doc == NULL)
5308 return(NULL);
5310 ret = xmlMalloc(sizeof(xmlTextReader));
5311 if (ret == NULL) {
5312 xmlGenericError(xmlGenericErrorContext,
5313 "xmlNewTextReader : malloc failed\n");
5314 return(NULL);
5316 memset(ret, 0, sizeof(xmlTextReader));
5317 ret->entNr = 0;
5318 ret->input = NULL;
5319 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5320 ret->node = NULL;
5321 ret->curnode = NULL;
5322 ret->base = 0;
5323 ret->cur = 0;
5324 ret->allocs = XML_TEXTREADER_CTXT;
5325 ret->doc = doc;
5326 ret->state = XML_TEXTREADER_START;
5327 ret->dict = xmlDictCreate();
5328 return(ret);
5332 * xmlReaderForDoc:
5333 * @cur: a pointer to a zero terminated string
5334 * @URL: the base URL to use for the document
5335 * @encoding: the document encoding, or NULL
5336 * @options: a combination of xmlParserOption
5338 * Create an xmltextReader for an XML in-memory document.
5339 * The parsing flags @options are a combination of xmlParserOption.
5341 * Returns the new reader or NULL in case of error.
5343 xmlTextReaderPtr
5344 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5345 int options)
5347 int len;
5349 if (cur == NULL)
5350 return (NULL);
5351 len = xmlStrlen(cur);
5353 return (xmlReaderForMemory
5354 ((const char *) cur, len, URL, encoding, options));
5358 * xmlReaderForFile:
5359 * @filename: a file or URL
5360 * @encoding: the document encoding, or NULL
5361 * @options: a combination of xmlParserOption
5363 * parse an XML file from the filesystem or the network.
5364 * The parsing flags @options are a combination of xmlParserOption.
5366 * Returns the new reader or NULL in case of error.
5368 xmlTextReaderPtr
5369 xmlReaderForFile(const char *filename, const char *encoding, int options)
5371 xmlTextReaderPtr reader;
5373 reader = xmlNewTextReaderFilename(filename);
5374 if (reader == NULL)
5375 return (NULL);
5376 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5377 return (reader);
5381 * xmlReaderForMemory:
5382 * @buffer: a pointer to a char array
5383 * @size: the size of the array
5384 * @URL: the base URL to use for the document
5385 * @encoding: the document encoding, or NULL
5386 * @options: a combination of xmlParserOption
5388 * Create an xmltextReader for an XML in-memory document.
5389 * The parsing flags @options are a combination of xmlParserOption.
5391 * Returns the new reader or NULL in case of error.
5393 xmlTextReaderPtr
5394 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5395 const char *encoding, int options)
5397 xmlTextReaderPtr reader;
5398 xmlParserInputBufferPtr buf;
5400 buf = xmlParserInputBufferCreateStatic(buffer, size,
5401 XML_CHAR_ENCODING_NONE);
5402 if (buf == NULL) {
5403 return (NULL);
5405 reader = xmlNewTextReader(buf, URL);
5406 if (reader == NULL) {
5407 xmlFreeParserInputBuffer(buf);
5408 return (NULL);
5410 reader->allocs |= XML_TEXTREADER_INPUT;
5411 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5412 return (reader);
5416 * xmlReaderForFd:
5417 * @fd: an open file descriptor
5418 * @URL: the base URL to use for the document
5419 * @encoding: the document encoding, or NULL
5420 * @options: a combination of xmlParserOption
5422 * Create an xmltextReader for an XML from a file descriptor.
5423 * The parsing flags @options are a combination of xmlParserOption.
5424 * NOTE that the file descriptor will not be closed when the
5425 * reader is closed or reset.
5427 * Returns the new reader or NULL in case of error.
5429 xmlTextReaderPtr
5430 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5432 xmlTextReaderPtr reader;
5433 xmlParserInputBufferPtr input;
5435 if (fd < 0)
5436 return (NULL);
5438 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5439 if (input == NULL)
5440 return (NULL);
5441 input->closecallback = NULL;
5442 reader = xmlNewTextReader(input, URL);
5443 if (reader == NULL) {
5444 xmlFreeParserInputBuffer(input);
5445 return (NULL);
5447 reader->allocs |= XML_TEXTREADER_INPUT;
5448 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5449 return (reader);
5453 * xmlReaderForIO:
5454 * @ioread: an I/O read function
5455 * @ioclose: an I/O close function
5456 * @ioctx: an I/O handler
5457 * @URL: the base URL to use for the document
5458 * @encoding: the document encoding, or NULL
5459 * @options: a combination of xmlParserOption
5461 * Create an xmltextReader for an XML document from I/O functions and source.
5462 * The parsing flags @options are a combination of xmlParserOption.
5464 * Returns the new reader or NULL in case of error.
5466 xmlTextReaderPtr
5467 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5468 void *ioctx, const char *URL, const char *encoding,
5469 int options)
5471 xmlTextReaderPtr reader;
5472 xmlParserInputBufferPtr input;
5474 if (ioread == NULL)
5475 return (NULL);
5477 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5478 XML_CHAR_ENCODING_NONE);
5479 if (input == NULL) {
5480 if (ioclose != NULL)
5481 ioclose(ioctx);
5482 return (NULL);
5484 reader = xmlNewTextReader(input, URL);
5485 if (reader == NULL) {
5486 xmlFreeParserInputBuffer(input);
5487 return (NULL);
5489 reader->allocs |= XML_TEXTREADER_INPUT;
5490 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5491 return (reader);
5495 * xmlReaderNewWalker:
5496 * @reader: an XML reader
5497 * @doc: a preparsed document
5499 * Setup an xmltextReader to parse a preparsed XML document.
5500 * This reuses the existing @reader xmlTextReader.
5502 * Returns 0 in case of success and -1 in case of error
5505 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5507 if (doc == NULL)
5508 return (-1);
5509 if (reader == NULL)
5510 return (-1);
5512 if (reader->input != NULL) {
5513 xmlFreeParserInputBuffer(reader->input);
5515 if (reader->ctxt != NULL) {
5516 xmlCtxtReset(reader->ctxt);
5519 reader->entNr = 0;
5520 reader->input = NULL;
5521 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5522 reader->node = NULL;
5523 reader->curnode = NULL;
5524 reader->base = 0;
5525 reader->cur = 0;
5526 reader->allocs = XML_TEXTREADER_CTXT;
5527 reader->doc = doc;
5528 reader->state = XML_TEXTREADER_START;
5529 if (reader->dict == NULL) {
5530 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5531 reader->dict = reader->ctxt->dict;
5532 else
5533 reader->dict = xmlDictCreate();
5535 return(0);
5539 * xmlReaderNewDoc:
5540 * @reader: an XML reader
5541 * @cur: a pointer to a zero terminated string
5542 * @URL: the base URL to use for the document
5543 * @encoding: the document encoding, or NULL
5544 * @options: a combination of xmlParserOption
5546 * Setup an xmltextReader to parse an XML in-memory document.
5547 * The parsing flags @options are a combination of xmlParserOption.
5548 * This reuses the existing @reader xmlTextReader.
5550 * Returns 0 in case of success and -1 in case of error
5553 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5554 const char *URL, const char *encoding, int options)
5557 int len;
5559 if (cur == NULL)
5560 return (-1);
5561 if (reader == NULL)
5562 return (-1);
5564 len = xmlStrlen(cur);
5565 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5566 URL, encoding, options));
5570 * xmlReaderNewFile:
5571 * @reader: an XML reader
5572 * @filename: a file or URL
5573 * @encoding: the document encoding, or NULL
5574 * @options: a combination of xmlParserOption
5576 * parse an XML file from the filesystem or the network.
5577 * The parsing flags @options are a combination of xmlParserOption.
5578 * This reuses the existing @reader xmlTextReader.
5580 * Returns 0 in case of success and -1 in case of error
5583 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5584 const char *encoding, int options)
5586 xmlParserInputBufferPtr input;
5588 if (filename == NULL)
5589 return (-1);
5590 if (reader == NULL)
5591 return (-1);
5593 input =
5594 xmlParserInputBufferCreateFilename(filename,
5595 XML_CHAR_ENCODING_NONE);
5596 if (input == NULL)
5597 return (-1);
5598 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5602 * xmlReaderNewMemory:
5603 * @reader: an XML reader
5604 * @buffer: a pointer to a char array
5605 * @size: the size of the array
5606 * @URL: the base URL to use for the document
5607 * @encoding: the document encoding, or NULL
5608 * @options: a combination of xmlParserOption
5610 * Setup an xmltextReader to parse an XML in-memory document.
5611 * The parsing flags @options are a combination of xmlParserOption.
5612 * This reuses the existing @reader xmlTextReader.
5614 * Returns 0 in case of success and -1 in case of error
5617 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5618 const char *URL, const char *encoding, int options)
5620 xmlParserInputBufferPtr input;
5622 if (reader == NULL)
5623 return (-1);
5624 if (buffer == NULL)
5625 return (-1);
5627 input = xmlParserInputBufferCreateStatic(buffer, size,
5628 XML_CHAR_ENCODING_NONE);
5629 if (input == NULL) {
5630 return (-1);
5632 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5636 * xmlReaderNewFd:
5637 * @reader: an XML reader
5638 * @fd: an open file descriptor
5639 * @URL: the base URL to use for the document
5640 * @encoding: the document encoding, or NULL
5641 * @options: a combination of xmlParserOption
5643 * Setup an xmltextReader to parse an XML from a file descriptor.
5644 * NOTE that the file descriptor will not be closed when the
5645 * reader is closed or reset.
5646 * The parsing flags @options are a combination of xmlParserOption.
5647 * This reuses the existing @reader xmlTextReader.
5649 * Returns 0 in case of success and -1 in case of error
5652 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5653 const char *URL, const char *encoding, int options)
5655 xmlParserInputBufferPtr input;
5657 if (fd < 0)
5658 return (-1);
5659 if (reader == NULL)
5660 return (-1);
5662 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5663 if (input == NULL)
5664 return (-1);
5665 input->closecallback = NULL;
5666 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5670 * xmlReaderNewIO:
5671 * @reader: an XML reader
5672 * @ioread: an I/O read function
5673 * @ioclose: an I/O close function
5674 * @ioctx: an I/O handler
5675 * @URL: the base URL to use for the document
5676 * @encoding: the document encoding, or NULL
5677 * @options: a combination of xmlParserOption
5679 * Setup an xmltextReader to parse an XML document from I/O functions
5680 * and source.
5681 * The parsing flags @options are a combination of xmlParserOption.
5682 * This reuses the existing @reader xmlTextReader.
5684 * Returns 0 in case of success and -1 in case of error
5687 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5688 xmlInputCloseCallback ioclose, void *ioctx,
5689 const char *URL, const char *encoding, int options)
5691 xmlParserInputBufferPtr input;
5693 if (ioread == NULL)
5694 return (-1);
5695 if (reader == NULL)
5696 return (-1);
5698 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5699 XML_CHAR_ENCODING_NONE);
5700 if (input == NULL) {
5701 if (ioclose != NULL)
5702 ioclose(ioctx);
5703 return (-1);
5705 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5708 /************************************************************************
5710 * Utilities *
5712 ************************************************************************/
5713 #ifdef NOT_USED_YET
5716 * xmlBase64Decode:
5717 * @in: the input buffer
5718 * @inlen: the size of the input (in), the size read from it (out)
5719 * @to: the output buffer
5720 * @tolen: the size of the output (in), the size written to (out)
5722 * Base64 decoder, reads from @in and save in @to
5723 * TODO: tell jody when this is actually exported
5725 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5726 * 2 if there wasn't enough space on the output or -1 in case of error.
5728 static int
5729 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5730 unsigned char *to, unsigned long *tolen)
5732 unsigned long incur; /* current index in in[] */
5734 unsigned long inblk; /* last block index in in[] */
5736 unsigned long outcur; /* current index in out[] */
5738 unsigned long inmax; /* size of in[] */
5740 unsigned long outmax; /* size of out[] */
5742 unsigned char cur; /* the current value read from in[] */
5744 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5746 int nbintmp; /* number of byte in intmp[] */
5748 int is_ignore; /* cur should be ignored */
5750 int is_end = 0; /* the end of the base64 was found */
5752 int retval = 1;
5754 int i;
5756 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5757 return (-1);
5759 incur = 0;
5760 inblk = 0;
5761 outcur = 0;
5762 inmax = *inlen;
5763 outmax = *tolen;
5764 nbintmp = 0;
5766 while (1) {
5767 if (incur >= inmax)
5768 break;
5769 cur = in[incur++];
5770 is_ignore = 0;
5771 if ((cur >= 'A') && (cur <= 'Z'))
5772 cur = cur - 'A';
5773 else if ((cur >= 'a') && (cur <= 'z'))
5774 cur = cur - 'a' + 26;
5775 else if ((cur >= '0') && (cur <= '9'))
5776 cur = cur - '0' + 52;
5777 else if (cur == '+')
5778 cur = 62;
5779 else if (cur == '/')
5780 cur = 63;
5781 else if (cur == '.')
5782 cur = 0;
5783 else if (cur == '=') /*no op , end of the base64 stream */
5784 is_end = 1;
5785 else {
5786 is_ignore = 1;
5787 if (nbintmp == 0)
5788 inblk = incur;
5791 if (!is_ignore) {
5792 int nbouttmp = 3;
5794 int is_break = 0;
5796 if (is_end) {
5797 if (nbintmp == 0)
5798 break;
5799 if ((nbintmp == 1) || (nbintmp == 2))
5800 nbouttmp = 1;
5801 else
5802 nbouttmp = 2;
5803 nbintmp = 3;
5804 is_break = 1;
5806 intmp[nbintmp++] = cur;
5808 * if intmp is full, push the 4byte sequence as a 3 byte
5809 * sequence out
5811 if (nbintmp == 4) {
5812 nbintmp = 0;
5813 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5814 outtmp[1] =
5815 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5816 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5817 if (outcur + 3 >= outmax) {
5818 retval = 2;
5819 break;
5822 for (i = 0; i < nbouttmp; i++)
5823 to[outcur++] = outtmp[i];
5824 inblk = incur;
5827 if (is_break) {
5828 retval = 0;
5829 break;
5834 *tolen = outcur;
5835 *inlen = inblk;
5836 return (retval);
5840 * Test routine for the xmlBase64Decode function
5842 #if 0
5844 main(int argc, char **argv)
5846 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5848 char output[100];
5850 char output2[100];
5852 char output3[100];
5854 unsigned long inlen = strlen(input);
5856 unsigned long outlen = 100;
5858 int ret;
5860 unsigned long cons, tmp, tmp2, prod;
5863 * Direct
5865 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5867 output[outlen] = 0;
5868 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5869 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5873 * output chunking
5875 cons = 0;
5876 prod = 0;
5877 while (cons < inlen) {
5878 tmp = 5;
5879 tmp2 = inlen - cons;
5881 printf("%ld %ld\n", cons, prod);
5882 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5883 cons += tmp2;
5884 prod += tmp;
5885 printf("%ld %ld\n", cons, prod);
5887 output2[outlen] = 0;
5888 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5889 prod, output2);
5892 * input chunking
5894 cons = 0;
5895 prod = 0;
5896 while (cons < inlen) {
5897 tmp = 100 - prod;
5898 tmp2 = inlen - cons;
5899 if (tmp2 > 5)
5900 tmp2 = 5;
5902 printf("%ld %ld\n", cons, prod);
5903 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5904 cons += tmp2;
5905 prod += tmp;
5906 printf("%ld %ld\n", cons, prod);
5908 output3[outlen] = 0;
5909 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5910 prod, output3);
5911 return (0);
5914 #endif
5915 #endif /* NOT_USED_YET */
5916 #define bottom_xmlreader
5917 #include "elfgcchack.h"
5918 #endif /* LIBXML_READER_ENABLED */