mshtml: Implement length prop for Storage.
[wine.git] / libs / xml2 / xmlreader.c
blobb3299cedfccebb74c9a57f3e5a6e093b99376df5
1 /*
2 * xmlreader.c: implements the xmlTextReader streaming node API
4 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
8 * See Copyright for the status of this software.
10 * daniel@veillard.com
14 * TODOs:
15 * - XML Schemas validation
17 #define IN_LIBXML
18 #include "libxml.h"
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
23 #include <ctype.h>
24 #include <stdlib.h>
26 #include <libxml/xmlmemory.h>
27 #include <libxml/xmlIO.h>
28 #include <libxml/xmlreader.h>
29 #include <libxml/parserInternals.h>
30 #ifdef LIBXML_SCHEMAS_ENABLED
31 #include <libxml/relaxng.h>
32 #include <libxml/xmlschemas.h>
33 #endif
34 #include <libxml/uri.h>
35 #ifdef LIBXML_XINCLUDE_ENABLED
36 #include <libxml/xinclude.h>
37 #endif
38 #ifdef LIBXML_PATTERN_ENABLED
39 #include <libxml/pattern.h>
40 #endif
42 #include "buf.h"
44 #define MAX_ERR_MSG_SIZE 64000
46 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
47 /* Keeping free objects can hide memory errors. */
48 #define MAX_FREE_NODES 1
49 #else
50 #define MAX_FREE_NODES 100
51 #endif
54 * The following VA_COPY was coded following an example in
55 * the Samba project. It may not be sufficient for some
56 * esoteric implementations of va_list but (hopefully) will
57 * be sufficient for libxml2.
59 #ifndef VA_COPY
60 #ifdef HAVE_VA_COPY
61 #define VA_COPY(dest, src) va_copy(dest, src)
62 #else
63 #ifdef HAVE___VA_COPY
64 #define VA_COPY(dest,src) __va_copy(dest, src)
65 #else
66 #ifndef VA_LIST_IS_ARRAY
67 #define VA_COPY(dest,src) (dest) = (src)
68 #else
69 #include <string.h>
70 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
71 #endif
72 #endif
73 #endif
74 #endif
76 /* #define DEBUG_CALLBACKS */
77 /* #define DEBUG_READER */
79 /**
80 * TODO:
82 * macro to flag unimplemented blocks
84 #define TODO \
85 xmlGenericError(xmlGenericErrorContext, \
86 "Unimplemented block at %s:%d\n", \
87 __FILE__, __LINE__);
89 #ifdef DEBUG_READER
90 #define DUMP_READER xmlTextReaderDebug(reader);
91 #else
92 #define DUMP_READER
93 #endif
95 #define CHUNK_SIZE 512
96 /************************************************************************
97 * *
98 * The parser: maps the Text Reader API on top of the existing *
99 * parsing routines building a tree *
101 ************************************************************************/
103 #define XML_TEXTREADER_INPUT 1
104 #define XML_TEXTREADER_CTXT 2
106 typedef enum {
107 XML_TEXTREADER_NONE = -1,
108 XML_TEXTREADER_START= 0,
109 XML_TEXTREADER_ELEMENT= 1,
110 XML_TEXTREADER_END= 2,
111 XML_TEXTREADER_EMPTY= 3,
112 XML_TEXTREADER_BACKTRACK= 4,
113 XML_TEXTREADER_DONE= 5,
114 XML_TEXTREADER_ERROR= 6
115 } xmlTextReaderState;
117 typedef enum {
118 XML_TEXTREADER_NOT_VALIDATE = 0,
119 XML_TEXTREADER_VALIDATE_DTD = 1,
120 XML_TEXTREADER_VALIDATE_RNG = 2,
121 XML_TEXTREADER_VALIDATE_XSD = 4
122 } xmlTextReaderValidate;
124 struct _xmlTextReader {
125 int mode; /* the parsing mode */
126 xmlDocPtr doc; /* when walking an existing doc */
127 xmlTextReaderValidate validate;/* is there any validation */
128 int allocs; /* what structure were deallocated */
129 xmlTextReaderState state;
130 xmlParserCtxtPtr ctxt; /* the parser context */
131 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
132 xmlParserInputBufferPtr input; /* the input */
133 startElementSAXFunc startElement;/* initial SAX callbacks */
134 endElementSAXFunc endElement; /* idem */
135 startElementNsSAX2Func startElementNs;/* idem */
136 endElementNsSAX2Func endElementNs; /* idem */
137 charactersSAXFunc characters;
138 cdataBlockSAXFunc cdataBlock;
139 unsigned int base; /* base of the segment in the input */
140 unsigned int cur; /* current position in the input */
141 xmlNodePtr node; /* current node */
142 xmlNodePtr curnode;/* current attribute node */
143 int depth; /* depth of the current node */
144 xmlNodePtr faketext;/* fake xmlNs chld */
145 int preserve;/* preserve the resulting document */
146 xmlBufPtr buffer; /* used to return const xmlChar * */
147 xmlDictPtr dict; /* the context dictionary */
149 /* entity stack when traversing entities content */
150 xmlNodePtr ent; /* Current Entity Ref Node */
151 int entNr; /* Depth of the entities stack */
152 int entMax; /* Max depth of the entities stack */
153 xmlNodePtr *entTab; /* array of entities */
155 /* error handling */
156 xmlTextReaderErrorFunc errorFunc; /* callback function */
157 void *errorFuncArg; /* callback function user argument */
159 #ifdef LIBXML_SCHEMAS_ENABLED
160 /* Handling of RelaxNG validation */
161 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
162 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
163 int rngPreserveCtxt; /* 1 if the context was provided by the user */
164 int rngValidErrors;/* The number of errors detected */
165 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
166 /* Handling of Schemas validation */
167 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
168 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
169 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
170 int xsdValidErrors;/* The number of errors detected */
171 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
172 #endif
173 #ifdef LIBXML_XINCLUDE_ENABLED
174 /* Handling of XInclude processing */
175 int xinclude; /* is xinclude asked for */
176 const xmlChar * xinclude_name; /* the xinclude name from dict */
177 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
178 int in_xinclude; /* counts for xinclude */
179 #endif
180 #ifdef LIBXML_PATTERN_ENABLED
181 int patternNr; /* number of preserve patterns */
182 int patternMax; /* max preserve patterns */
183 xmlPatternPtr *patternTab; /* array of preserve patterns */
184 #endif
185 int preserves; /* level of preserves */
186 int parserFlags; /* the set of options set */
187 /* Structured error handling */
188 xmlStructuredErrorFunc sErrorFunc; /* callback function */
191 #define NODE_IS_EMPTY 0x1
192 #define NODE_IS_PRESERVED 0x2
193 #define NODE_IS_SPRESERVED 0x4
196 * CONSTSTR:
198 * Macro used to return an interned string
200 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
201 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
203 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
204 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
206 /************************************************************************
208 * Our own version of the freeing routines as we recycle nodes *
210 ************************************************************************/
212 * DICT_FREE:
213 * @str: a string
215 * Free a string if it is not owned by the "dict" dictionary in the
216 * current scope
218 #define DICT_FREE(str) \
219 if ((str) && ((!dict) || \
220 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
221 xmlFree((char *)(str));
223 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
224 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
227 * xmlTextReaderFreeProp:
228 * @reader: the xmlTextReaderPtr used
229 * @cur: the node
231 * Free a node.
233 static void
234 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
235 xmlDictPtr dict;
237 if ((reader != NULL) && (reader->ctxt != NULL))
238 dict = reader->ctxt->dict;
239 else
240 dict = NULL;
241 if (cur == NULL) return;
243 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
244 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
246 if (cur->children != NULL)
247 xmlTextReaderFreeNodeList(reader, cur->children);
249 DICT_FREE(cur->name);
250 if ((reader != NULL) && (reader->ctxt != NULL) &&
251 (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
252 cur->next = reader->ctxt->freeAttrs;
253 reader->ctxt->freeAttrs = cur;
254 reader->ctxt->freeAttrsNr++;
255 } else {
256 xmlFree(cur);
261 * xmlTextReaderFreePropList:
262 * @reader: the xmlTextReaderPtr used
263 * @cur: the first property in the list
265 * Free a property and all its siblings, all the children are freed too.
267 static void
268 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
269 xmlAttrPtr next;
271 while (cur != NULL) {
272 next = cur->next;
273 xmlTextReaderFreeProp(reader, cur);
274 cur = next;
279 * xmlTextReaderFreeNodeList:
280 * @reader: the xmlTextReaderPtr used
281 * @cur: the first node in the list
283 * Free a node and all its siblings, this is a recursive behaviour, all
284 * the children are freed too.
286 static void
287 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
288 xmlNodePtr next;
289 xmlNodePtr parent;
290 xmlDictPtr dict;
291 size_t depth = 0;
293 if ((reader != NULL) && (reader->ctxt != NULL))
294 dict = reader->ctxt->dict;
295 else
296 dict = NULL;
297 if (cur == NULL) return;
298 if (cur->type == XML_NAMESPACE_DECL) {
299 xmlFreeNsList((xmlNsPtr) cur);
300 return;
302 if ((cur->type == XML_DOCUMENT_NODE) ||
303 (cur->type == XML_HTML_DOCUMENT_NODE)) {
304 xmlFreeDoc((xmlDocPtr) cur);
305 return;
307 while (1) {
308 while ((cur->type != XML_DTD_NODE) &&
309 (cur->type != XML_ENTITY_REF_NODE) &&
310 (cur->children != NULL) &&
311 (cur->children->parent == cur)) {
312 cur = cur->children;
313 depth += 1;
316 next = cur->next;
317 parent = cur->parent;
319 /* unroll to speed up freeing the document */
320 if (cur->type != XML_DTD_NODE) {
322 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
323 xmlDeregisterNodeDefaultValue(cur);
325 if (((cur->type == XML_ELEMENT_NODE) ||
326 (cur->type == XML_XINCLUDE_START) ||
327 (cur->type == XML_XINCLUDE_END)) &&
328 (cur->properties != NULL))
329 xmlTextReaderFreePropList(reader, cur->properties);
330 if ((cur->content != (xmlChar *) &(cur->properties)) &&
331 (cur->type != XML_ELEMENT_NODE) &&
332 (cur->type != XML_XINCLUDE_START) &&
333 (cur->type != XML_XINCLUDE_END) &&
334 (cur->type != XML_ENTITY_REF_NODE)) {
335 DICT_FREE(cur->content);
337 if (((cur->type == XML_ELEMENT_NODE) ||
338 (cur->type == XML_XINCLUDE_START) ||
339 (cur->type == XML_XINCLUDE_END)) &&
340 (cur->nsDef != NULL))
341 xmlFreeNsList(cur->nsDef);
344 * we don't free element names here they are interned now
346 if ((cur->type != XML_TEXT_NODE) &&
347 (cur->type != XML_COMMENT_NODE))
348 DICT_FREE(cur->name);
349 if (((cur->type == XML_ELEMENT_NODE) ||
350 (cur->type == XML_TEXT_NODE)) &&
351 (reader != NULL) && (reader->ctxt != NULL) &&
352 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
353 cur->next = reader->ctxt->freeElems;
354 reader->ctxt->freeElems = cur;
355 reader->ctxt->freeElemsNr++;
356 } else {
357 xmlFree(cur);
361 if (next != NULL) {
362 cur = next;
363 } else {
364 if ((depth == 0) || (parent == NULL))
365 break;
366 depth -= 1;
367 cur = parent;
368 cur->children = NULL;
374 * xmlTextReaderFreeNode:
375 * @reader: the xmlTextReaderPtr used
376 * @cur: the node
378 * Free a node, this is a recursive behaviour, all the children are freed too.
379 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
381 static void
382 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
383 xmlDictPtr dict;
385 if ((reader != NULL) && (reader->ctxt != NULL))
386 dict = reader->ctxt->dict;
387 else
388 dict = NULL;
389 if (cur->type == XML_DTD_NODE) {
390 xmlFreeDtd((xmlDtdPtr) cur);
391 return;
393 if (cur->type == XML_NAMESPACE_DECL) {
394 xmlFreeNs((xmlNsPtr) cur);
395 return;
397 if (cur->type == XML_ATTRIBUTE_NODE) {
398 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
399 return;
402 if ((cur->children != NULL) &&
403 (cur->type != XML_ENTITY_REF_NODE)) {
404 if (cur->children->parent == cur)
405 xmlTextReaderFreeNodeList(reader, cur->children);
406 cur->children = NULL;
409 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
410 xmlDeregisterNodeDefaultValue(cur);
412 if (((cur->type == XML_ELEMENT_NODE) ||
413 (cur->type == XML_XINCLUDE_START) ||
414 (cur->type == XML_XINCLUDE_END)) &&
415 (cur->properties != NULL))
416 xmlTextReaderFreePropList(reader, cur->properties);
417 if ((cur->content != (xmlChar *) &(cur->properties)) &&
418 (cur->type != XML_ELEMENT_NODE) &&
419 (cur->type != XML_XINCLUDE_START) &&
420 (cur->type != XML_XINCLUDE_END) &&
421 (cur->type != XML_ENTITY_REF_NODE)) {
422 DICT_FREE(cur->content);
424 if (((cur->type == XML_ELEMENT_NODE) ||
425 (cur->type == XML_XINCLUDE_START) ||
426 (cur->type == XML_XINCLUDE_END)) &&
427 (cur->nsDef != NULL))
428 xmlFreeNsList(cur->nsDef);
431 * we don't free names here they are interned now
433 if ((cur->type != XML_TEXT_NODE) &&
434 (cur->type != XML_COMMENT_NODE))
435 DICT_FREE(cur->name);
437 if (((cur->type == XML_ELEMENT_NODE) ||
438 (cur->type == XML_TEXT_NODE)) &&
439 (reader != NULL) && (reader->ctxt != NULL) &&
440 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
441 cur->next = reader->ctxt->freeElems;
442 reader->ctxt->freeElems = cur;
443 reader->ctxt->freeElemsNr++;
444 } else {
445 xmlFree(cur);
450 * xmlTextReaderFreeDoc:
451 * @reader: the xmlTextReaderPtr used
452 * @cur: pointer to the document
454 * Free up all the structures used by a document, tree included.
456 static void
457 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
458 xmlDtdPtr extSubset, intSubset;
460 if (cur == NULL) return;
462 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
463 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
466 * Do this before freeing the children list to avoid ID lookups
468 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
469 cur->ids = NULL;
470 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
471 cur->refs = NULL;
472 extSubset = cur->extSubset;
473 intSubset = cur->intSubset;
474 if (intSubset == extSubset)
475 extSubset = NULL;
476 if (extSubset != NULL) {
477 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
478 cur->extSubset = NULL;
479 xmlFreeDtd(extSubset);
481 if (intSubset != NULL) {
482 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
483 cur->intSubset = NULL;
484 xmlFreeDtd(intSubset);
487 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
489 if (cur->version != NULL) xmlFree((char *) cur->version);
490 if (cur->name != NULL) xmlFree((char *) cur->name);
491 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
492 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
493 if (cur->URL != NULL) xmlFree((char *) cur->URL);
494 if (cur->dict != NULL) xmlDictFree(cur->dict);
496 xmlFree(cur);
499 /************************************************************************
501 * The reader core parser *
503 ************************************************************************/
504 #ifdef DEBUG_READER
505 static void
506 xmlTextReaderDebug(xmlTextReaderPtr reader) {
507 if ((reader == NULL) || (reader->ctxt == NULL)) {
508 fprintf(stderr, "xmlTextReader NULL\n");
509 return;
511 fprintf(stderr, "xmlTextReader: state %d depth %d ",
512 reader->state, reader->depth);
513 if (reader->node == NULL) {
514 fprintf(stderr, "node = NULL\n");
515 } else {
516 fprintf(stderr, "node %s\n", reader->node->name);
518 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
519 reader->base, reader->cur, reader->ctxt->nodeNr);
520 if (reader->input->buffer == NULL) {
521 fprintf(stderr, "buffer is NULL\n");
522 } else {
523 #ifdef LIBXML_DEBUG_ENABLED
524 xmlDebugDumpString(stderr,
525 &reader->input->buffer->content[reader->cur]);
526 #endif
527 fprintf(stderr, "\n");
530 #endif
533 * xmlTextReaderEntPush:
534 * @reader: the xmlTextReaderPtr used
535 * @value: the entity reference node
537 * Pushes a new entity reference node on top of the entities stack
539 * Returns 0 in case of error, the index in the stack otherwise
541 static int
542 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
544 if (reader->entMax <= 0) {
545 reader->entMax = 10;
546 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
547 sizeof(reader->entTab[0]));
548 if (reader->entTab == NULL) {
549 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
550 return (0);
553 if (reader->entNr >= reader->entMax) {
554 reader->entMax *= 2;
555 reader->entTab =
556 (xmlNodePtr *) xmlRealloc(reader->entTab,
557 reader->entMax *
558 sizeof(reader->entTab[0]));
559 if (reader->entTab == NULL) {
560 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
561 return (0);
564 reader->entTab[reader->entNr] = value;
565 reader->ent = value;
566 return (reader->entNr++);
570 * xmlTextReaderEntPop:
571 * @reader: the xmlTextReaderPtr used
573 * Pops the top element entity from the entities stack
575 * Returns the entity just removed
577 static xmlNodePtr
578 xmlTextReaderEntPop(xmlTextReaderPtr reader)
580 xmlNodePtr ret;
582 if (reader->entNr <= 0)
583 return (NULL);
584 reader->entNr--;
585 if (reader->entNr > 0)
586 reader->ent = reader->entTab[reader->entNr - 1];
587 else
588 reader->ent = NULL;
589 ret = reader->entTab[reader->entNr];
590 reader->entTab[reader->entNr] = NULL;
591 return (ret);
595 * xmlTextReaderStartElement:
596 * @ctx: the user data (XML parser context)
597 * @fullname: The element name, including namespace prefix
598 * @atts: An array of name/value attributes pairs, NULL terminated
600 * called when an opening tag has been processed.
602 static void
603 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
604 const xmlChar **atts) {
605 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
606 xmlTextReaderPtr reader = ctxt->_private;
608 #ifdef DEBUG_CALLBACKS
609 printf("xmlTextReaderStartElement(%s)\n", fullname);
610 #endif
611 if ((reader != NULL) && (reader->startElement != NULL)) {
612 reader->startElement(ctx, fullname, atts);
613 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
614 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
615 (ctxt->input->cur[1] == '>'))
616 ctxt->node->extra = NODE_IS_EMPTY;
618 if (reader != NULL)
619 reader->state = XML_TEXTREADER_ELEMENT;
623 * xmlTextReaderEndElement:
624 * @ctx: the user data (XML parser context)
625 * @fullname: The element name, including namespace prefix
627 * called when an ending tag has been processed.
629 static void
630 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
631 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
632 xmlTextReaderPtr reader = ctxt->_private;
634 #ifdef DEBUG_CALLBACKS
635 printf("xmlTextReaderEndElement(%s)\n", fullname);
636 #endif
637 if ((reader != NULL) && (reader->endElement != NULL)) {
638 reader->endElement(ctx, fullname);
643 * xmlTextReaderStartElementNs:
644 * @ctx: the user data (XML parser context)
645 * @localname: the local name of the element
646 * @prefix: the element namespace prefix if available
647 * @URI: the element namespace name if available
648 * @nb_namespaces: number of namespace definitions on that node
649 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
650 * @nb_attributes: the number of attributes on that node
651 * nb_defaulted: the number of defaulted attributes.
652 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
653 * attribute values.
655 * called when an opening tag has been processed.
657 static void
658 xmlTextReaderStartElementNs(void *ctx,
659 const xmlChar *localname,
660 const xmlChar *prefix,
661 const xmlChar *URI,
662 int nb_namespaces,
663 const xmlChar **namespaces,
664 int nb_attributes,
665 int nb_defaulted,
666 const xmlChar **attributes)
668 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
669 xmlTextReaderPtr reader = ctxt->_private;
671 #ifdef DEBUG_CALLBACKS
672 printf("xmlTextReaderStartElementNs(%s)\n", localname);
673 #endif
674 if ((reader != NULL) && (reader->startElementNs != NULL)) {
675 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
676 namespaces, nb_attributes, nb_defaulted,
677 attributes);
678 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
679 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
680 (ctxt->input->cur[1] == '>'))
681 ctxt->node->extra = NODE_IS_EMPTY;
683 if (reader != NULL)
684 reader->state = XML_TEXTREADER_ELEMENT;
688 * xmlTextReaderEndElementNs:
689 * @ctx: the user data (XML parser context)
690 * @localname: the local name of the element
691 * @prefix: the element namespace prefix if available
692 * @URI: the element namespace name if available
694 * called when an ending tag has been processed.
696 static void
697 xmlTextReaderEndElementNs(void *ctx,
698 const xmlChar * localname,
699 const xmlChar * prefix,
700 const xmlChar * URI)
702 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
703 xmlTextReaderPtr reader = ctxt->_private;
705 #ifdef DEBUG_CALLBACKS
706 printf("xmlTextReaderEndElementNs(%s)\n", localname);
707 #endif
708 if ((reader != NULL) && (reader->endElementNs != NULL)) {
709 reader->endElementNs(ctx, localname, prefix, URI);
715 * xmlTextReaderCharacters:
716 * @ctx: the user data (XML parser context)
717 * @ch: a xmlChar string
718 * @len: the number of xmlChar
720 * receiving some chars from the parser.
722 static void
723 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
725 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
726 xmlTextReaderPtr reader = ctxt->_private;
728 #ifdef DEBUG_CALLBACKS
729 printf("xmlTextReaderCharacters()\n");
730 #endif
731 if ((reader != NULL) && (reader->characters != NULL)) {
732 reader->characters(ctx, ch, len);
737 * xmlTextReaderCDataBlock:
738 * @ctx: the user data (XML parser context)
739 * @value: The pcdata content
740 * @len: the block length
742 * called when a pcdata block has been parsed
744 static void
745 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
747 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
748 xmlTextReaderPtr reader = ctxt->_private;
750 #ifdef DEBUG_CALLBACKS
751 printf("xmlTextReaderCDataBlock()\n");
752 #endif
753 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
754 reader->cdataBlock(ctx, ch, len);
759 * xmlTextReaderPushData:
760 * @reader: the xmlTextReaderPtr used
762 * Push data down the progressive parser until a significant callback
763 * got raised.
765 * Returns -1 in case of failure, 0 otherwise
767 static int
768 xmlTextReaderPushData(xmlTextReaderPtr reader) {
769 xmlBufPtr inbuf;
770 int val, s;
771 xmlTextReaderState oldstate;
772 int alloc;
774 if ((reader->input == NULL) || (reader->input->buffer == NULL))
775 return(-1);
777 oldstate = reader->state;
778 reader->state = XML_TEXTREADER_NONE;
779 inbuf = reader->input->buffer;
780 alloc = xmlBufGetAllocationScheme(inbuf);
782 while (reader->state == XML_TEXTREADER_NONE) {
783 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
785 * Refill the buffer unless we are at the end of the stream
787 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
788 val = xmlParserInputBufferRead(reader->input, 4096);
789 if ((val == 0) &&
790 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
791 if (xmlBufUse(inbuf) == reader->cur) {
792 reader->mode = XML_TEXTREADER_MODE_EOF;
793 reader->state = oldstate;
795 } else if (val < 0) {
796 reader->mode = XML_TEXTREADER_MODE_EOF;
797 reader->state = oldstate;
798 if ((oldstate != XML_TEXTREADER_START) ||
799 (reader->ctxt->myDoc != NULL))
800 return(val);
801 } else if (val == 0) {
802 /* mark the end of the stream and process the remains */
803 reader->mode = XML_TEXTREADER_MODE_EOF;
804 break;
807 } else
808 break;
811 * parse by block of CHUNK_SIZE bytes, various tests show that
812 * it's the best tradeoff at least on a 1.2GH Duron
814 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
815 val = xmlParseChunk(reader->ctxt,
816 (const char *) xmlBufContent(inbuf) + reader->cur,
817 CHUNK_SIZE, 0);
818 reader->cur += CHUNK_SIZE;
819 if (val != 0)
820 reader->ctxt->wellFormed = 0;
821 if (reader->ctxt->wellFormed == 0)
822 break;
823 } else {
824 s = xmlBufUse(inbuf) - reader->cur;
825 val = xmlParseChunk(reader->ctxt,
826 (const char *) xmlBufContent(inbuf) + reader->cur,
827 s, 0);
828 reader->cur += s;
829 if (val != 0)
830 reader->ctxt->wellFormed = 0;
831 break;
836 * Discard the consumed input when needed and possible
838 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
839 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
840 if ((reader->cur >= 4096) &&
841 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
842 val = xmlBufShrink(inbuf, reader->cur);
843 if (val >= 0) {
844 reader->cur -= val;
851 * At the end of the stream signal that the work is done to the Push
852 * parser.
854 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
855 if (reader->state != XML_TEXTREADER_DONE) {
856 s = xmlBufUse(inbuf) - reader->cur;
857 val = xmlParseChunk(reader->ctxt,
858 (const char *) xmlBufContent(inbuf) + reader->cur,
859 s, 1);
860 reader->cur = xmlBufUse(inbuf);
861 reader->state = XML_TEXTREADER_DONE;
862 if (val != 0) {
863 if (reader->ctxt->wellFormed)
864 reader->ctxt->wellFormed = 0;
865 else
866 return(-1);
870 reader->state = oldstate;
871 if (reader->ctxt->wellFormed == 0) {
872 reader->mode = XML_TEXTREADER_MODE_EOF;
873 return(-1);
876 return(0);
879 #ifdef LIBXML_REGEXP_ENABLED
881 * xmlTextReaderValidatePush:
882 * @reader: the xmlTextReaderPtr used
884 * Push the current node for validation
886 static void
887 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
888 xmlNodePtr node = reader->node;
890 #ifdef LIBXML_VALID_ENABLED
891 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
892 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
893 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
894 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
895 reader->ctxt->myDoc, node, node->name);
896 } else {
897 /* TODO use the BuildQName interface */
898 xmlChar *qname;
900 qname = xmlStrdup(node->ns->prefix);
901 qname = xmlStrcat(qname, BAD_CAST ":");
902 qname = xmlStrcat(qname, node->name);
903 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
904 reader->ctxt->myDoc, node, qname);
905 if (qname != NULL)
906 xmlFree(qname);
909 #endif /* LIBXML_VALID_ENABLED */
910 #ifdef LIBXML_SCHEMAS_ENABLED
911 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
912 (reader->rngValidCtxt != NULL)) {
913 int ret;
915 if (reader->rngFullNode != NULL) return;
916 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
917 reader->ctxt->myDoc,
918 node);
919 if (ret == 0) {
921 * this element requires a full tree
923 node = xmlTextReaderExpand(reader);
924 if (node == NULL) {
925 ret = -1;
926 } else {
927 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
928 reader->ctxt->myDoc,
929 node);
930 reader->rngFullNode = node;
933 if (ret != 1)
934 reader->rngValidErrors++;
936 #endif
940 * xmlTextReaderValidateCData:
941 * @reader: the xmlTextReaderPtr used
942 * @data: pointer to the CData
943 * @len: length of the CData block in bytes.
945 * Push some CData for validation
947 static void
948 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
949 const xmlChar *data, int len) {
950 #ifdef LIBXML_VALID_ENABLED
951 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
952 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
953 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
954 data, len);
956 #endif /* LIBXML_VALID_ENABLED */
957 #ifdef LIBXML_SCHEMAS_ENABLED
958 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
959 (reader->rngValidCtxt != NULL)) {
960 int ret;
962 if (reader->rngFullNode != NULL) return;
963 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
964 if (ret != 1)
965 reader->rngValidErrors++;
967 #endif
971 * xmlTextReaderValidatePop:
972 * @reader: the xmlTextReaderPtr used
974 * Pop the current node from validation
976 static void
977 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
978 xmlNodePtr node = reader->node;
980 #ifdef LIBXML_VALID_ENABLED
981 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
982 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
983 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
984 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
985 reader->ctxt->myDoc, node, node->name);
986 } else {
987 /* TODO use the BuildQName interface */
988 xmlChar *qname;
990 qname = xmlStrdup(node->ns->prefix);
991 qname = xmlStrcat(qname, BAD_CAST ":");
992 qname = xmlStrcat(qname, node->name);
993 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
994 reader->ctxt->myDoc, node, qname);
995 if (qname != NULL)
996 xmlFree(qname);
999 #endif /* LIBXML_VALID_ENABLED */
1000 #ifdef LIBXML_SCHEMAS_ENABLED
1001 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1002 (reader->rngValidCtxt != NULL)) {
1003 int ret;
1005 if (reader->rngFullNode != NULL) {
1006 if (node == reader->rngFullNode)
1007 reader->rngFullNode = NULL;
1008 return;
1010 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1011 reader->ctxt->myDoc,
1012 node);
1013 if (ret != 1)
1014 reader->rngValidErrors++;
1016 #endif
1020 * xmlTextReaderValidateEntity:
1021 * @reader: the xmlTextReaderPtr used
1023 * Handle the validation when an entity reference is encountered and
1024 * entity substitution is not activated. As a result the parser interface
1025 * must walk through the entity and do the validation calls
1027 static void
1028 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1029 xmlNodePtr oldnode = reader->node;
1030 xmlNodePtr node = reader->node;
1032 do {
1033 if (node->type == XML_ENTITY_REF_NODE) {
1034 if ((node->children != NULL) &&
1035 (node->children->type == XML_ENTITY_DECL) &&
1036 (node->children->children != NULL)) {
1037 xmlTextReaderEntPush(reader, node);
1038 node = node->children->children;
1039 continue;
1040 } else {
1042 * The error has probably been raised already.
1044 if (node == oldnode)
1045 break;
1046 goto skip_children;
1048 #ifdef LIBXML_REGEXP_ENABLED
1049 } else if (node->type == XML_ELEMENT_NODE) {
1050 reader->node = node;
1051 xmlTextReaderValidatePush(reader);
1052 } else if ((node->type == XML_TEXT_NODE) ||
1053 (node->type == XML_CDATA_SECTION_NODE)) {
1054 xmlTextReaderValidateCData(reader, node->content,
1055 xmlStrlen(node->content));
1056 #endif
1060 * go to next node
1062 if (node->children != NULL) {
1063 node = node->children;
1064 continue;
1065 } else if (node->type == XML_ELEMENT_NODE) {
1066 xmlTextReaderValidatePop(reader);
1068 skip_children:
1069 if (node->next != NULL) {
1070 node = node->next;
1071 continue;
1073 do {
1074 node = node->parent;
1075 if (node->type == XML_ELEMENT_NODE) {
1076 xmlNodePtr tmp;
1077 if (reader->entNr == 0) {
1078 while ((tmp = node->last) != NULL) {
1079 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1080 xmlUnlinkNode(tmp);
1081 xmlTextReaderFreeNode(reader, tmp);
1082 } else
1083 break;
1086 reader->node = node;
1087 xmlTextReaderValidatePop(reader);
1089 if ((node->type == XML_ENTITY_DECL) &&
1090 (reader->ent != NULL) && (reader->ent->children == node)) {
1091 node = xmlTextReaderEntPop(reader);
1093 if (node == oldnode)
1094 break;
1095 if (node->next != NULL) {
1096 node = node->next;
1097 break;
1099 } while ((node != NULL) && (node != oldnode));
1100 } while ((node != NULL) && (node != oldnode));
1101 reader->node = oldnode;
1103 #endif /* LIBXML_REGEXP_ENABLED */
1107 * xmlTextReaderGetSuccessor:
1108 * @cur: the current node
1110 * Get the successor of a node if available.
1112 * Returns the successor node or NULL
1114 static xmlNodePtr
1115 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1116 if (cur == NULL) return(NULL) ; /* ERROR */
1117 if (cur->next != NULL) return(cur->next) ;
1118 do {
1119 cur = cur->parent;
1120 if (cur == NULL) break;
1121 if (cur->next != NULL) return(cur->next);
1122 } while (cur != NULL);
1123 return(cur);
1127 * xmlTextReaderDoExpand:
1128 * @reader: the xmlTextReaderPtr used
1130 * Makes sure that the current node is fully read as well as all its
1131 * descendant. It means the full DOM subtree must be available at the
1132 * end of the call.
1134 * Returns 1 if the node was expanded successfully, 0 if there is no more
1135 * nodes to read, or -1 in case of error
1137 static int
1138 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1139 int val;
1141 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1142 return(-1);
1143 do {
1144 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1146 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1147 return(1);
1148 if (reader->ctxt->nodeNr < reader->depth)
1149 return(1);
1150 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1151 return(1);
1152 val = xmlTextReaderPushData(reader);
1153 if (val < 0){
1154 reader->mode = XML_TEXTREADER_MODE_ERROR;
1155 return(-1);
1157 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1158 return(1);
1162 * xmlTextReaderCollectSiblings:
1163 * @node: the first child
1165 * Traverse depth-first through all sibling nodes and their children
1166 * nodes and concatenate their content. This is an auxiliary function
1167 * to xmlTextReaderReadString.
1169 * Returns a string containing the content, or NULL in case of error.
1171 static xmlChar *
1172 xmlTextReaderCollectSiblings(xmlNodePtr node)
1174 xmlBufferPtr buffer;
1175 xmlChar *ret;
1177 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1178 return(NULL);
1180 buffer = xmlBufferCreate();
1181 if (buffer == NULL)
1182 return NULL;
1183 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
1185 for ( ; node != NULL; node = node->next) {
1186 switch (node->type) {
1187 case XML_TEXT_NODE:
1188 case XML_CDATA_SECTION_NODE:
1189 xmlBufferCat(buffer, node->content);
1190 break;
1191 case XML_ELEMENT_NODE: {
1192 xmlChar *tmp;
1194 tmp = xmlTextReaderCollectSiblings(node->children);
1195 xmlBufferCat(buffer, tmp);
1196 xmlFree(tmp);
1197 break;
1199 default:
1200 break;
1203 ret = buffer->content;
1204 buffer->content = NULL;
1205 xmlBufferFree(buffer);
1206 return(ret);
1210 * xmlTextReaderRead:
1211 * @reader: the xmlTextReaderPtr used
1213 * Moves the position of the current instance to the next node in
1214 * the stream, exposing its properties.
1216 * Returns 1 if the node was read successfully, 0 if there is no more
1217 * nodes to read, or -1 in case of error
1220 xmlTextReaderRead(xmlTextReaderPtr reader) {
1221 int val, olddepth = 0;
1222 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1223 xmlNodePtr oldnode = NULL;
1226 if (reader == NULL)
1227 return(-1);
1228 reader->curnode = NULL;
1229 if (reader->doc != NULL)
1230 return(xmlTextReaderReadTree(reader));
1231 if (reader->ctxt == NULL)
1232 return(-1);
1234 #ifdef DEBUG_READER
1235 fprintf(stderr, "\nREAD ");
1236 DUMP_READER
1237 #endif
1238 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1239 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1241 * Initial state
1243 do {
1244 val = xmlTextReaderPushData(reader);
1245 if (val < 0){
1246 reader->mode = XML_TEXTREADER_MODE_ERROR;
1247 reader->state = XML_TEXTREADER_ERROR;
1248 return(-1);
1250 } while ((reader->ctxt->node == NULL) &&
1251 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1252 (reader->state != XML_TEXTREADER_DONE)));
1253 if (reader->ctxt->node == NULL) {
1254 if (reader->ctxt->myDoc != NULL) {
1255 reader->node = reader->ctxt->myDoc->children;
1257 if (reader->node == NULL){
1258 reader->mode = XML_TEXTREADER_MODE_ERROR;
1259 reader->state = XML_TEXTREADER_ERROR;
1260 return(-1);
1262 reader->state = XML_TEXTREADER_ELEMENT;
1263 } else {
1264 if (reader->ctxt->myDoc != NULL) {
1265 reader->node = reader->ctxt->myDoc->children;
1267 if (reader->node == NULL)
1268 reader->node = reader->ctxt->nodeTab[0];
1269 reader->state = XML_TEXTREADER_ELEMENT;
1271 reader->depth = 0;
1272 reader->ctxt->parseMode = XML_PARSE_READER;
1273 goto node_found;
1275 oldstate = reader->state;
1276 olddepth = reader->ctxt->nodeNr;
1277 oldnode = reader->node;
1279 get_next_node:
1280 if (reader->node == NULL) {
1281 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1282 return(0);
1283 else
1284 return(-1);
1288 * If we are not backtracking on ancestors or examined nodes,
1289 * that the parser didn't finished or that we aren't at the end
1290 * of stream, continue processing.
1292 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1293 (reader->ctxt->nodeNr == olddepth) &&
1294 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1295 (reader->node->children == NULL) ||
1296 (reader->node->type == XML_ENTITY_REF_NODE) ||
1297 ((reader->node->children != NULL) &&
1298 (reader->node->children->type == XML_TEXT_NODE) &&
1299 (reader->node->children->next == NULL)) ||
1300 (reader->node->type == XML_DTD_NODE) ||
1301 (reader->node->type == XML_DOCUMENT_NODE) ||
1302 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1303 ((reader->ctxt->node == NULL) ||
1304 (reader->ctxt->node == reader->node) ||
1305 (reader->ctxt->node == reader->node->parent)) &&
1306 (reader->ctxt->instate != XML_PARSER_EOF)) {
1307 val = xmlTextReaderPushData(reader);
1308 if (val < 0){
1309 reader->mode = XML_TEXTREADER_MODE_ERROR;
1310 reader->state = XML_TEXTREADER_ERROR;
1311 return(-1);
1313 if (reader->node == NULL)
1314 goto node_end;
1316 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1317 if ((reader->node->children != NULL) &&
1318 (reader->node->type != XML_ENTITY_REF_NODE) &&
1319 (reader->node->type != XML_XINCLUDE_START) &&
1320 (reader->node->type != XML_DTD_NODE)) {
1321 reader->node = reader->node->children;
1322 reader->depth++;
1323 reader->state = XML_TEXTREADER_ELEMENT;
1324 goto node_found;
1327 if (reader->node->next != NULL) {
1328 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1329 (reader->node->type == XML_ELEMENT_NODE) &&
1330 (reader->node->children == NULL) &&
1331 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1332 #ifdef LIBXML_XINCLUDE_ENABLED
1333 && (reader->in_xinclude <= 0)
1334 #endif
1336 reader->state = XML_TEXTREADER_END;
1337 goto node_found;
1339 #ifdef LIBXML_REGEXP_ENABLED
1340 if ((reader->validate) &&
1341 (reader->node->type == XML_ELEMENT_NODE))
1342 xmlTextReaderValidatePop(reader);
1343 #endif /* LIBXML_REGEXP_ENABLED */
1344 if ((reader->preserves > 0) &&
1345 (reader->node->extra & NODE_IS_SPRESERVED))
1346 reader->preserves--;
1347 reader->node = reader->node->next;
1348 reader->state = XML_TEXTREADER_ELEMENT;
1351 * Cleanup of the old node
1353 if ((reader->preserves == 0) &&
1354 #ifdef LIBXML_XINCLUDE_ENABLED
1355 (reader->in_xinclude == 0) &&
1356 #endif
1357 (reader->entNr == 0) &&
1358 (reader->node->prev != NULL) &&
1359 (reader->node->prev->type != XML_DTD_NODE)) {
1360 xmlNodePtr tmp = reader->node->prev;
1361 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1362 if (oldnode == tmp)
1363 oldnode = NULL;
1364 xmlUnlinkNode(tmp);
1365 xmlTextReaderFreeNode(reader, tmp);
1369 goto node_found;
1371 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1372 (reader->node->type == XML_ELEMENT_NODE) &&
1373 (reader->node->children == NULL) &&
1374 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1375 reader->state = XML_TEXTREADER_END;
1376 goto node_found;
1378 #ifdef LIBXML_REGEXP_ENABLED
1379 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1380 xmlTextReaderValidatePop(reader);
1381 #endif /* LIBXML_REGEXP_ENABLED */
1382 if ((reader->preserves > 0) &&
1383 (reader->node->extra & NODE_IS_SPRESERVED))
1384 reader->preserves--;
1385 reader->node = reader->node->parent;
1386 if ((reader->node == NULL) ||
1387 (reader->node->type == XML_DOCUMENT_NODE) ||
1388 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1389 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1390 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1391 reader->state = XML_TEXTREADER_DONE;
1392 if (val != 0)
1393 return(-1);
1395 reader->node = NULL;
1396 reader->depth = -1;
1399 * Cleanup of the old node
1401 if ((oldnode != NULL) && (reader->preserves == 0) &&
1402 #ifdef LIBXML_XINCLUDE_ENABLED
1403 (reader->in_xinclude == 0) &&
1404 #endif
1405 (reader->entNr == 0) &&
1406 (oldnode->type != XML_DTD_NODE) &&
1407 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1408 xmlUnlinkNode(oldnode);
1409 xmlTextReaderFreeNode(reader, oldnode);
1412 goto node_end;
1414 if ((reader->preserves == 0) &&
1415 #ifdef LIBXML_XINCLUDE_ENABLED
1416 (reader->in_xinclude == 0) &&
1417 #endif
1418 (reader->entNr == 0) &&
1419 (reader->node->last != NULL) &&
1420 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1421 xmlNodePtr tmp = reader->node->last;
1422 xmlUnlinkNode(tmp);
1423 xmlTextReaderFreeNode(reader, tmp);
1425 reader->depth--;
1426 reader->state = XML_TEXTREADER_BACKTRACK;
1428 node_found:
1429 DUMP_READER
1432 * If we are in the middle of a piece of CDATA make sure it's finished
1434 if ((reader->node != NULL) &&
1435 (reader->node->next == NULL) &&
1436 ((reader->node->type == XML_TEXT_NODE) ||
1437 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1438 if (xmlTextReaderExpand(reader) == NULL)
1439 return -1;
1442 #ifdef LIBXML_XINCLUDE_ENABLED
1444 * Handle XInclude if asked for
1446 if ((reader->xinclude) && (reader->in_xinclude == 0) &&
1447 (reader->node != NULL) &&
1448 (reader->node->type == XML_ELEMENT_NODE) &&
1449 (reader->node->ns != NULL) &&
1450 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1451 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1452 if (reader->xincctxt == NULL) {
1453 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1454 xmlXIncludeSetFlags(reader->xincctxt,
1455 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1458 * expand that node and process it
1460 if (xmlTextReaderExpand(reader) == NULL)
1461 return -1;
1462 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1464 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1465 reader->in_xinclude++;
1466 goto get_next_node;
1468 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1469 reader->in_xinclude--;
1470 goto get_next_node;
1472 #endif
1474 * Handle entities enter and exit when in entity replacement mode
1476 if ((reader->node != NULL) &&
1477 (reader->node->type == XML_ENTITY_REF_NODE) &&
1478 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1479 if ((reader->node->children != NULL) &&
1480 (reader->node->children->type == XML_ENTITY_DECL) &&
1481 (reader->node->children->children != NULL)) {
1482 xmlTextReaderEntPush(reader, reader->node);
1483 reader->node = reader->node->children->children;
1485 #ifdef LIBXML_REGEXP_ENABLED
1486 } else if ((reader->node != NULL) &&
1487 (reader->node->type == XML_ENTITY_REF_NODE) &&
1488 (reader->ctxt != NULL) && (reader->validate)) {
1489 xmlTextReaderValidateEntity(reader);
1490 #endif /* LIBXML_REGEXP_ENABLED */
1492 if ((reader->node != NULL) &&
1493 (reader->node->type == XML_ENTITY_DECL) &&
1494 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1495 reader->node = xmlTextReaderEntPop(reader);
1496 reader->depth++;
1497 goto get_next_node;
1499 #ifdef LIBXML_REGEXP_ENABLED
1500 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1501 xmlNodePtr node = reader->node;
1503 if ((node->type == XML_ELEMENT_NODE) &&
1504 ((reader->state != XML_TEXTREADER_END) &&
1505 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1506 xmlTextReaderValidatePush(reader);
1507 } else if ((node->type == XML_TEXT_NODE) ||
1508 (node->type == XML_CDATA_SECTION_NODE)) {
1509 xmlTextReaderValidateCData(reader, node->content,
1510 xmlStrlen(node->content));
1513 #endif /* LIBXML_REGEXP_ENABLED */
1514 #ifdef LIBXML_PATTERN_ENABLED
1515 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1516 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1517 int i;
1518 for (i = 0;i < reader->patternNr;i++) {
1519 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1520 xmlTextReaderPreserve(reader);
1521 break;
1525 #endif /* LIBXML_PATTERN_ENABLED */
1526 #ifdef LIBXML_SCHEMAS_ENABLED
1527 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1528 (reader->xsdValidErrors == 0) &&
1529 (reader->xsdValidCtxt != NULL)) {
1530 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1532 #endif /* LIBXML_PATTERN_ENABLED */
1533 return(1);
1534 node_end:
1535 reader->state = XML_TEXTREADER_DONE;
1536 return(0);
1540 * xmlTextReaderReadState:
1541 * @reader: the xmlTextReaderPtr used
1543 * Gets the read state of the reader.
1545 * Returns the state value, or -1 in case of error
1548 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1549 if (reader == NULL)
1550 return(-1);
1551 return(reader->mode);
1555 * xmlTextReaderExpand:
1556 * @reader: the xmlTextReaderPtr used
1558 * Reads the contents of the current node and the full subtree. It then makes
1559 * the subtree available until the next xmlTextReaderRead() call
1561 * Returns a node pointer valid until the next xmlTextReaderRead() call
1562 * or NULL in case of error.
1564 xmlNodePtr
1565 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1566 if ((reader == NULL) || (reader->node == NULL))
1567 return(NULL);
1568 if (reader->doc != NULL)
1569 return(reader->node);
1570 if (reader->ctxt == NULL)
1571 return(NULL);
1572 if (xmlTextReaderDoExpand(reader) < 0)
1573 return(NULL);
1574 return(reader->node);
1578 * xmlTextReaderNext:
1579 * @reader: the xmlTextReaderPtr used
1581 * Skip to the node following the current one in document order while
1582 * avoiding the subtree if any.
1584 * Returns 1 if the node was read successfully, 0 if there is no more
1585 * nodes to read, or -1 in case of error
1588 xmlTextReaderNext(xmlTextReaderPtr reader) {
1589 int ret;
1590 xmlNodePtr cur;
1592 if (reader == NULL)
1593 return(-1);
1594 if (reader->doc != NULL)
1595 return(xmlTextReaderNextTree(reader));
1596 cur = reader->node;
1597 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1598 return(xmlTextReaderRead(reader));
1599 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1600 return(xmlTextReaderRead(reader));
1601 if (cur->extra & NODE_IS_EMPTY)
1602 return(xmlTextReaderRead(reader));
1603 do {
1604 ret = xmlTextReaderRead(reader);
1605 if (ret != 1)
1606 return(ret);
1607 } while (reader->node != cur);
1608 return(xmlTextReaderRead(reader));
1611 #ifdef LIBXML_WRITER_ENABLED
1613 * xmlTextReaderReadInnerXml:
1614 * @reader: the xmlTextReaderPtr used
1616 * Reads the contents of the current node, including child nodes and markup.
1618 * Returns a string containing the XML content, or NULL if the current node
1619 * is neither an element nor attribute, or has no child nodes. The
1620 * string must be deallocated by the caller.
1622 xmlChar *
1623 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1625 xmlChar *resbuf;
1626 xmlNodePtr node, cur_node;
1627 xmlBufferPtr buff, buff2;
1628 xmlDocPtr doc;
1630 if (xmlTextReaderExpand(reader) == NULL) {
1631 return NULL;
1633 doc = reader->node->doc;
1634 buff = xmlBufferCreate();
1635 if (buff == NULL)
1636 return NULL;
1637 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1638 for (cur_node = reader->node->children; cur_node != NULL;
1639 cur_node = cur_node->next) {
1640 /* XXX: Why is the node copied? */
1641 node = xmlDocCopyNode(cur_node, doc, 1);
1642 /* XXX: Why do we need a second buffer? */
1643 buff2 = xmlBufferCreate();
1644 xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT);
1645 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1646 xmlFreeNode(node);
1647 xmlBufferFree(buff2);
1648 xmlBufferFree(buff);
1649 return NULL;
1651 xmlBufferCat(buff, buff2->content);
1652 xmlFreeNode(node);
1653 xmlBufferFree(buff2);
1655 resbuf = buff->content;
1656 buff->content = NULL;
1658 xmlBufferFree(buff);
1659 return resbuf;
1661 #endif
1663 #ifdef LIBXML_WRITER_ENABLED
1665 * xmlTextReaderReadOuterXml:
1666 * @reader: the xmlTextReaderPtr used
1668 * Reads the contents of the current node, including child nodes and markup.
1670 * Returns a string containing the node and any XML content, or NULL if the
1671 * current node cannot be serialized. The string must be deallocated
1672 * by the caller.
1674 xmlChar *
1675 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1677 xmlChar *resbuf;
1678 xmlNodePtr node;
1679 xmlBufferPtr buff;
1680 xmlDocPtr doc;
1682 if (xmlTextReaderExpand(reader) == NULL) {
1683 return NULL;
1685 node = reader->node;
1686 doc = node->doc;
1687 /* XXX: Why is the node copied? */
1688 if (node->type == XML_DTD_NODE) {
1689 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1690 } else {
1691 node = xmlDocCopyNode(node, doc, 1);
1693 buff = xmlBufferCreate();
1694 xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT);
1695 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1696 xmlFreeNode(node);
1697 xmlBufferFree(buff);
1698 return NULL;
1701 resbuf = buff->content;
1702 buff->content = NULL;
1704 xmlFreeNode(node);
1705 xmlBufferFree(buff);
1706 return resbuf;
1708 #endif
1711 * xmlTextReaderReadString:
1712 * @reader: the xmlTextReaderPtr used
1714 * Reads the contents of an element or a text node as a string.
1716 * Returns a string containing the contents of the Element or Text node,
1717 * or NULL if the reader is positioned on any other type of node.
1718 * The string must be deallocated by the caller.
1720 xmlChar *
1721 xmlTextReaderReadString(xmlTextReaderPtr reader)
1723 xmlNodePtr node;
1725 if ((reader == NULL) || (reader->node == NULL))
1726 return(NULL);
1728 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1729 switch (node->type) {
1730 case XML_TEXT_NODE:
1731 if (node->content != NULL)
1732 return(xmlStrdup(node->content));
1733 break;
1734 case XML_ELEMENT_NODE:
1735 if (xmlTextReaderDoExpand(reader) != -1) {
1736 return xmlTextReaderCollectSiblings(node->children);
1738 break;
1739 case XML_ATTRIBUTE_NODE:
1740 TODO
1741 break;
1742 default:
1743 break;
1745 return(NULL);
1748 #if 0
1750 * xmlTextReaderReadBase64:
1751 * @reader: the xmlTextReaderPtr used
1752 * @array: a byte array to store the content.
1753 * @offset: the zero-based index into array where the method should
1754 * begin to write.
1755 * @len: the number of bytes to write.
1757 * Reads and decodes the Base64 encoded contents of an element and
1758 * stores the result in a byte buffer.
1760 * Returns the number of bytes written to array, or zero if the current
1761 * instance is not positioned on an element or -1 in case of error.
1764 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1765 unsigned char *array ATTRIBUTE_UNUSED,
1766 int offset ATTRIBUTE_UNUSED,
1767 int len ATTRIBUTE_UNUSED) {
1768 if ((reader == NULL) || (reader->ctxt == NULL))
1769 return(-1);
1770 if (reader->ctxt->wellFormed != 1)
1771 return(-1);
1773 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1774 return(0);
1775 TODO
1776 return(0);
1780 * xmlTextReaderReadBinHex:
1781 * @reader: the xmlTextReaderPtr used
1782 * @array: a byte array to store the content.
1783 * @offset: the zero-based index into array where the method should
1784 * begin to write.
1785 * @len: the number of bytes to write.
1787 * Reads and decodes the BinHex encoded contents of an element and
1788 * stores the result in a byte buffer.
1790 * Returns the number of bytes written to array, or zero if the current
1791 * instance is not positioned on an element or -1 in case of error.
1794 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1795 unsigned char *array ATTRIBUTE_UNUSED,
1796 int offset ATTRIBUTE_UNUSED,
1797 int len ATTRIBUTE_UNUSED) {
1798 if ((reader == NULL) || (reader->ctxt == NULL))
1799 return(-1);
1800 if (reader->ctxt->wellFormed != 1)
1801 return(-1);
1803 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1804 return(0);
1805 TODO
1806 return(0);
1808 #endif
1810 /************************************************************************
1812 * Operating on a preparsed tree *
1814 ************************************************************************/
1815 static int
1816 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1818 if (reader == NULL)
1819 return(-1);
1821 if (reader->state == XML_TEXTREADER_END)
1822 return(0);
1824 if (reader->node == NULL) {
1825 if (reader->doc->children == NULL) {
1826 reader->state = XML_TEXTREADER_END;
1827 return(0);
1830 reader->node = reader->doc->children;
1831 reader->state = XML_TEXTREADER_START;
1832 return(1);
1835 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1836 /* Here removed traversal to child, because we want to skip the subtree,
1837 replace with traversal to sibling to skip subtree */
1838 if (reader->node->next != 0) {
1839 /* Move to sibling if present,skipping sub-tree */
1840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1845 /* if reader->node->next is NULL mean no subtree for current node,
1846 so need to move to sibling of parent node if present */
1847 reader->state = XML_TEXTREADER_BACKTRACK;
1848 /* This will move to parent if present */
1849 xmlTextReaderRead(reader);
1852 if (reader->node->next != 0) {
1853 reader->node = reader->node->next;
1854 reader->state = XML_TEXTREADER_START;
1855 return(1);
1858 if (reader->node->parent != 0) {
1859 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1860 reader->state = XML_TEXTREADER_END;
1861 return(0);
1864 reader->node = reader->node->parent;
1865 reader->depth--;
1866 reader->state = XML_TEXTREADER_BACKTRACK;
1867 /* Repeat process to move to sibling of parent node if present */
1868 xmlTextReaderNextTree(reader);
1871 reader->state = XML_TEXTREADER_END;
1873 return(1);
1877 * xmlTextReaderReadTree:
1878 * @reader: the xmlTextReaderPtr used
1880 * Moves the position of the current instance to the next node in
1881 * the stream, exposing its properties.
1883 * Returns 1 if the node was read successfully, 0 if there is no more
1884 * nodes to read, or -1 in case of error
1886 static int
1887 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1888 if (reader->state == XML_TEXTREADER_END)
1889 return(0);
1891 next_node:
1892 if (reader->node == NULL) {
1893 if (reader->doc->children == NULL) {
1894 reader->state = XML_TEXTREADER_END;
1895 return(0);
1898 reader->node = reader->doc->children;
1899 reader->state = XML_TEXTREADER_START;
1900 goto found_node;
1903 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1904 (reader->node->type != XML_DTD_NODE) &&
1905 (reader->node->type != XML_XINCLUDE_START) &&
1906 (reader->node->type != XML_ENTITY_REF_NODE)) {
1907 if (reader->node->children != NULL) {
1908 reader->node = reader->node->children;
1909 reader->depth++;
1910 reader->state = XML_TEXTREADER_START;
1911 goto found_node;
1914 if (reader->node->type == XML_ATTRIBUTE_NODE) {
1915 reader->state = XML_TEXTREADER_BACKTRACK;
1916 goto found_node;
1920 if (reader->node->next != NULL) {
1921 reader->node = reader->node->next;
1922 reader->state = XML_TEXTREADER_START;
1923 goto found_node;
1926 if (reader->node->parent != NULL) {
1927 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1928 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1929 reader->state = XML_TEXTREADER_END;
1930 return(0);
1933 reader->node = reader->node->parent;
1934 reader->depth--;
1935 reader->state = XML_TEXTREADER_BACKTRACK;
1936 goto found_node;
1939 reader->state = XML_TEXTREADER_END;
1941 found_node:
1942 if ((reader->node->type == XML_XINCLUDE_START) ||
1943 (reader->node->type == XML_XINCLUDE_END))
1944 goto next_node;
1946 return(1);
1950 * xmlTextReaderNextSibling:
1951 * @reader: the xmlTextReaderPtr used
1953 * Skip to the node following the current one in document order while
1954 * avoiding the subtree if any.
1955 * Currently implemented only for Readers built on a document
1957 * Returns 1 if the node was read successfully, 0 if there is no more
1958 * nodes to read, or -1 in case of error
1961 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1962 if (reader == NULL)
1963 return(-1);
1964 if (reader->doc == NULL) {
1965 /* TODO */
1966 return(-1);
1969 if (reader->state == XML_TEXTREADER_END)
1970 return(0);
1972 if (reader->node == NULL)
1973 return(xmlTextReaderNextTree(reader));
1975 if (reader->node->next != NULL) {
1976 reader->node = reader->node->next;
1977 reader->state = XML_TEXTREADER_START;
1978 return(1);
1981 return(0);
1984 /************************************************************************
1986 * Constructor and destructors *
1988 ************************************************************************/
1990 * xmlNewTextReader:
1991 * @input: the xmlParserInputBufferPtr used to read data
1992 * @URI: the URI information for the source if available
1994 * Create an xmlTextReader structure fed with @input
1996 * Returns the new xmlTextReaderPtr or NULL in case of error
1998 xmlTextReaderPtr
1999 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2000 xmlTextReaderPtr ret;
2002 if (input == NULL)
2003 return(NULL);
2004 ret = xmlMalloc(sizeof(xmlTextReader));
2005 if (ret == NULL) {
2006 xmlGenericError(xmlGenericErrorContext,
2007 "xmlNewTextReader : malloc failed\n");
2008 return(NULL);
2010 memset(ret, 0, sizeof(xmlTextReader));
2011 ret->doc = NULL;
2012 ret->entTab = NULL;
2013 ret->entMax = 0;
2014 ret->entNr = 0;
2015 ret->input = input;
2016 ret->buffer = xmlBufCreateSize(100);
2017 if (ret->buffer == NULL) {
2018 xmlFree(ret);
2019 xmlGenericError(xmlGenericErrorContext,
2020 "xmlNewTextReader : malloc failed\n");
2021 return(NULL);
2023 /* no operation on a reader should require a huge buffer */
2024 xmlBufSetAllocationScheme(ret->buffer,
2025 XML_BUFFER_ALLOC_DOUBLEIT);
2026 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2027 if (ret->sax == NULL) {
2028 xmlBufFree(ret->buffer);
2029 xmlFree(ret);
2030 xmlGenericError(xmlGenericErrorContext,
2031 "xmlNewTextReader : malloc failed\n");
2032 return(NULL);
2034 xmlSAXVersion(ret->sax, 2);
2035 ret->startElement = ret->sax->startElement;
2036 ret->sax->startElement = xmlTextReaderStartElement;
2037 ret->endElement = ret->sax->endElement;
2038 ret->sax->endElement = xmlTextReaderEndElement;
2039 #ifdef LIBXML_SAX1_ENABLED
2040 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2041 #endif /* LIBXML_SAX1_ENABLED */
2042 ret->startElementNs = ret->sax->startElementNs;
2043 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2044 ret->endElementNs = ret->sax->endElementNs;
2045 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2046 #ifdef LIBXML_SAX1_ENABLED
2047 } else {
2048 ret->startElementNs = NULL;
2049 ret->endElementNs = NULL;
2051 #endif /* LIBXML_SAX1_ENABLED */
2052 ret->characters = ret->sax->characters;
2053 ret->sax->characters = xmlTextReaderCharacters;
2054 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2055 ret->cdataBlock = ret->sax->cdataBlock;
2056 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2058 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2059 ret->node = NULL;
2060 ret->curnode = NULL;
2061 if (xmlBufUse(ret->input->buffer) < 4) {
2062 xmlParserInputBufferRead(input, 4);
2064 if (xmlBufUse(ret->input->buffer) >= 4) {
2065 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2066 (const char *) xmlBufContent(ret->input->buffer),
2067 4, URI);
2068 ret->base = 0;
2069 ret->cur = 4;
2070 } else {
2071 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2072 ret->base = 0;
2073 ret->cur = 0;
2076 if (ret->ctxt == NULL) {
2077 xmlGenericError(xmlGenericErrorContext,
2078 "xmlNewTextReader : malloc failed\n");
2079 xmlBufFree(ret->buffer);
2080 xmlFree(ret->sax);
2081 xmlFree(ret);
2082 return(NULL);
2084 ret->ctxt->parseMode = XML_PARSE_READER;
2085 ret->ctxt->_private = ret;
2086 ret->ctxt->linenumbers = 1;
2087 ret->ctxt->dictNames = 1;
2088 ret->allocs = XML_TEXTREADER_CTXT;
2090 * use the parser dictionary to allocate all elements and attributes names
2092 ret->ctxt->docdict = 1;
2093 ret->dict = ret->ctxt->dict;
2094 #ifdef LIBXML_XINCLUDE_ENABLED
2095 ret->xinclude = 0;
2096 #endif
2097 #ifdef LIBXML_PATTERN_ENABLED
2098 ret->patternMax = 0;
2099 ret->patternTab = NULL;
2100 #endif
2101 return(ret);
2105 * xmlNewTextReaderFilename:
2106 * @URI: the URI of the resource to process
2108 * Create an xmlTextReader structure fed with the resource at @URI
2110 * Returns the new xmlTextReaderPtr or NULL in case of error
2112 xmlTextReaderPtr
2113 xmlNewTextReaderFilename(const char *URI) {
2114 xmlParserInputBufferPtr input;
2115 xmlTextReaderPtr ret;
2116 char *directory = NULL;
2118 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2119 if (input == NULL)
2120 return(NULL);
2121 ret = xmlNewTextReader(input, URI);
2122 if (ret == NULL) {
2123 xmlFreeParserInputBuffer(input);
2124 return(NULL);
2126 ret->allocs |= XML_TEXTREADER_INPUT;
2127 if (ret->ctxt->directory == NULL)
2128 directory = xmlParserGetDirectory(URI);
2129 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2130 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2131 if (directory != NULL)
2132 xmlFree(directory);
2133 return(ret);
2137 * xmlFreeTextReader:
2138 * @reader: the xmlTextReaderPtr
2140 * Deallocate all the resources associated to the reader
2142 void
2143 xmlFreeTextReader(xmlTextReaderPtr reader) {
2144 if (reader == NULL)
2145 return;
2146 #ifdef LIBXML_SCHEMAS_ENABLED
2147 if (reader->rngSchemas != NULL) {
2148 xmlRelaxNGFree(reader->rngSchemas);
2149 reader->rngSchemas = NULL;
2151 if (reader->rngValidCtxt != NULL) {
2152 if (! reader->rngPreserveCtxt)
2153 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2154 reader->rngValidCtxt = NULL;
2156 if (reader->xsdPlug != NULL) {
2157 xmlSchemaSAXUnplug(reader->xsdPlug);
2158 reader->xsdPlug = NULL;
2160 if (reader->xsdValidCtxt != NULL) {
2161 if (! reader->xsdPreserveCtxt)
2162 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2163 reader->xsdValidCtxt = NULL;
2165 if (reader->xsdSchemas != NULL) {
2166 xmlSchemaFree(reader->xsdSchemas);
2167 reader->xsdSchemas = NULL;
2169 #endif
2170 #ifdef LIBXML_XINCLUDE_ENABLED
2171 if (reader->xincctxt != NULL)
2172 xmlXIncludeFreeContext(reader->xincctxt);
2173 #endif
2174 #ifdef LIBXML_PATTERN_ENABLED
2175 if (reader->patternTab != NULL) {
2176 int i;
2177 for (i = 0;i < reader->patternNr;i++) {
2178 if (reader->patternTab[i] != NULL)
2179 xmlFreePattern(reader->patternTab[i]);
2181 xmlFree(reader->patternTab);
2183 #endif
2184 if (reader->mode != XML_TEXTREADER_MODE_CLOSED)
2185 xmlTextReaderClose(reader);
2186 if (reader->ctxt != NULL) {
2187 if (reader->dict == reader->ctxt->dict)
2188 reader->dict = NULL;
2189 if (reader->allocs & XML_TEXTREADER_CTXT)
2190 xmlFreeParserCtxt(reader->ctxt);
2192 if (reader->sax != NULL)
2193 xmlFree(reader->sax);
2194 if (reader->buffer != NULL)
2195 xmlBufFree(reader->buffer);
2196 if (reader->entTab != NULL)
2197 xmlFree(reader->entTab);
2198 if (reader->dict != NULL)
2199 xmlDictFree(reader->dict);
2200 xmlFree(reader);
2203 /************************************************************************
2205 * Methods for XmlTextReader *
2207 ************************************************************************/
2209 * xmlTextReaderClose:
2210 * @reader: the xmlTextReaderPtr used
2212 * This method releases any resources allocated by the current instance
2213 * changes the state to Closed and close any underlying input.
2215 * Returns 0 or -1 in case of error
2218 xmlTextReaderClose(xmlTextReaderPtr reader) {
2219 if (reader == NULL)
2220 return(-1);
2221 reader->node = NULL;
2222 reader->curnode = NULL;
2223 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2224 if (reader->faketext != NULL) {
2225 xmlFreeNode(reader->faketext);
2226 reader->faketext = NULL;
2228 if (reader->ctxt != NULL) {
2229 #ifdef LIBXML_VALID_ENABLED
2230 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2231 (reader->ctxt->vctxt.vstateMax > 0)){
2232 #ifdef LIBXML_REGEXP_ENABLED
2233 while (reader->ctxt->vctxt.vstateNr > 0)
2234 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2235 #endif /* LIBXML_REGEXP_ENABLED */
2236 xmlFree(reader->ctxt->vctxt.vstateTab);
2237 reader->ctxt->vctxt.vstateTab = NULL;
2238 reader->ctxt->vctxt.vstateMax = 0;
2240 #endif /* LIBXML_VALID_ENABLED */
2241 xmlStopParser(reader->ctxt);
2242 if (reader->ctxt->myDoc != NULL) {
2243 if (reader->preserve == 0)
2244 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2245 reader->ctxt->myDoc = NULL;
2248 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2249 xmlFreeParserInputBuffer(reader->input);
2250 reader->allocs -= XML_TEXTREADER_INPUT;
2252 return(0);
2256 * xmlTextReaderGetAttributeNo:
2257 * @reader: the xmlTextReaderPtr used
2258 * @no: the zero-based index of the attribute relative to the containing element
2260 * Provides the value of the attribute with the specified index relative
2261 * to the containing element.
2263 * Returns a string containing the value of the specified attribute, or NULL
2264 * in case of error. The string must be deallocated by the caller.
2266 xmlChar *
2267 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2268 xmlChar *ret;
2269 int i;
2270 xmlAttrPtr cur;
2271 xmlNsPtr ns;
2273 if (reader == NULL)
2274 return(NULL);
2275 if (reader->node == NULL)
2276 return(NULL);
2277 if (reader->curnode != NULL)
2278 return(NULL);
2279 /* TODO: handle the xmlDecl */
2280 if (reader->node->type != XML_ELEMENT_NODE)
2281 return(NULL);
2283 ns = reader->node->nsDef;
2284 for (i = 0;(i < no) && (ns != NULL);i++) {
2285 ns = ns->next;
2287 if (ns != NULL)
2288 return(xmlStrdup(ns->href));
2290 cur = reader->node->properties;
2291 if (cur == NULL)
2292 return(NULL);
2293 for (;i < no;i++) {
2294 cur = cur->next;
2295 if (cur == NULL)
2296 return(NULL);
2298 /* TODO walk the DTD if present */
2300 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2301 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2302 return(ret);
2306 * xmlTextReaderGetAttribute:
2307 * @reader: the xmlTextReaderPtr used
2308 * @name: the qualified name of the attribute.
2310 * Provides the value of the attribute with the specified qualified name.
2312 * Returns a string containing the value of the specified attribute, or NULL
2313 * in case of error. The string must be deallocated by the caller.
2315 xmlChar *
2316 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2317 xmlChar *prefix = NULL;
2318 xmlChar *localname;
2319 xmlNsPtr ns;
2320 xmlChar *ret = NULL;
2322 if ((reader == NULL) || (name == NULL))
2323 return(NULL);
2324 if (reader->node == NULL)
2325 return(NULL);
2326 if (reader->curnode != NULL)
2327 return(NULL);
2329 /* TODO: handle the xmlDecl */
2330 if (reader->node->type != XML_ELEMENT_NODE)
2331 return(NULL);
2333 localname = xmlSplitQName2(name, &prefix);
2334 if (localname == NULL) {
2336 * Namespace default decl
2338 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2339 ns = reader->node->nsDef;
2340 while (ns != NULL) {
2341 if (ns->prefix == NULL) {
2342 return(xmlStrdup(ns->href));
2344 ns = ns->next;
2346 return NULL;
2348 return(xmlGetNoNsProp(reader->node, name));
2352 * Namespace default decl
2354 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2355 ns = reader->node->nsDef;
2356 while (ns != NULL) {
2357 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2358 ret = xmlStrdup(ns->href);
2359 break;
2361 ns = ns->next;
2363 } else {
2364 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2365 if (ns != NULL)
2366 ret = xmlGetNsProp(reader->node, localname, ns->href);
2369 xmlFree(localname);
2370 if (prefix != NULL)
2371 xmlFree(prefix);
2372 return(ret);
2377 * xmlTextReaderGetAttributeNs:
2378 * @reader: the xmlTextReaderPtr used
2379 * @localName: the local name of the attribute.
2380 * @namespaceURI: the namespace URI of the attribute.
2382 * Provides the value of the specified attribute
2384 * Returns a string containing the value of the specified attribute, or NULL
2385 * in case of error. The string must be deallocated by the caller.
2387 xmlChar *
2388 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2389 const xmlChar *namespaceURI) {
2390 xmlChar *prefix = NULL;
2391 xmlNsPtr ns;
2393 if ((reader == NULL) || (localName == NULL))
2394 return(NULL);
2395 if (reader->node == NULL)
2396 return(NULL);
2397 if (reader->curnode != NULL)
2398 return(NULL);
2400 /* TODO: handle the xmlDecl */
2401 if (reader->node->type != XML_ELEMENT_NODE)
2402 return(NULL);
2404 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2405 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2406 prefix = BAD_CAST localName;
2408 ns = reader->node->nsDef;
2409 while (ns != NULL) {
2410 if ((prefix == NULL && ns->prefix == NULL) ||
2411 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2412 return xmlStrdup(ns->href);
2414 ns = ns->next;
2416 return NULL;
2419 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2423 * xmlTextReaderGetRemainder:
2424 * @reader: the xmlTextReaderPtr used
2426 * Method to get the remainder of the buffered XML. this method stops the
2427 * parser, set its state to End Of File and return the input stream with
2428 * what is left that the parser did not use.
2430 * The implementation is not good, the parser certainly progressed past
2431 * what's left in reader->input, and there is an allocation problem. Best
2432 * would be to rewrite it differently.
2434 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2435 * in case of error.
2437 xmlParserInputBufferPtr
2438 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2439 xmlParserInputBufferPtr ret = NULL;
2441 if (reader == NULL)
2442 return(NULL);
2443 if (reader->node == NULL)
2444 return(NULL);
2446 reader->node = NULL;
2447 reader->curnode = NULL;
2448 reader->mode = XML_TEXTREADER_MODE_EOF;
2449 if (reader->ctxt != NULL) {
2450 xmlStopParser(reader->ctxt);
2451 if (reader->ctxt->myDoc != NULL) {
2452 if (reader->preserve == 0)
2453 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2454 reader->ctxt->myDoc = NULL;
2457 if (reader->allocs & XML_TEXTREADER_INPUT) {
2458 ret = reader->input;
2459 reader->input = NULL;
2460 reader->allocs -= XML_TEXTREADER_INPUT;
2461 } else {
2463 * Hum, one may need to duplicate the data structure because
2464 * without reference counting the input may be freed twice:
2465 * - by the layer which allocated it.
2466 * - by the layer to which would have been returned to.
2468 TODO
2469 return(NULL);
2471 return(ret);
2475 * xmlTextReaderLookupNamespace:
2476 * @reader: the xmlTextReaderPtr used
2477 * @prefix: the prefix whose namespace URI is to be resolved. To return
2478 * the default namespace, specify NULL
2480 * Resolves a namespace prefix in the scope of the current element.
2482 * Returns a string containing the namespace URI to which the prefix maps
2483 * or NULL in case of error. The string must be deallocated by the caller.
2485 xmlChar *
2486 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2487 xmlNsPtr ns;
2489 if (reader == NULL)
2490 return(NULL);
2491 if (reader->node == NULL)
2492 return(NULL);
2494 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2495 if (ns == NULL)
2496 return(NULL);
2497 return(xmlStrdup(ns->href));
2501 * xmlTextReaderMoveToAttributeNo:
2502 * @reader: the xmlTextReaderPtr used
2503 * @no: the zero-based index of the attribute relative to the containing
2504 * element.
2506 * Moves the position of the current instance to the attribute with
2507 * the specified index relative to the containing element.
2509 * Returns 1 in case of success, -1 in case of error, 0 if not found
2512 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2513 int i;
2514 xmlAttrPtr cur;
2515 xmlNsPtr ns;
2517 if (reader == NULL)
2518 return(-1);
2519 if (reader->node == NULL)
2520 return(-1);
2521 /* TODO: handle the xmlDecl */
2522 if (reader->node->type != XML_ELEMENT_NODE)
2523 return(-1);
2525 reader->curnode = NULL;
2527 ns = reader->node->nsDef;
2528 for (i = 0;(i < no) && (ns != NULL);i++) {
2529 ns = ns->next;
2531 if (ns != NULL) {
2532 reader->curnode = (xmlNodePtr) ns;
2533 return(1);
2536 cur = reader->node->properties;
2537 if (cur == NULL)
2538 return(0);
2539 for (;i < no;i++) {
2540 cur = cur->next;
2541 if (cur == NULL)
2542 return(0);
2544 /* TODO walk the DTD if present */
2546 reader->curnode = (xmlNodePtr) cur;
2547 return(1);
2551 * xmlTextReaderMoveToAttribute:
2552 * @reader: the xmlTextReaderPtr used
2553 * @name: the qualified name of the attribute.
2555 * Moves the position of the current instance to the attribute with
2556 * the specified qualified name.
2558 * Returns 1 in case of success, -1 in case of error, 0 if not found
2561 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2562 xmlChar *prefix = NULL;
2563 xmlChar *localname;
2564 xmlNsPtr ns;
2565 xmlAttrPtr prop;
2567 if ((reader == NULL) || (name == NULL))
2568 return(-1);
2569 if (reader->node == NULL)
2570 return(-1);
2572 /* TODO: handle the xmlDecl */
2573 if (reader->node->type != XML_ELEMENT_NODE)
2574 return(0);
2576 localname = xmlSplitQName2(name, &prefix);
2577 if (localname == NULL) {
2579 * Namespace default decl
2581 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2582 ns = reader->node->nsDef;
2583 while (ns != NULL) {
2584 if (ns->prefix == NULL) {
2585 reader->curnode = (xmlNodePtr) ns;
2586 return(1);
2588 ns = ns->next;
2590 return(0);
2593 prop = reader->node->properties;
2594 while (prop != NULL) {
2596 * One need to have
2597 * - same attribute names
2598 * - and the attribute carrying that namespace
2600 if ((xmlStrEqual(prop->name, name)) &&
2601 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2602 reader->curnode = (xmlNodePtr) prop;
2603 return(1);
2605 prop = prop->next;
2607 return(0);
2611 * Namespace default decl
2613 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2614 ns = reader->node->nsDef;
2615 while (ns != NULL) {
2616 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2617 reader->curnode = (xmlNodePtr) ns;
2618 goto found;
2620 ns = ns->next;
2622 goto not_found;
2624 prop = reader->node->properties;
2625 while (prop != NULL) {
2627 * One need to have
2628 * - same attribute names
2629 * - and the attribute carrying that namespace
2631 if ((xmlStrEqual(prop->name, localname)) &&
2632 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2633 reader->curnode = (xmlNodePtr) prop;
2634 goto found;
2636 prop = prop->next;
2638 not_found:
2639 if (localname != NULL)
2640 xmlFree(localname);
2641 if (prefix != NULL)
2642 xmlFree(prefix);
2643 return(0);
2645 found:
2646 if (localname != NULL)
2647 xmlFree(localname);
2648 if (prefix != NULL)
2649 xmlFree(prefix);
2650 return(1);
2654 * xmlTextReaderMoveToAttributeNs:
2655 * @reader: the xmlTextReaderPtr used
2656 * @localName: the local name of the attribute.
2657 * @namespaceURI: the namespace URI of the attribute.
2659 * Moves the position of the current instance to the attribute with the
2660 * specified local name and namespace URI.
2662 * Returns 1 in case of success, -1 in case of error, 0 if not found
2665 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2666 const xmlChar *localName, const xmlChar *namespaceURI) {
2667 xmlAttrPtr prop;
2668 xmlNodePtr node;
2669 xmlNsPtr ns;
2670 xmlChar *prefix = NULL;
2672 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2673 return(-1);
2674 if (reader->node == NULL)
2675 return(-1);
2676 if (reader->node->type != XML_ELEMENT_NODE)
2677 return(0);
2678 node = reader->node;
2680 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2681 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2682 prefix = BAD_CAST localName;
2684 ns = reader->node->nsDef;
2685 while (ns != NULL) {
2686 if ((prefix == NULL && ns->prefix == NULL) ||
2687 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2688 reader->curnode = (xmlNodePtr) ns;
2689 return(1);
2691 ns = ns->next;
2693 return(0);
2696 prop = node->properties;
2697 while (prop != NULL) {
2699 * One need to have
2700 * - same attribute names
2701 * - and the attribute carrying that namespace
2703 if (xmlStrEqual(prop->name, localName) &&
2704 ((prop->ns != NULL) &&
2705 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2706 reader->curnode = (xmlNodePtr) prop;
2707 return(1);
2709 prop = prop->next;
2711 return(0);
2715 * xmlTextReaderMoveToFirstAttribute:
2716 * @reader: the xmlTextReaderPtr used
2718 * Moves the position of the current instance to the first attribute
2719 * associated with the current node.
2721 * Returns 1 in case of success, -1 in case of error, 0 if not found
2724 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2725 if (reader == NULL)
2726 return(-1);
2727 if (reader->node == NULL)
2728 return(-1);
2729 if (reader->node->type != XML_ELEMENT_NODE)
2730 return(0);
2732 if (reader->node->nsDef != NULL) {
2733 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2734 return(1);
2736 if (reader->node->properties != NULL) {
2737 reader->curnode = (xmlNodePtr) reader->node->properties;
2738 return(1);
2740 return(0);
2744 * xmlTextReaderMoveToNextAttribute:
2745 * @reader: the xmlTextReaderPtr used
2747 * Moves the position of the current instance to the next attribute
2748 * associated with the current node.
2750 * Returns 1 in case of success, -1 in case of error, 0 if not found
2753 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2754 if (reader == NULL)
2755 return(-1);
2756 if (reader->node == NULL)
2757 return(-1);
2758 if (reader->node->type != XML_ELEMENT_NODE)
2759 return(0);
2760 if (reader->curnode == NULL)
2761 return(xmlTextReaderMoveToFirstAttribute(reader));
2763 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2764 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2765 if (ns->next != NULL) {
2766 reader->curnode = (xmlNodePtr) ns->next;
2767 return(1);
2769 if (reader->node->properties != NULL) {
2770 reader->curnode = (xmlNodePtr) reader->node->properties;
2771 return(1);
2773 return(0);
2774 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2775 (reader->curnode->next != NULL)) {
2776 reader->curnode = reader->curnode->next;
2777 return(1);
2779 return(0);
2783 * xmlTextReaderMoveToElement:
2784 * @reader: the xmlTextReaderPtr used
2786 * Moves the position of the current instance to the node that
2787 * contains the current Attribute node.
2789 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2792 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2793 if (reader == NULL)
2794 return(-1);
2795 if (reader->node == NULL)
2796 return(-1);
2797 if (reader->node->type != XML_ELEMENT_NODE)
2798 return(0);
2799 if (reader->curnode != NULL) {
2800 reader->curnode = NULL;
2801 return(1);
2803 return(0);
2807 * xmlTextReaderReadAttributeValue:
2808 * @reader: the xmlTextReaderPtr used
2810 * Parses an attribute value into one or more Text and EntityReference nodes.
2812 * Returns 1 in case of success, 0 if the reader was not positioned on an
2813 * attribute node or all the attribute values have been read, or -1
2814 * in case of error.
2817 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2818 if (reader == NULL)
2819 return(-1);
2820 if (reader->node == NULL)
2821 return(-1);
2822 if (reader->curnode == NULL)
2823 return(0);
2824 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2825 if (reader->curnode->children == NULL)
2826 return(0);
2827 reader->curnode = reader->curnode->children;
2828 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2829 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2831 if (reader->faketext == NULL) {
2832 reader->faketext = xmlNewDocText(reader->node->doc,
2833 ns->href);
2834 } else {
2835 if ((reader->faketext->content != NULL) &&
2836 (reader->faketext->content !=
2837 (xmlChar *) &(reader->faketext->properties)))
2838 xmlFree(reader->faketext->content);
2839 reader->faketext->content = xmlStrdup(ns->href);
2841 reader->curnode = reader->faketext;
2842 } else {
2843 if (reader->curnode->next == NULL)
2844 return(0);
2845 reader->curnode = reader->curnode->next;
2847 return(1);
2851 * xmlTextReaderConstEncoding:
2852 * @reader: the xmlTextReaderPtr used
2854 * Determine the encoding of the document being read.
2856 * Returns a string containing the encoding of the document or NULL in
2857 * case of error. The string is deallocated with the reader.
2859 const xmlChar *
2860 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2861 xmlDocPtr doc = NULL;
2862 if (reader == NULL)
2863 return(NULL);
2864 if (reader->doc != NULL)
2865 doc = reader->doc;
2866 else if (reader->ctxt != NULL)
2867 doc = reader->ctxt->myDoc;
2868 if (doc == NULL)
2869 return(NULL);
2871 if (doc->encoding == NULL)
2872 return(NULL);
2873 else
2874 return(CONSTSTR(doc->encoding));
2878 /************************************************************************
2880 * Access API to the current node *
2882 ************************************************************************/
2884 * xmlTextReaderAttributeCount:
2885 * @reader: the xmlTextReaderPtr used
2887 * Provides the number of attributes of the current node
2889 * Returns 0 i no attributes, -1 in case of error or the attribute count
2892 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2893 int ret;
2894 xmlAttrPtr attr;
2895 xmlNsPtr ns;
2896 xmlNodePtr node;
2898 if (reader == NULL)
2899 return(-1);
2900 if (reader->node == NULL)
2901 return(0);
2903 if (reader->curnode != NULL)
2904 node = reader->curnode;
2905 else
2906 node = reader->node;
2908 if (node->type != XML_ELEMENT_NODE)
2909 return(0);
2910 if ((reader->state == XML_TEXTREADER_END) ||
2911 (reader->state == XML_TEXTREADER_BACKTRACK))
2912 return(0);
2913 ret = 0;
2914 attr = node->properties;
2915 while (attr != NULL) {
2916 ret++;
2917 attr = attr->next;
2919 ns = node->nsDef;
2920 while (ns != NULL) {
2921 ret++;
2922 ns = ns->next;
2924 return(ret);
2928 * xmlTextReaderNodeType:
2929 * @reader: the xmlTextReaderPtr used
2931 * Get the node type of the current node
2932 * Reference:
2933 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
2935 * Returns the xmlReaderTypes of the current node or -1 in case of error
2938 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
2939 xmlNodePtr node;
2941 if (reader == NULL)
2942 return(-1);
2943 if (reader->node == NULL)
2944 return(XML_READER_TYPE_NONE);
2945 if (reader->curnode != NULL)
2946 node = reader->curnode;
2947 else
2948 node = reader->node;
2949 switch (node->type) {
2950 case XML_ELEMENT_NODE:
2951 if ((reader->state == XML_TEXTREADER_END) ||
2952 (reader->state == XML_TEXTREADER_BACKTRACK))
2953 return(XML_READER_TYPE_END_ELEMENT);
2954 return(XML_READER_TYPE_ELEMENT);
2955 case XML_NAMESPACE_DECL:
2956 case XML_ATTRIBUTE_NODE:
2957 return(XML_READER_TYPE_ATTRIBUTE);
2958 case XML_TEXT_NODE:
2959 if (xmlIsBlankNode(reader->node)) {
2960 if (xmlNodeGetSpacePreserve(reader->node))
2961 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2962 else
2963 return(XML_READER_TYPE_WHITESPACE);
2964 } else {
2965 return(XML_READER_TYPE_TEXT);
2967 case XML_CDATA_SECTION_NODE:
2968 return(XML_READER_TYPE_CDATA);
2969 case XML_ENTITY_REF_NODE:
2970 return(XML_READER_TYPE_ENTITY_REFERENCE);
2971 case XML_ENTITY_NODE:
2972 return(XML_READER_TYPE_ENTITY);
2973 case XML_PI_NODE:
2974 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
2975 case XML_COMMENT_NODE:
2976 return(XML_READER_TYPE_COMMENT);
2977 case XML_DOCUMENT_NODE:
2978 case XML_HTML_DOCUMENT_NODE:
2979 return(XML_READER_TYPE_DOCUMENT);
2980 case XML_DOCUMENT_FRAG_NODE:
2981 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
2982 case XML_NOTATION_NODE:
2983 return(XML_READER_TYPE_NOTATION);
2984 case XML_DOCUMENT_TYPE_NODE:
2985 case XML_DTD_NODE:
2986 return(XML_READER_TYPE_DOCUMENT_TYPE);
2988 case XML_ELEMENT_DECL:
2989 case XML_ATTRIBUTE_DECL:
2990 case XML_ENTITY_DECL:
2991 case XML_XINCLUDE_START:
2992 case XML_XINCLUDE_END:
2993 return(XML_READER_TYPE_NONE);
2995 return(-1);
2999 * xmlTextReaderIsEmptyElement:
3000 * @reader: the xmlTextReaderPtr used
3002 * Check if the current node is empty
3004 * Returns 1 if empty, 0 if not and -1 in case of error
3007 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3008 if ((reader == NULL) || (reader->node == NULL))
3009 return(-1);
3010 if (reader->node->type != XML_ELEMENT_NODE)
3011 return(0);
3012 if (reader->curnode != NULL)
3013 return(0);
3014 if (reader->node->children != NULL)
3015 return(0);
3016 if (reader->state == XML_TEXTREADER_END)
3017 return(0);
3018 if (reader->doc != NULL)
3019 return(1);
3020 #ifdef LIBXML_XINCLUDE_ENABLED
3021 if (reader->in_xinclude > 0)
3022 return(1);
3023 #endif
3024 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3028 * xmlTextReaderLocalName:
3029 * @reader: the xmlTextReaderPtr used
3031 * The local name of the node.
3033 * Returns the local name or NULL if not available,
3034 * if non NULL it need to be freed by the caller.
3036 xmlChar *
3037 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3038 xmlNodePtr node;
3039 if ((reader == NULL) || (reader->node == NULL))
3040 return(NULL);
3041 if (reader->curnode != NULL)
3042 node = reader->curnode;
3043 else
3044 node = reader->node;
3045 if (node->type == XML_NAMESPACE_DECL) {
3046 xmlNsPtr ns = (xmlNsPtr) node;
3047 if (ns->prefix == NULL)
3048 return(xmlStrdup(BAD_CAST "xmlns"));
3049 else
3050 return(xmlStrdup(ns->prefix));
3052 if ((node->type != XML_ELEMENT_NODE) &&
3053 (node->type != XML_ATTRIBUTE_NODE))
3054 return(xmlTextReaderName(reader));
3055 return(xmlStrdup(node->name));
3059 * xmlTextReaderConstLocalName:
3060 * @reader: the xmlTextReaderPtr used
3062 * The local name of the node.
3064 * Returns the local name or NULL if not available, the
3065 * string will be deallocated with the reader.
3067 const xmlChar *
3068 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3069 xmlNodePtr node;
3070 if ((reader == NULL) || (reader->node == NULL))
3071 return(NULL);
3072 if (reader->curnode != NULL)
3073 node = reader->curnode;
3074 else
3075 node = reader->node;
3076 if (node->type == XML_NAMESPACE_DECL) {
3077 xmlNsPtr ns = (xmlNsPtr) node;
3078 if (ns->prefix == NULL)
3079 return(CONSTSTR(BAD_CAST "xmlns"));
3080 else
3081 return(ns->prefix);
3083 if ((node->type != XML_ELEMENT_NODE) &&
3084 (node->type != XML_ATTRIBUTE_NODE))
3085 return(xmlTextReaderConstName(reader));
3086 return(node->name);
3090 * xmlTextReaderName:
3091 * @reader: the xmlTextReaderPtr used
3093 * The qualified name of the node, equal to Prefix :LocalName.
3095 * Returns the local name or NULL if not available,
3096 * if non NULL it need to be freed by the caller.
3098 xmlChar *
3099 xmlTextReaderName(xmlTextReaderPtr reader) {
3100 xmlNodePtr node;
3101 xmlChar *ret;
3103 if ((reader == NULL) || (reader->node == NULL))
3104 return(NULL);
3105 if (reader->curnode != NULL)
3106 node = reader->curnode;
3107 else
3108 node = reader->node;
3109 switch (node->type) {
3110 case XML_ELEMENT_NODE:
3111 case XML_ATTRIBUTE_NODE:
3112 if ((node->ns == NULL) ||
3113 (node->ns->prefix == NULL))
3114 return(xmlStrdup(node->name));
3116 ret = xmlStrdup(node->ns->prefix);
3117 ret = xmlStrcat(ret, BAD_CAST ":");
3118 ret = xmlStrcat(ret, node->name);
3119 return(ret);
3120 case XML_TEXT_NODE:
3121 return(xmlStrdup(BAD_CAST "#text"));
3122 case XML_CDATA_SECTION_NODE:
3123 return(xmlStrdup(BAD_CAST "#cdata-section"));
3124 case XML_ENTITY_NODE:
3125 case XML_ENTITY_REF_NODE:
3126 return(xmlStrdup(node->name));
3127 case XML_PI_NODE:
3128 return(xmlStrdup(node->name));
3129 case XML_COMMENT_NODE:
3130 return(xmlStrdup(BAD_CAST "#comment"));
3131 case XML_DOCUMENT_NODE:
3132 case XML_HTML_DOCUMENT_NODE:
3133 return(xmlStrdup(BAD_CAST "#document"));
3134 case XML_DOCUMENT_FRAG_NODE:
3135 return(xmlStrdup(BAD_CAST "#document-fragment"));
3136 case XML_NOTATION_NODE:
3137 return(xmlStrdup(node->name));
3138 case XML_DOCUMENT_TYPE_NODE:
3139 case XML_DTD_NODE:
3140 return(xmlStrdup(node->name));
3141 case XML_NAMESPACE_DECL: {
3142 xmlNsPtr ns = (xmlNsPtr) node;
3144 ret = xmlStrdup(BAD_CAST "xmlns");
3145 if (ns->prefix == NULL)
3146 return(ret);
3147 ret = xmlStrcat(ret, BAD_CAST ":");
3148 ret = xmlStrcat(ret, ns->prefix);
3149 return(ret);
3152 case XML_ELEMENT_DECL:
3153 case XML_ATTRIBUTE_DECL:
3154 case XML_ENTITY_DECL:
3155 case XML_XINCLUDE_START:
3156 case XML_XINCLUDE_END:
3157 return(NULL);
3159 return(NULL);
3163 * xmlTextReaderConstName:
3164 * @reader: the xmlTextReaderPtr used
3166 * The qualified name of the node, equal to Prefix :LocalName.
3168 * Returns the local name or NULL if not available, the string is
3169 * deallocated with the reader.
3171 const xmlChar *
3172 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3173 xmlNodePtr node;
3175 if ((reader == NULL) || (reader->node == NULL))
3176 return(NULL);
3177 if (reader->curnode != NULL)
3178 node = reader->curnode;
3179 else
3180 node = reader->node;
3181 switch (node->type) {
3182 case XML_ELEMENT_NODE:
3183 case XML_ATTRIBUTE_NODE:
3184 if ((node->ns == NULL) ||
3185 (node->ns->prefix == NULL))
3186 return(node->name);
3187 return(CONSTQSTR(node->ns->prefix, node->name));
3188 case XML_TEXT_NODE:
3189 return(CONSTSTR(BAD_CAST "#text"));
3190 case XML_CDATA_SECTION_NODE:
3191 return(CONSTSTR(BAD_CAST "#cdata-section"));
3192 case XML_ENTITY_NODE:
3193 case XML_ENTITY_REF_NODE:
3194 return(CONSTSTR(node->name));
3195 case XML_PI_NODE:
3196 return(CONSTSTR(node->name));
3197 case XML_COMMENT_NODE:
3198 return(CONSTSTR(BAD_CAST "#comment"));
3199 case XML_DOCUMENT_NODE:
3200 case XML_HTML_DOCUMENT_NODE:
3201 return(CONSTSTR(BAD_CAST "#document"));
3202 case XML_DOCUMENT_FRAG_NODE:
3203 return(CONSTSTR(BAD_CAST "#document-fragment"));
3204 case XML_NOTATION_NODE:
3205 return(CONSTSTR(node->name));
3206 case XML_DOCUMENT_TYPE_NODE:
3207 case XML_DTD_NODE:
3208 return(CONSTSTR(node->name));
3209 case XML_NAMESPACE_DECL: {
3210 xmlNsPtr ns = (xmlNsPtr) node;
3212 if (ns->prefix == NULL)
3213 return(CONSTSTR(BAD_CAST "xmlns"));
3214 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3217 case XML_ELEMENT_DECL:
3218 case XML_ATTRIBUTE_DECL:
3219 case XML_ENTITY_DECL:
3220 case XML_XINCLUDE_START:
3221 case XML_XINCLUDE_END:
3222 return(NULL);
3224 return(NULL);
3228 * xmlTextReaderPrefix:
3229 * @reader: the xmlTextReaderPtr used
3231 * A shorthand reference to the namespace associated with the node.
3233 * Returns the prefix or NULL if not available,
3234 * if non NULL it need to be freed by the caller.
3236 xmlChar *
3237 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3238 xmlNodePtr node;
3239 if ((reader == NULL) || (reader->node == NULL))
3240 return(NULL);
3241 if (reader->curnode != NULL)
3242 node = reader->curnode;
3243 else
3244 node = reader->node;
3245 if (node->type == XML_NAMESPACE_DECL) {
3246 xmlNsPtr ns = (xmlNsPtr) node;
3247 if (ns->prefix == NULL)
3248 return(NULL);
3249 return(xmlStrdup(BAD_CAST "xmlns"));
3251 if ((node->type != XML_ELEMENT_NODE) &&
3252 (node->type != XML_ATTRIBUTE_NODE))
3253 return(NULL);
3254 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3255 return(xmlStrdup(node->ns->prefix));
3256 return(NULL);
3260 * xmlTextReaderConstPrefix:
3261 * @reader: the xmlTextReaderPtr used
3263 * A shorthand reference to the namespace associated with the node.
3265 * Returns the prefix or NULL if not available, the string is deallocated
3266 * with the reader.
3268 const xmlChar *
3269 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3270 xmlNodePtr node;
3271 if ((reader == NULL) || (reader->node == NULL))
3272 return(NULL);
3273 if (reader->curnode != NULL)
3274 node = reader->curnode;
3275 else
3276 node = reader->node;
3277 if (node->type == XML_NAMESPACE_DECL) {
3278 xmlNsPtr ns = (xmlNsPtr) node;
3279 if (ns->prefix == NULL)
3280 return(NULL);
3281 return(CONSTSTR(BAD_CAST "xmlns"));
3283 if ((node->type != XML_ELEMENT_NODE) &&
3284 (node->type != XML_ATTRIBUTE_NODE))
3285 return(NULL);
3286 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3287 return(CONSTSTR(node->ns->prefix));
3288 return(NULL);
3292 * xmlTextReaderNamespaceUri:
3293 * @reader: the xmlTextReaderPtr used
3295 * The URI defining the namespace associated with the node.
3297 * Returns the namespace URI or NULL if not available,
3298 * if non NULL it need to be freed by the caller.
3300 xmlChar *
3301 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3302 xmlNodePtr node;
3303 if ((reader == NULL) || (reader->node == NULL))
3304 return(NULL);
3305 if (reader->curnode != NULL)
3306 node = reader->curnode;
3307 else
3308 node = reader->node;
3309 if (node->type == XML_NAMESPACE_DECL)
3310 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3311 if ((node->type != XML_ELEMENT_NODE) &&
3312 (node->type != XML_ATTRIBUTE_NODE))
3313 return(NULL);
3314 if (node->ns != NULL)
3315 return(xmlStrdup(node->ns->href));
3316 return(NULL);
3320 * xmlTextReaderConstNamespaceUri:
3321 * @reader: the xmlTextReaderPtr used
3323 * The URI defining the namespace associated with the node.
3325 * Returns the namespace URI or NULL if not available, the string
3326 * will be deallocated with the reader
3328 const xmlChar *
3329 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3330 xmlNodePtr node;
3331 if ((reader == NULL) || (reader->node == NULL))
3332 return(NULL);
3333 if (reader->curnode != NULL)
3334 node = reader->curnode;
3335 else
3336 node = reader->node;
3337 if (node->type == XML_NAMESPACE_DECL)
3338 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3339 if ((node->type != XML_ELEMENT_NODE) &&
3340 (node->type != XML_ATTRIBUTE_NODE))
3341 return(NULL);
3342 if (node->ns != NULL)
3343 return(CONSTSTR(node->ns->href));
3344 return(NULL);
3348 * xmlTextReaderBaseUri:
3349 * @reader: the xmlTextReaderPtr used
3351 * The base URI of the node.
3353 * Returns the base URI or NULL if not available,
3354 * if non NULL it need to be freed by the caller.
3356 xmlChar *
3357 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3358 if ((reader == NULL) || (reader->node == NULL))
3359 return(NULL);
3360 return(xmlNodeGetBase(NULL, reader->node));
3364 * xmlTextReaderConstBaseUri:
3365 * @reader: the xmlTextReaderPtr used
3367 * The base URI of the node.
3369 * Returns the base URI or NULL if not available, the string
3370 * will be deallocated with the reader
3372 const xmlChar *
3373 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3374 xmlChar *tmp;
3375 const xmlChar *ret;
3377 if ((reader == NULL) || (reader->node == NULL))
3378 return(NULL);
3379 tmp = xmlNodeGetBase(NULL, reader->node);
3380 if (tmp == NULL)
3381 return(NULL);
3382 ret = CONSTSTR(tmp);
3383 xmlFree(tmp);
3384 return(ret);
3388 * xmlTextReaderDepth:
3389 * @reader: the xmlTextReaderPtr used
3391 * The depth of the node in the tree.
3393 * Returns the depth or -1 in case of error
3396 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3397 if (reader == NULL)
3398 return(-1);
3399 if (reader->node == NULL)
3400 return(0);
3402 if (reader->curnode != NULL) {
3403 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3404 (reader->curnode->type == XML_NAMESPACE_DECL))
3405 return(reader->depth + 1);
3406 return(reader->depth + 2);
3408 return(reader->depth);
3412 * xmlTextReaderHasAttributes:
3413 * @reader: the xmlTextReaderPtr used
3415 * Whether the node has attributes.
3417 * Returns 1 if true, 0 if false, and -1 in case or error
3420 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3421 xmlNodePtr node;
3422 if (reader == NULL)
3423 return(-1);
3424 if (reader->node == NULL)
3425 return(0);
3426 if (reader->curnode != NULL)
3427 node = reader->curnode;
3428 else
3429 node = reader->node;
3431 if ((node->type == XML_ELEMENT_NODE) &&
3432 ((node->properties != NULL) || (node->nsDef != NULL)))
3433 return(1);
3434 /* TODO: handle the xmlDecl */
3435 return(0);
3439 * xmlTextReaderHasValue:
3440 * @reader: the xmlTextReaderPtr used
3442 * Whether the node can have a text value.
3444 * Returns 1 if true, 0 if false, and -1 in case or error
3447 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3448 xmlNodePtr node;
3449 if (reader == NULL)
3450 return(-1);
3451 if (reader->node == NULL)
3452 return(0);
3453 if (reader->curnode != NULL)
3454 node = reader->curnode;
3455 else
3456 node = reader->node;
3458 switch (node->type) {
3459 case XML_ATTRIBUTE_NODE:
3460 case XML_TEXT_NODE:
3461 case XML_CDATA_SECTION_NODE:
3462 case XML_PI_NODE:
3463 case XML_COMMENT_NODE:
3464 case XML_NAMESPACE_DECL:
3465 return(1);
3466 default:
3467 break;
3469 return(0);
3473 * xmlTextReaderValue:
3474 * @reader: the xmlTextReaderPtr used
3476 * Provides the text value of the node if present
3478 * Returns the string or NULL if not available. The result must be deallocated
3479 * with xmlFree()
3481 xmlChar *
3482 xmlTextReaderValue(xmlTextReaderPtr reader) {
3483 xmlNodePtr node;
3484 if (reader == NULL)
3485 return(NULL);
3486 if (reader->node == NULL)
3487 return(NULL);
3488 if (reader->curnode != NULL)
3489 node = reader->curnode;
3490 else
3491 node = reader->node;
3493 switch (node->type) {
3494 case XML_NAMESPACE_DECL:
3495 return(xmlStrdup(((xmlNsPtr) node)->href));
3496 case XML_ATTRIBUTE_NODE:{
3497 xmlAttrPtr attr = (xmlAttrPtr) node;
3499 if (attr->parent != NULL)
3500 return (xmlNodeListGetString
3501 (attr->parent->doc, attr->children, 1));
3502 else
3503 return (xmlNodeListGetString(NULL, attr->children, 1));
3504 break;
3506 case XML_TEXT_NODE:
3507 case XML_CDATA_SECTION_NODE:
3508 case XML_PI_NODE:
3509 case XML_COMMENT_NODE:
3510 if (node->content != NULL)
3511 return (xmlStrdup(node->content));
3512 default:
3513 break;
3515 return(NULL);
3519 * xmlTextReaderConstValue:
3520 * @reader: the xmlTextReaderPtr used
3522 * Provides the text value of the node if present
3524 * Returns the string or NULL if not available. The result will be
3525 * deallocated on the next Read() operation.
3527 const xmlChar *
3528 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3529 xmlNodePtr node;
3530 if (reader == NULL)
3531 return(NULL);
3532 if (reader->node == NULL)
3533 return(NULL);
3534 if (reader->curnode != NULL)
3535 node = reader->curnode;
3536 else
3537 node = reader->node;
3539 switch (node->type) {
3540 case XML_NAMESPACE_DECL:
3541 return(((xmlNsPtr) node)->href);
3542 case XML_ATTRIBUTE_NODE:{
3543 xmlAttrPtr attr = (xmlAttrPtr) node;
3544 const xmlChar *ret;
3546 if ((attr->children != NULL) &&
3547 (attr->children->type == XML_TEXT_NODE) &&
3548 (attr->children->next == NULL))
3549 return(attr->children->content);
3550 else {
3551 if (reader->buffer == NULL) {
3552 reader->buffer = xmlBufCreateSize(100);
3553 if (reader->buffer == NULL) {
3554 xmlGenericError(xmlGenericErrorContext,
3555 "xmlTextReaderSetup : malloc failed\n");
3556 return (NULL);
3558 xmlBufSetAllocationScheme(reader->buffer,
3559 XML_BUFFER_ALLOC_DOUBLEIT);
3560 } else
3561 xmlBufEmpty(reader->buffer);
3562 xmlBufGetNodeContent(reader->buffer, node);
3563 ret = xmlBufContent(reader->buffer);
3564 if (ret == NULL) {
3565 /* error on the buffer best to reallocate */
3566 xmlBufFree(reader->buffer);
3567 reader->buffer = xmlBufCreateSize(100);
3568 xmlBufSetAllocationScheme(reader->buffer,
3569 XML_BUFFER_ALLOC_DOUBLEIT);
3570 ret = BAD_CAST "";
3572 return(ret);
3574 break;
3576 case XML_TEXT_NODE:
3577 case XML_CDATA_SECTION_NODE:
3578 case XML_PI_NODE:
3579 case XML_COMMENT_NODE:
3580 return(node->content);
3581 default:
3582 break;
3584 return(NULL);
3588 * xmlTextReaderIsDefault:
3589 * @reader: the xmlTextReaderPtr used
3591 * Whether an Attribute node was generated from the default value
3592 * defined in the DTD or schema.
3594 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3597 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3598 if (reader == NULL)
3599 return(-1);
3600 return(0);
3604 * xmlTextReaderQuoteChar:
3605 * @reader: the xmlTextReaderPtr used
3607 * The quotation mark character used to enclose the value of an attribute.
3609 * Returns " or ' and -1 in case of error
3612 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3613 if (reader == NULL)
3614 return(-1);
3615 /* TODO maybe lookup the attribute value for " first */
3616 return((int) '"');
3620 * xmlTextReaderXmlLang:
3621 * @reader: the xmlTextReaderPtr used
3623 * The xml:lang scope within which the node resides.
3625 * Returns the xml:lang value or NULL if none exists.,
3626 * if non NULL it need to be freed by the caller.
3628 xmlChar *
3629 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3630 if (reader == NULL)
3631 return(NULL);
3632 if (reader->node == NULL)
3633 return(NULL);
3634 return(xmlNodeGetLang(reader->node));
3638 * xmlTextReaderConstXmlLang:
3639 * @reader: the xmlTextReaderPtr used
3641 * The xml:lang scope within which the node resides.
3643 * Returns the xml:lang value or NULL if none exists.
3645 const xmlChar *
3646 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3647 xmlChar *tmp;
3648 const xmlChar *ret;
3650 if (reader == NULL)
3651 return(NULL);
3652 if (reader->node == NULL)
3653 return(NULL);
3654 tmp = xmlNodeGetLang(reader->node);
3655 if (tmp == NULL)
3656 return(NULL);
3657 ret = CONSTSTR(tmp);
3658 xmlFree(tmp);
3659 return(ret);
3663 * xmlTextReaderConstString:
3664 * @reader: the xmlTextReaderPtr used
3665 * @str: the string to intern.
3667 * Get an interned string from the reader, allows for example to
3668 * speedup string name comparisons
3670 * Returns an interned copy of the string or NULL in case of error. The
3671 * string will be deallocated with the reader.
3673 const xmlChar *
3674 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3675 if (reader == NULL)
3676 return(NULL);
3677 return(CONSTSTR(str));
3681 * xmlTextReaderNormalization:
3682 * @reader: the xmlTextReaderPtr used
3684 * The value indicating whether to normalize white space and attribute values.
3685 * Since attribute value and end of line normalizations are a MUST in the XML
3686 * specification only the value true is accepted. The broken behaviour of
3687 * accepting out of range character entities like &#0; is of course not
3688 * supported either.
3690 * Returns 1 or -1 in case of error.
3693 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3694 if (reader == NULL)
3695 return(-1);
3696 return(1);
3699 /************************************************************************
3701 * Extensions to the base APIs *
3703 ************************************************************************/
3706 * xmlTextReaderSetParserProp:
3707 * @reader: the xmlTextReaderPtr used
3708 * @prop: the xmlParserProperties to set
3709 * @value: usually 0 or 1 to (de)activate it
3711 * Change the parser processing behaviour by changing some of its internal
3712 * properties. Note that some properties can only be changed before any
3713 * read has been done.
3715 * Returns 0 if the call was successful, or -1 in case of error
3718 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3719 xmlParserProperties p = (xmlParserProperties) prop;
3720 xmlParserCtxtPtr ctxt;
3722 if ((reader == NULL) || (reader->ctxt == NULL))
3723 return(-1);
3724 ctxt = reader->ctxt;
3726 switch (p) {
3727 case XML_PARSER_LOADDTD:
3728 if (value != 0) {
3729 if (ctxt->loadsubset == 0) {
3730 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3731 return(-1);
3732 ctxt->loadsubset = XML_DETECT_IDS;
3734 } else {
3735 ctxt->loadsubset = 0;
3737 return(0);
3738 case XML_PARSER_DEFAULTATTRS:
3739 if (value != 0) {
3740 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3741 } else {
3742 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3743 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3745 return(0);
3746 case XML_PARSER_VALIDATE:
3747 if (value != 0) {
3748 ctxt->options |= XML_PARSE_DTDVALID;
3749 ctxt->validate = 1;
3750 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3751 } else {
3752 ctxt->options &= ~XML_PARSE_DTDVALID;
3753 ctxt->validate = 0;
3755 return(0);
3756 case XML_PARSER_SUBST_ENTITIES:
3757 if (value != 0) {
3758 ctxt->options |= XML_PARSE_NOENT;
3759 ctxt->replaceEntities = 1;
3760 } else {
3761 ctxt->options &= ~XML_PARSE_NOENT;
3762 ctxt->replaceEntities = 0;
3764 return(0);
3766 return(-1);
3770 * xmlTextReaderGetParserProp:
3771 * @reader: the xmlTextReaderPtr used
3772 * @prop: the xmlParserProperties to get
3774 * Read the parser internal property.
3776 * Returns the value, usually 0 or 1, or -1 in case of error.
3779 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3780 xmlParserProperties p = (xmlParserProperties) prop;
3781 xmlParserCtxtPtr ctxt;
3783 if ((reader == NULL) || (reader->ctxt == NULL))
3784 return(-1);
3785 ctxt = reader->ctxt;
3787 switch (p) {
3788 case XML_PARSER_LOADDTD:
3789 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3790 return(1);
3791 return(0);
3792 case XML_PARSER_DEFAULTATTRS:
3793 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3794 return(1);
3795 return(0);
3796 case XML_PARSER_VALIDATE:
3797 return(reader->validate);
3798 case XML_PARSER_SUBST_ENTITIES:
3799 return(ctxt->replaceEntities);
3801 return(-1);
3806 * xmlTextReaderGetParserLineNumber:
3807 * @reader: the user data (XML reader context)
3809 * Provide the line number of the current parsing point.
3811 * Returns an int or 0 if not available
3814 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3816 if ((reader == NULL) || (reader->ctxt == NULL) ||
3817 (reader->ctxt->input == NULL)) {
3818 return (0);
3820 return (reader->ctxt->input->line);
3824 * xmlTextReaderGetParserColumnNumber:
3825 * @reader: the user data (XML reader context)
3827 * Provide the column number of the current parsing point.
3829 * Returns an int or 0 if not available
3832 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3834 if ((reader == NULL) || (reader->ctxt == NULL) ||
3835 (reader->ctxt->input == NULL)) {
3836 return (0);
3838 return (reader->ctxt->input->col);
3842 * xmlTextReaderCurrentNode:
3843 * @reader: the xmlTextReaderPtr used
3845 * Hacking interface allowing to get the xmlNodePtr corresponding to the
3846 * current node being accessed by the xmlTextReader. This is dangerous
3847 * because the underlying node may be destroyed on the next Reads.
3849 * Returns the xmlNodePtr or NULL in case of error.
3851 xmlNodePtr
3852 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3853 if (reader == NULL)
3854 return(NULL);
3856 if (reader->curnode != NULL)
3857 return(reader->curnode);
3858 return(reader->node);
3862 * xmlTextReaderPreserve:
3863 * @reader: the xmlTextReaderPtr used
3865 * This tells the XML Reader to preserve the current node.
3866 * The caller must also use xmlTextReaderCurrentDoc() to
3867 * keep an handle on the resulting document once parsing has finished
3869 * Returns the xmlNodePtr or NULL in case of error.
3871 xmlNodePtr
3872 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3873 xmlNodePtr cur, parent;
3875 if (reader == NULL)
3876 return(NULL);
3878 if (reader->curnode != NULL)
3879 cur = reader->curnode;
3880 else
3881 cur = reader->node;
3882 if (cur == NULL)
3883 return(NULL);
3885 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3886 cur->extra |= NODE_IS_PRESERVED;
3887 cur->extra |= NODE_IS_SPRESERVED;
3889 reader->preserves++;
3891 parent = cur->parent;;
3892 while (parent != NULL) {
3893 if (parent->type == XML_ELEMENT_NODE)
3894 parent->extra |= NODE_IS_PRESERVED;
3895 parent = parent->parent;
3897 return(cur);
3900 #ifdef LIBXML_PATTERN_ENABLED
3902 * xmlTextReaderPreservePattern:
3903 * @reader: the xmlTextReaderPtr used
3904 * @pattern: an XPath subset pattern
3905 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3907 * This tells the XML Reader to preserve all nodes matched by the
3908 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3909 * keep an handle on the resulting document once parsing has finished
3911 * Returns a non-negative number in case of success and -1 in case of error
3914 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3915 const xmlChar **namespaces)
3917 xmlPatternPtr comp;
3919 if ((reader == NULL) || (pattern == NULL))
3920 return(-1);
3922 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3923 if (comp == NULL)
3924 return(-1);
3926 if (reader->patternMax <= 0) {
3927 reader->patternMax = 4;
3928 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3929 sizeof(reader->patternTab[0]));
3930 if (reader->patternTab == NULL) {
3931 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3932 return (-1);
3935 if (reader->patternNr >= reader->patternMax) {
3936 xmlPatternPtr *tmp;
3937 reader->patternMax *= 2;
3938 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3939 reader->patternMax *
3940 sizeof(reader->patternTab[0]));
3941 if (tmp == NULL) {
3942 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3943 reader->patternMax /= 2;
3944 return (-1);
3946 reader->patternTab = tmp;
3948 reader->patternTab[reader->patternNr] = comp;
3949 return(reader->patternNr++);
3951 #endif
3954 * xmlTextReaderCurrentDoc:
3955 * @reader: the xmlTextReaderPtr used
3957 * Hacking interface allowing to get the xmlDocPtr corresponding to the
3958 * current document being accessed by the xmlTextReader.
3959 * NOTE: as a result of this call, the reader will not destroy the
3960 * associated XML document and calling xmlFreeDoc() on the result
3961 * is needed once the reader parsing has finished.
3963 * Returns the xmlDocPtr or NULL in case of error.
3965 xmlDocPtr
3966 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
3967 if (reader == NULL)
3968 return(NULL);
3969 if (reader->doc != NULL)
3970 return(reader->doc);
3971 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
3972 return(NULL);
3974 reader->preserve = 1;
3975 return(reader->ctxt->myDoc);
3978 #ifdef LIBXML_SCHEMAS_ENABLED
3979 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
3981 static void XMLCDECL
3982 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3984 static void XMLCDECL
3985 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3987 static void XMLCDECL
3988 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3990 static void XMLCDECL
3991 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
3993 static void XMLCDECL
3994 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
3996 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3998 char *str;
4000 va_list ap;
4002 va_start(ap, msg);
4003 str = xmlTextReaderBuildMessage(msg, ap);
4004 if (!reader->errorFunc) {
4005 xmlTextReaderValidityError(ctx, "%s", str);
4006 } else {
4007 reader->errorFunc(reader->errorFuncArg, str,
4008 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4009 NULL /* locator */ );
4011 if (str != NULL)
4012 xmlFree(str);
4013 va_end(ap);
4016 static void XMLCDECL
4017 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4019 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4021 char *str;
4023 va_list ap;
4025 va_start(ap, msg);
4026 str = xmlTextReaderBuildMessage(msg, ap);
4027 if (!reader->errorFunc) {
4028 xmlTextReaderValidityWarning(ctx, "%s", str);
4029 } else {
4030 reader->errorFunc(reader->errorFuncArg, str,
4031 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4032 NULL /* locator */ );
4034 if (str != NULL)
4035 xmlFree(str);
4036 va_end(ap);
4039 static void
4040 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4042 static void
4043 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4045 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4047 if (reader->sErrorFunc) {
4048 reader->sErrorFunc(reader->errorFuncArg, error);
4049 } else {
4050 xmlTextReaderStructuredError(reader, error);
4054 * xmlTextReaderRelaxNGSetSchema:
4055 * @reader: the xmlTextReaderPtr used
4056 * @schema: a precompiled RelaxNG schema
4058 * Use RelaxNG to validate the document as it is processed.
4059 * Activation is only possible before the first Read().
4060 * if @schema is NULL, then RelaxNG validation is deactivated.
4061 @ The @schema should not be freed until the reader is deallocated
4062 * or its use has been deactivated.
4064 * Returns 0 in case the RelaxNG validation could be (de)activated and
4065 * -1 in case of error.
4068 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4069 if (reader == NULL)
4070 return(-1);
4071 if (schema == NULL) {
4072 if (reader->rngSchemas != NULL) {
4073 xmlRelaxNGFree(reader->rngSchemas);
4074 reader->rngSchemas = NULL;
4076 if (reader->rngValidCtxt != NULL) {
4077 if (! reader->rngPreserveCtxt)
4078 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4079 reader->rngValidCtxt = NULL;
4081 reader->rngPreserveCtxt = 0;
4082 return(0);
4084 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4085 return(-1);
4086 if (reader->rngSchemas != NULL) {
4087 xmlRelaxNGFree(reader->rngSchemas);
4088 reader->rngSchemas = NULL;
4090 if (reader->rngValidCtxt != NULL) {
4091 if (! reader->rngPreserveCtxt)
4092 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4093 reader->rngValidCtxt = NULL;
4095 reader->rngPreserveCtxt = 0;
4096 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4097 if (reader->rngValidCtxt == NULL)
4098 return(-1);
4099 if (reader->errorFunc != NULL) {
4100 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4101 xmlTextReaderValidityErrorRelay,
4102 xmlTextReaderValidityWarningRelay,
4103 reader);
4105 if (reader->sErrorFunc != NULL) {
4106 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4107 xmlTextReaderValidityStructuredRelay,
4108 reader);
4110 reader->rngValidErrors = 0;
4111 reader->rngFullNode = NULL;
4112 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4113 return(0);
4117 * xmlTextReaderLocator:
4118 * @ctx: the xmlTextReaderPtr used
4119 * @file: returned file information
4120 * @line: returned line information
4122 * Internal locator function for the readers
4124 * Returns 0 in case the Schema validation could be (de)activated and
4125 * -1 in case of error.
4127 static int
4128 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4129 xmlTextReaderPtr reader;
4131 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4132 return(-1);
4134 if (file != NULL)
4135 *file = NULL;
4136 if (line != NULL)
4137 *line = 0;
4139 reader = (xmlTextReaderPtr) ctx;
4140 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4141 if (file != NULL)
4142 *file = reader->ctxt->input->filename;
4143 if (line != NULL)
4144 *line = reader->ctxt->input->line;
4145 return(0);
4147 if (reader->node != NULL) {
4148 long res;
4149 int ret = 0;
4151 if (line != NULL) {
4152 res = xmlGetLineNo(reader->node);
4153 if (res > 0)
4154 *line = (unsigned long) res;
4155 else
4156 ret = -1;
4158 if (file != NULL) {
4159 xmlDocPtr doc = reader->node->doc;
4160 if ((doc != NULL) && (doc->URL != NULL))
4161 *file = (const char *) doc->URL;
4162 else
4163 ret = -1;
4165 return(ret);
4167 return(-1);
4171 * xmlTextReaderSetSchema:
4172 * @reader: the xmlTextReaderPtr used
4173 * @schema: a precompiled Schema schema
4175 * Use XSD Schema to validate the document as it is processed.
4176 * Activation is only possible before the first Read().
4177 * if @schema is NULL, then Schema validation is deactivated.
4178 * The @schema should not be freed until the reader is deallocated
4179 * or its use has been deactivated.
4181 * Returns 0 in case the Schema validation could be (de)activated and
4182 * -1 in case of error.
4185 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4186 if (reader == NULL)
4187 return(-1);
4188 if (schema == NULL) {
4189 if (reader->xsdPlug != NULL) {
4190 xmlSchemaSAXUnplug(reader->xsdPlug);
4191 reader->xsdPlug = NULL;
4193 if (reader->xsdValidCtxt != NULL) {
4194 if (! reader->xsdPreserveCtxt)
4195 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4196 reader->xsdValidCtxt = NULL;
4198 reader->xsdPreserveCtxt = 0;
4199 if (reader->xsdSchemas != NULL) {
4200 xmlSchemaFree(reader->xsdSchemas);
4201 reader->xsdSchemas = NULL;
4203 return(0);
4205 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4206 return(-1);
4207 if (reader->xsdPlug != NULL) {
4208 xmlSchemaSAXUnplug(reader->xsdPlug);
4209 reader->xsdPlug = NULL;
4211 if (reader->xsdValidCtxt != NULL) {
4212 if (! reader->xsdPreserveCtxt)
4213 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4214 reader->xsdValidCtxt = NULL;
4216 reader->xsdPreserveCtxt = 0;
4217 if (reader->xsdSchemas != NULL) {
4218 xmlSchemaFree(reader->xsdSchemas);
4219 reader->xsdSchemas = NULL;
4221 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4222 if (reader->xsdValidCtxt == NULL) {
4223 xmlSchemaFree(reader->xsdSchemas);
4224 reader->xsdSchemas = NULL;
4225 return(-1);
4227 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4228 &(reader->ctxt->sax),
4229 &(reader->ctxt->userData));
4230 if (reader->xsdPlug == NULL) {
4231 xmlSchemaFree(reader->xsdSchemas);
4232 reader->xsdSchemas = NULL;
4233 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4234 reader->xsdValidCtxt = NULL;
4235 return(-1);
4237 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4238 xmlTextReaderLocator,
4239 (void *) reader);
4241 if (reader->errorFunc != NULL) {
4242 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4243 xmlTextReaderValidityErrorRelay,
4244 xmlTextReaderValidityWarningRelay,
4245 reader);
4247 if (reader->sErrorFunc != NULL) {
4248 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4249 xmlTextReaderValidityStructuredRelay,
4250 reader);
4252 reader->xsdValidErrors = 0;
4253 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4254 return(0);
4258 * xmlTextReaderRelaxNGValidateInternal:
4259 * @reader: the xmlTextReaderPtr used
4260 * @rng: the path to a RelaxNG schema or NULL
4261 * @ctxt: the RelaxNG schema validation context or NULL
4262 * @options: options (not yet used)
4264 * Use RelaxNG to validate the document as it is processed.
4265 * Activation is only possible before the first Read().
4266 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4268 * Returns 0 in case the RelaxNG validation could be (de)activated and
4269 * -1 in case of error.
4271 static int
4272 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4273 const char *rng,
4274 xmlRelaxNGValidCtxtPtr ctxt,
4275 int options ATTRIBUTE_UNUSED)
4277 if (reader == NULL)
4278 return(-1);
4280 if ((rng != NULL) && (ctxt != NULL))
4281 return (-1);
4283 if (((rng != NULL) || (ctxt != NULL)) &&
4284 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4285 (reader->ctxt == NULL)))
4286 return(-1);
4288 /* Cleanup previous validation stuff. */
4289 if (reader->rngValidCtxt != NULL) {
4290 if ( !reader->rngPreserveCtxt)
4291 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4292 reader->rngValidCtxt = NULL;
4294 reader->rngPreserveCtxt = 0;
4295 if (reader->rngSchemas != NULL) {
4296 xmlRelaxNGFree(reader->rngSchemas);
4297 reader->rngSchemas = NULL;
4300 if ((rng == NULL) && (ctxt == NULL)) {
4301 /* We just want to deactivate the validation, so get out. */
4302 return(0);
4306 if (rng != NULL) {
4307 xmlRelaxNGParserCtxtPtr pctxt;
4308 /* Parse the schema and create validation environment. */
4310 pctxt = xmlRelaxNGNewParserCtxt(rng);
4311 if (reader->errorFunc != NULL) {
4312 xmlRelaxNGSetParserErrors(pctxt,
4313 xmlTextReaderValidityErrorRelay,
4314 xmlTextReaderValidityWarningRelay,
4315 reader);
4317 if (reader->sErrorFunc != NULL) {
4318 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4319 xmlTextReaderValidityStructuredRelay,
4320 reader);
4322 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4323 xmlRelaxNGFreeParserCtxt(pctxt);
4324 if (reader->rngSchemas == NULL)
4325 return(-1);
4326 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4327 if (reader->rngValidCtxt == NULL) {
4328 xmlRelaxNGFree(reader->rngSchemas);
4329 reader->rngSchemas = NULL;
4330 return(-1);
4332 } else {
4333 /* Use the given validation context. */
4334 reader->rngValidCtxt = ctxt;
4335 reader->rngPreserveCtxt = 1;
4338 * Redirect the validation context's error channels to use
4339 * the reader channels.
4340 * TODO: In case the user provides the validation context we
4341 * could make this redirection optional.
4343 if (reader->errorFunc != NULL) {
4344 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4345 xmlTextReaderValidityErrorRelay,
4346 xmlTextReaderValidityWarningRelay,
4347 reader);
4349 if (reader->sErrorFunc != NULL) {
4350 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4351 xmlTextReaderValidityStructuredRelay,
4352 reader);
4354 reader->rngValidErrors = 0;
4355 reader->rngFullNode = NULL;
4356 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4357 return(0);
4361 * xmlTextReaderSchemaValidateInternal:
4362 * @reader: the xmlTextReaderPtr used
4363 * @xsd: the path to a W3C XSD schema or NULL
4364 * @ctxt: the XML Schema validation context or NULL
4365 * @options: options (not used yet)
4367 * Validate the document as it is processed using XML Schema.
4368 * Activation is only possible before the first Read().
4369 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4371 * Returns 0 in case the schemas validation could be (de)activated and
4372 * -1 in case of error.
4374 static int
4375 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4376 const char *xsd,
4377 xmlSchemaValidCtxtPtr ctxt,
4378 int options ATTRIBUTE_UNUSED)
4380 if (reader == NULL)
4381 return(-1);
4383 if ((xsd != NULL) && (ctxt != NULL))
4384 return(-1);
4386 if (((xsd != NULL) || (ctxt != NULL)) &&
4387 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4388 (reader->ctxt == NULL)))
4389 return(-1);
4391 /* Cleanup previous validation stuff. */
4392 if (reader->xsdPlug != NULL) {
4393 xmlSchemaSAXUnplug(reader->xsdPlug);
4394 reader->xsdPlug = NULL;
4396 if (reader->xsdValidCtxt != NULL) {
4397 if (! reader->xsdPreserveCtxt)
4398 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4399 reader->xsdValidCtxt = NULL;
4401 reader->xsdPreserveCtxt = 0;
4402 if (reader->xsdSchemas != NULL) {
4403 xmlSchemaFree(reader->xsdSchemas);
4404 reader->xsdSchemas = NULL;
4407 if ((xsd == NULL) && (ctxt == NULL)) {
4408 /* We just want to deactivate the validation, so get out. */
4409 return(0);
4412 if (xsd != NULL) {
4413 xmlSchemaParserCtxtPtr pctxt;
4414 /* Parse the schema and create validation environment. */
4415 pctxt = xmlSchemaNewParserCtxt(xsd);
4416 if (reader->errorFunc != NULL) {
4417 xmlSchemaSetParserErrors(pctxt,
4418 xmlTextReaderValidityErrorRelay,
4419 xmlTextReaderValidityWarningRelay,
4420 reader);
4422 reader->xsdSchemas = xmlSchemaParse(pctxt);
4423 xmlSchemaFreeParserCtxt(pctxt);
4424 if (reader->xsdSchemas == NULL)
4425 return(-1);
4426 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4427 if (reader->xsdValidCtxt == NULL) {
4428 xmlSchemaFree(reader->xsdSchemas);
4429 reader->xsdSchemas = NULL;
4430 return(-1);
4432 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4433 &(reader->ctxt->sax),
4434 &(reader->ctxt->userData));
4435 if (reader->xsdPlug == NULL) {
4436 xmlSchemaFree(reader->xsdSchemas);
4437 reader->xsdSchemas = NULL;
4438 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4439 reader->xsdValidCtxt = NULL;
4440 return(-1);
4442 } else {
4443 /* Use the given validation context. */
4444 reader->xsdValidCtxt = ctxt;
4445 reader->xsdPreserveCtxt = 1;
4446 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4447 &(reader->ctxt->sax),
4448 &(reader->ctxt->userData));
4449 if (reader->xsdPlug == NULL) {
4450 reader->xsdValidCtxt = NULL;
4451 reader->xsdPreserveCtxt = 0;
4452 return(-1);
4455 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4456 xmlTextReaderLocator,
4457 (void *) reader);
4459 * Redirect the validation context's error channels to use
4460 * the reader channels.
4461 * TODO: In case the user provides the validation context we
4462 * could make this redirection optional.
4464 if (reader->errorFunc != NULL) {
4465 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4466 xmlTextReaderValidityErrorRelay,
4467 xmlTextReaderValidityWarningRelay,
4468 reader);
4470 if (reader->sErrorFunc != NULL) {
4471 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4472 xmlTextReaderValidityStructuredRelay,
4473 reader);
4475 reader->xsdValidErrors = 0;
4476 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4477 return(0);
4481 * xmlTextReaderSchemaValidateCtxt:
4482 * @reader: the xmlTextReaderPtr used
4483 * @ctxt: the XML Schema validation context or NULL
4484 * @options: options (not used yet)
4486 * Use W3C XSD schema context to validate the document as it is processed.
4487 * Activation is only possible before the first Read().
4488 * If @ctxt is NULL, then XML Schema validation is deactivated.
4490 * Returns 0 in case the schemas validation could be (de)activated and
4491 * -1 in case of error.
4494 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4495 xmlSchemaValidCtxtPtr ctxt,
4496 int options)
4498 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4502 * xmlTextReaderSchemaValidate:
4503 * @reader: the xmlTextReaderPtr used
4504 * @xsd: the path to a W3C XSD schema or NULL
4506 * Use W3C XSD schema to validate the document as it is processed.
4507 * Activation is only possible before the first Read().
4508 * If @xsd is NULL, then XML Schema validation is deactivated.
4510 * Returns 0 in case the schemas validation could be (de)activated and
4511 * -1 in case of error.
4514 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4516 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4520 * xmlTextReaderRelaxNGValidateCtxt:
4521 * @reader: the xmlTextReaderPtr used
4522 * @ctxt: the RelaxNG schema validation context or NULL
4523 * @options: options (not used yet)
4525 * Use RelaxNG 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 RelaxNG schema validation is deactivated.
4529 * Returns 0 in case the schemas validation could be (de)activated and
4530 * -1 in case of error.
4533 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4534 xmlRelaxNGValidCtxtPtr ctxt,
4535 int options)
4537 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4541 * xmlTextReaderRelaxNGValidate:
4542 * @reader: the xmlTextReaderPtr used
4543 * @rng: the path to a RelaxNG schema or NULL
4545 * Use RelaxNG schema to validate the document as it is processed.
4546 * Activation is only possible before the first Read().
4547 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4549 * Returns 0 in case the schemas validation could be (de)activated and
4550 * -1 in case of error.
4553 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4555 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4558 #endif
4561 * xmlTextReaderIsNamespaceDecl:
4562 * @reader: the xmlTextReaderPtr used
4564 * Determine whether the current node is a namespace declaration
4565 * rather than a regular attribute.
4567 * Returns 1 if the current node is a namespace declaration, 0 if it
4568 * is a regular attribute or other type of node, or -1 in case of
4569 * error.
4572 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4573 xmlNodePtr node;
4574 if (reader == NULL)
4575 return(-1);
4576 if (reader->node == NULL)
4577 return(-1);
4578 if (reader->curnode != NULL)
4579 node = reader->curnode;
4580 else
4581 node = reader->node;
4583 if (XML_NAMESPACE_DECL == node->type)
4584 return(1);
4585 else
4586 return(0);
4590 * xmlTextReaderConstXmlVersion:
4591 * @reader: the xmlTextReaderPtr used
4593 * Determine the XML version of the document being read.
4595 * Returns a string containing the XML version of the document or NULL
4596 * in case of error. The string is deallocated with the reader.
4598 const xmlChar *
4599 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4600 xmlDocPtr doc = NULL;
4601 if (reader == NULL)
4602 return(NULL);
4603 if (reader->doc != NULL)
4604 doc = reader->doc;
4605 else if (reader->ctxt != NULL)
4606 doc = reader->ctxt->myDoc;
4607 if (doc == NULL)
4608 return(NULL);
4610 if (doc->version == NULL)
4611 return(NULL);
4612 else
4613 return(CONSTSTR(doc->version));
4617 * xmlTextReaderStandalone:
4618 * @reader: the xmlTextReaderPtr used
4620 * Determine the standalone status of the document being read.
4622 * Returns 1 if the document was declared to be standalone, 0 if it
4623 * was declared to be not standalone, or -1 if the document did not
4624 * specify its standalone status or in case of error.
4627 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4628 xmlDocPtr doc = NULL;
4629 if (reader == NULL)
4630 return(-1);
4631 if (reader->doc != NULL)
4632 doc = reader->doc;
4633 else if (reader->ctxt != NULL)
4634 doc = reader->ctxt->myDoc;
4635 if (doc == NULL)
4636 return(-1);
4638 return(doc->standalone);
4641 /************************************************************************
4643 * Error Handling Extensions *
4645 ************************************************************************/
4647 /* helper to build a xmlMalloc'ed string from a format and va_list */
4648 static char *
4649 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4650 int size = 0;
4651 int chars;
4652 char *larger;
4653 char *str = NULL;
4654 va_list aq;
4656 while (1) {
4657 VA_COPY(aq, ap);
4658 chars = vsnprintf(str, size, msg, aq);
4659 va_end(aq);
4660 if (chars < 0) {
4661 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4662 if (str)
4663 xmlFree(str);
4664 return NULL;
4666 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4667 break;
4668 if (chars < MAX_ERR_MSG_SIZE)
4669 size = chars + 1;
4670 else
4671 size = MAX_ERR_MSG_SIZE;
4672 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4673 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4674 if (str)
4675 xmlFree(str);
4676 return NULL;
4678 str = larger;
4681 return str;
4685 * xmlTextReaderLocatorLineNumber:
4686 * @locator: the xmlTextReaderLocatorPtr used
4688 * Obtain the line number for the given locator.
4690 * Returns the line number or -1 in case of error.
4693 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4694 /* we know that locator is a xmlParserCtxtPtr */
4695 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4696 int ret = -1;
4698 if (locator == NULL)
4699 return(-1);
4700 if (ctx->node != NULL) {
4701 ret = xmlGetLineNo(ctx->node);
4703 else {
4704 /* inspired from error.c */
4705 xmlParserInputPtr input;
4706 input = ctx->input;
4707 if ((input->filename == NULL) && (ctx->inputNr > 1))
4708 input = ctx->inputTab[ctx->inputNr - 2];
4709 if (input != NULL) {
4710 ret = input->line;
4712 else {
4713 ret = -1;
4717 return ret;
4721 * xmlTextReaderLocatorBaseURI:
4722 * @locator: the xmlTextReaderLocatorPtr used
4724 * Obtain the base URI for the given locator.
4726 * Returns the base URI or NULL in case of error,
4727 * if non NULL it need to be freed by the caller.
4729 xmlChar *
4730 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4731 /* we know that locator is a xmlParserCtxtPtr */
4732 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4733 xmlChar *ret = NULL;
4735 if (locator == NULL)
4736 return(NULL);
4737 if (ctx->node != NULL) {
4738 ret = xmlNodeGetBase(NULL,ctx->node);
4740 else {
4741 /* inspired from error.c */
4742 xmlParserInputPtr input;
4743 input = ctx->input;
4744 if ((input->filename == NULL) && (ctx->inputNr > 1))
4745 input = ctx->inputTab[ctx->inputNr - 2];
4746 if (input != NULL) {
4747 ret = xmlStrdup(BAD_CAST input->filename);
4749 else {
4750 ret = NULL;
4754 return ret;
4757 static void
4758 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4759 char *str)
4761 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4763 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4765 if (str != NULL) {
4766 if (reader->errorFunc)
4767 reader->errorFunc(reader->errorFuncArg, str, severity,
4768 (xmlTextReaderLocatorPtr) ctx);
4769 xmlFree(str);
4773 static void
4774 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4776 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4778 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4780 if (error && reader->sErrorFunc) {
4781 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4785 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4786 xmlTextReaderError(void *ctxt, const char *msg, ...)
4788 va_list ap;
4790 va_start(ap, msg);
4791 xmlTextReaderGenericError(ctxt,
4792 XML_PARSER_SEVERITY_ERROR,
4793 xmlTextReaderBuildMessage(msg, ap));
4794 va_end(ap);
4798 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4799 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4801 va_list ap;
4803 va_start(ap, msg);
4804 xmlTextReaderGenericError(ctxt,
4805 XML_PARSER_SEVERITY_WARNING,
4806 xmlTextReaderBuildMessage(msg, ap));
4807 va_end(ap);
4810 static void XMLCDECL
4811 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4813 va_list ap;
4815 int len = xmlStrlen((const xmlChar *) msg);
4817 if ((len > 1) && (msg[len - 2] != ':')) {
4819 * some callbacks only report locator information:
4820 * skip them (mimicking behaviour in error.c)
4822 va_start(ap, msg);
4823 xmlTextReaderGenericError(ctxt,
4824 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4825 xmlTextReaderBuildMessage(msg, ap));
4826 va_end(ap);
4830 static void XMLCDECL
4831 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4833 va_list ap;
4835 int len = xmlStrlen((const xmlChar *) msg);
4837 if ((len != 0) && (msg[len - 1] != ':')) {
4839 * some callbacks only report locator information:
4840 * skip them (mimicking behaviour in error.c)
4842 va_start(ap, msg);
4843 xmlTextReaderGenericError(ctxt,
4844 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4845 xmlTextReaderBuildMessage(msg, ap));
4846 va_end(ap);
4851 * xmlTextReaderSetErrorHandler:
4852 * @reader: the xmlTextReaderPtr used
4853 * @f: the callback function to call on error and warnings
4854 * @arg: a user argument to pass to the callback function
4856 * Register a callback function that will be called on error and warnings.
4858 * If @f is NULL, the default error and warning handlers are restored.
4860 void
4861 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4862 xmlTextReaderErrorFunc f, void *arg)
4864 if (f != NULL) {
4865 reader->ctxt->sax->error = xmlTextReaderError;
4866 reader->ctxt->sax->serror = NULL;
4867 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4868 reader->ctxt->sax->warning = xmlTextReaderWarning;
4869 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4870 reader->errorFunc = f;
4871 reader->sErrorFunc = NULL;
4872 reader->errorFuncArg = arg;
4873 #ifdef LIBXML_SCHEMAS_ENABLED
4874 if (reader->rngValidCtxt) {
4875 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4876 xmlTextReaderValidityErrorRelay,
4877 xmlTextReaderValidityWarningRelay,
4878 reader);
4879 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4880 reader);
4882 if (reader->xsdValidCtxt) {
4883 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4884 xmlTextReaderValidityErrorRelay,
4885 xmlTextReaderValidityWarningRelay,
4886 reader);
4887 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4888 reader);
4890 #endif
4891 } else {
4892 /* restore defaults */
4893 reader->ctxt->sax->error = xmlParserError;
4894 reader->ctxt->vctxt.error = xmlParserValidityError;
4895 reader->ctxt->sax->warning = xmlParserWarning;
4896 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4897 reader->errorFunc = NULL;
4898 reader->sErrorFunc = NULL;
4899 reader->errorFuncArg = NULL;
4900 #ifdef LIBXML_SCHEMAS_ENABLED
4901 if (reader->rngValidCtxt) {
4902 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4903 reader);
4904 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4905 reader);
4907 if (reader->xsdValidCtxt) {
4908 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4909 reader);
4910 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4911 reader);
4913 #endif
4918 * xmlTextReaderSetStructuredErrorHandler:
4919 * @reader: the xmlTextReaderPtr used
4920 * @f: the callback function to call on error and warnings
4921 * @arg: a user argument to pass to the callback function
4923 * Register a callback function that will be called on error and warnings.
4925 * If @f is NULL, the default error and warning handlers are restored.
4927 void
4928 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4929 xmlStructuredErrorFunc f, void *arg)
4931 if (f != NULL) {
4932 reader->ctxt->sax->error = NULL;
4933 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4934 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4935 reader->ctxt->sax->warning = xmlTextReaderWarning;
4936 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4937 reader->sErrorFunc = f;
4938 reader->errorFunc = NULL;
4939 reader->errorFuncArg = arg;
4940 #ifdef LIBXML_SCHEMAS_ENABLED
4941 if (reader->rngValidCtxt) {
4942 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4943 reader);
4944 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4945 xmlTextReaderValidityStructuredRelay,
4946 reader);
4948 if (reader->xsdValidCtxt) {
4949 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4950 reader);
4951 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4952 xmlTextReaderValidityStructuredRelay,
4953 reader);
4955 #endif
4956 } else {
4957 /* restore defaults */
4958 reader->ctxt->sax->error = xmlParserError;
4959 reader->ctxt->sax->serror = NULL;
4960 reader->ctxt->vctxt.error = xmlParserValidityError;
4961 reader->ctxt->sax->warning = xmlParserWarning;
4962 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4963 reader->errorFunc = NULL;
4964 reader->sErrorFunc = NULL;
4965 reader->errorFuncArg = NULL;
4966 #ifdef LIBXML_SCHEMAS_ENABLED
4967 if (reader->rngValidCtxt) {
4968 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4969 reader);
4970 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4971 reader);
4973 if (reader->xsdValidCtxt) {
4974 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4975 reader);
4976 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4977 reader);
4979 #endif
4984 * xmlTextReaderIsValid:
4985 * @reader: the xmlTextReaderPtr used
4987 * Retrieve the validity status from the parser context
4989 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4992 xmlTextReaderIsValid(xmlTextReaderPtr reader)
4994 if (reader == NULL)
4995 return (-1);
4996 #ifdef LIBXML_SCHEMAS_ENABLED
4997 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4998 return (reader->rngValidErrors == 0);
4999 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5000 return (reader->xsdValidErrors == 0);
5001 #endif
5002 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5003 return (reader->ctxt->valid);
5004 return (0);
5008 * xmlTextReaderGetErrorHandler:
5009 * @reader: the xmlTextReaderPtr used
5010 * @f: the callback function or NULL is no callback has been registered
5011 * @arg: a user argument
5013 * Retrieve the error callback function and user argument.
5015 void
5016 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5017 xmlTextReaderErrorFunc * f, void **arg)
5019 if (f != NULL)
5020 *f = reader->errorFunc;
5021 if (arg != NULL)
5022 *arg = reader->errorFuncArg;
5024 /************************************************************************
5026 * New set (2.6.0) of simpler and more flexible APIs *
5028 ************************************************************************/
5031 * xmlTextReaderSetup:
5032 * @reader: an XML reader
5033 * @input: xmlParserInputBufferPtr used to feed the reader, will
5034 * be destroyed with it.
5035 * @URL: the base URL to use for the document
5036 * @encoding: the document encoding, or NULL
5037 * @options: a combination of xmlParserOption
5039 * Setup an XML reader with new options
5041 * Returns 0 in case of success and -1 in case of error.
5044 xmlTextReaderSetup(xmlTextReaderPtr reader,
5045 xmlParserInputBufferPtr input, const char *URL,
5046 const char *encoding, int options)
5048 if (reader == NULL) {
5049 if (input != NULL)
5050 xmlFreeParserInputBuffer(input);
5051 return (-1);
5055 * we force the generation of compact text nodes on the reader
5056 * since usr applications should never modify the tree
5058 options |= XML_PARSE_COMPACT;
5060 reader->doc = NULL;
5061 reader->entNr = 0;
5062 reader->parserFlags = options;
5063 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5064 if ((input != NULL) && (reader->input != NULL) &&
5065 (reader->allocs & XML_TEXTREADER_INPUT)) {
5066 xmlFreeParserInputBuffer(reader->input);
5067 reader->input = NULL;
5068 reader->allocs -= XML_TEXTREADER_INPUT;
5070 if (input != NULL) {
5071 reader->input = input;
5072 reader->allocs |= XML_TEXTREADER_INPUT;
5074 if (reader->buffer == NULL)
5075 reader->buffer = xmlBufCreateSize(100);
5076 if (reader->buffer == NULL) {
5077 xmlGenericError(xmlGenericErrorContext,
5078 "xmlTextReaderSetup : malloc failed\n");
5079 return (-1);
5081 /* no operation on a reader should require a huge buffer */
5082 xmlBufSetAllocationScheme(reader->buffer,
5083 XML_BUFFER_ALLOC_DOUBLEIT);
5084 if (reader->sax == NULL)
5085 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5086 if (reader->sax == NULL) {
5087 xmlGenericError(xmlGenericErrorContext,
5088 "xmlTextReaderSetup : malloc failed\n");
5089 return (-1);
5091 xmlSAXVersion(reader->sax, 2);
5092 reader->startElement = reader->sax->startElement;
5093 reader->sax->startElement = xmlTextReaderStartElement;
5094 reader->endElement = reader->sax->endElement;
5095 reader->sax->endElement = xmlTextReaderEndElement;
5096 #ifdef LIBXML_SAX1_ENABLED
5097 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5098 #endif /* LIBXML_SAX1_ENABLED */
5099 reader->startElementNs = reader->sax->startElementNs;
5100 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5101 reader->endElementNs = reader->sax->endElementNs;
5102 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5103 #ifdef LIBXML_SAX1_ENABLED
5104 } else {
5105 reader->startElementNs = NULL;
5106 reader->endElementNs = NULL;
5108 #endif /* LIBXML_SAX1_ENABLED */
5109 reader->characters = reader->sax->characters;
5110 reader->sax->characters = xmlTextReaderCharacters;
5111 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5112 reader->cdataBlock = reader->sax->cdataBlock;
5113 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5115 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5116 reader->node = NULL;
5117 reader->curnode = NULL;
5118 if (input != NULL) {
5119 if (xmlBufUse(reader->input->buffer) < 4) {
5120 xmlParserInputBufferRead(input, 4);
5122 if (reader->ctxt == NULL) {
5123 if (xmlBufUse(reader->input->buffer) >= 4) {
5124 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5125 (const char *) xmlBufContent(reader->input->buffer),
5126 4, URL);
5127 reader->base = 0;
5128 reader->cur = 4;
5129 } else {
5130 reader->ctxt =
5131 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5132 reader->base = 0;
5133 reader->cur = 0;
5135 } else {
5136 xmlParserInputPtr inputStream;
5137 xmlParserInputBufferPtr buf;
5138 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5140 xmlCtxtReset(reader->ctxt);
5141 buf = xmlAllocParserInputBuffer(enc);
5142 if (buf == NULL) return(-1);
5143 inputStream = xmlNewInputStream(reader->ctxt);
5144 if (inputStream == NULL) {
5145 xmlFreeParserInputBuffer(buf);
5146 return(-1);
5149 if (URL == NULL)
5150 inputStream->filename = NULL;
5151 else
5152 inputStream->filename = (char *)
5153 xmlCanonicPath((const xmlChar *) URL);
5154 inputStream->buf = buf;
5155 xmlBufResetInput(buf->buffer, inputStream);
5157 inputPush(reader->ctxt, inputStream);
5158 reader->cur = 0;
5160 if (reader->ctxt == NULL) {
5161 xmlGenericError(xmlGenericErrorContext,
5162 "xmlTextReaderSetup : malloc failed\n");
5163 return (-1);
5166 if (reader->dict != NULL) {
5167 if (reader->ctxt->dict != NULL) {
5168 if (reader->dict != reader->ctxt->dict) {
5169 xmlDictFree(reader->dict);
5170 reader->dict = reader->ctxt->dict;
5172 } else {
5173 reader->ctxt->dict = reader->dict;
5175 } else {
5176 if (reader->ctxt->dict == NULL)
5177 reader->ctxt->dict = xmlDictCreate();
5178 reader->dict = reader->ctxt->dict;
5180 reader->ctxt->_private = reader;
5181 reader->ctxt->linenumbers = 1;
5182 reader->ctxt->dictNames = 1;
5184 * use the parser dictionary to allocate all elements and attributes names
5186 reader->ctxt->docdict = 1;
5187 reader->ctxt->parseMode = XML_PARSE_READER;
5189 #ifdef LIBXML_XINCLUDE_ENABLED
5190 if (reader->xincctxt != NULL) {
5191 xmlXIncludeFreeContext(reader->xincctxt);
5192 reader->xincctxt = NULL;
5194 if (options & XML_PARSE_XINCLUDE) {
5195 reader->xinclude = 1;
5196 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5197 options -= XML_PARSE_XINCLUDE;
5198 } else
5199 reader->xinclude = 0;
5200 reader->in_xinclude = 0;
5201 #endif
5202 #ifdef LIBXML_PATTERN_ENABLED
5203 if (reader->patternTab == NULL) {
5204 reader->patternNr = 0;
5205 reader->patternMax = 0;
5207 while (reader->patternNr > 0) {
5208 reader->patternNr--;
5209 if (reader->patternTab[reader->patternNr] != NULL) {
5210 xmlFreePattern(reader->patternTab[reader->patternNr]);
5211 reader->patternTab[reader->patternNr] = NULL;
5214 #endif
5216 if (options & XML_PARSE_DTDVALID)
5217 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5219 xmlCtxtUseOptions(reader->ctxt, options);
5220 if (encoding != NULL) {
5221 xmlCharEncodingHandlerPtr hdlr;
5223 hdlr = xmlFindCharEncodingHandler(encoding);
5224 if (hdlr != NULL)
5225 xmlSwitchToEncoding(reader->ctxt, hdlr);
5227 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5228 (reader->ctxt->input->filename == NULL))
5229 reader->ctxt->input->filename = (char *)
5230 xmlStrdup((const xmlChar *) URL);
5232 reader->doc = NULL;
5234 return (0);
5238 * xmlTextReaderByteConsumed:
5239 * @reader: an XML reader
5241 * This function provides the current index of the parser used
5242 * by the reader, relative to the start of the current entity.
5243 * This function actually just wraps a call to xmlBytesConsumed()
5244 * for the parser context associated with the reader.
5245 * See xmlBytesConsumed() for more information.
5247 * Returns the index in bytes from the beginning of the entity or -1
5248 * in case the index could not be computed.
5250 long
5251 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5252 if ((reader == NULL) || (reader->ctxt == NULL))
5253 return(-1);
5254 return(xmlByteConsumed(reader->ctxt));
5259 * xmlReaderWalker:
5260 * @doc: a preparsed document
5262 * Create an xmltextReader for a preparsed document.
5264 * Returns the new reader or NULL in case of error.
5266 xmlTextReaderPtr
5267 xmlReaderWalker(xmlDocPtr doc)
5269 xmlTextReaderPtr ret;
5271 if (doc == NULL)
5272 return(NULL);
5274 ret = xmlMalloc(sizeof(xmlTextReader));
5275 if (ret == NULL) {
5276 xmlGenericError(xmlGenericErrorContext,
5277 "xmlNewTextReader : malloc failed\n");
5278 return(NULL);
5280 memset(ret, 0, sizeof(xmlTextReader));
5281 ret->entNr = 0;
5282 ret->input = NULL;
5283 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5284 ret->node = NULL;
5285 ret->curnode = NULL;
5286 ret->base = 0;
5287 ret->cur = 0;
5288 ret->allocs = XML_TEXTREADER_CTXT;
5289 ret->doc = doc;
5290 ret->state = XML_TEXTREADER_START;
5291 ret->dict = xmlDictCreate();
5292 return(ret);
5296 * xmlReaderForDoc:
5297 * @cur: a pointer to a zero terminated string
5298 * @URL: the base URL to use for the document
5299 * @encoding: the document encoding, or NULL
5300 * @options: a combination of xmlParserOption
5302 * Create an xmltextReader for an XML in-memory document.
5303 * The parsing flags @options are a combination of xmlParserOption.
5305 * Returns the new reader or NULL in case of error.
5307 xmlTextReaderPtr
5308 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5309 int options)
5311 int len;
5313 if (cur == NULL)
5314 return (NULL);
5315 len = xmlStrlen(cur);
5317 return (xmlReaderForMemory
5318 ((const char *) cur, len, URL, encoding, options));
5322 * xmlReaderForFile:
5323 * @filename: a file or URL
5324 * @encoding: the document encoding, or NULL
5325 * @options: a combination of xmlParserOption
5327 * parse an XML file from the filesystem or the network.
5328 * The parsing flags @options are a combination of xmlParserOption.
5330 * Returns the new reader or NULL in case of error.
5332 xmlTextReaderPtr
5333 xmlReaderForFile(const char *filename, const char *encoding, int options)
5335 xmlTextReaderPtr reader;
5337 reader = xmlNewTextReaderFilename(filename);
5338 if (reader == NULL)
5339 return (NULL);
5340 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5341 return (reader);
5345 * xmlReaderForMemory:
5346 * @buffer: a pointer to a char array
5347 * @size: the size of the array
5348 * @URL: the base URL to use for the document
5349 * @encoding: the document encoding, or NULL
5350 * @options: a combination of xmlParserOption
5352 * Create an xmltextReader for an XML in-memory document.
5353 * The parsing flags @options are a combination of xmlParserOption.
5355 * Returns the new reader or NULL in case of error.
5357 xmlTextReaderPtr
5358 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5359 const char *encoding, int options)
5361 xmlTextReaderPtr reader;
5362 xmlParserInputBufferPtr buf;
5364 buf = xmlParserInputBufferCreateStatic(buffer, size,
5365 XML_CHAR_ENCODING_NONE);
5366 if (buf == NULL) {
5367 return (NULL);
5369 reader = xmlNewTextReader(buf, URL);
5370 if (reader == NULL) {
5371 xmlFreeParserInputBuffer(buf);
5372 return (NULL);
5374 reader->allocs |= XML_TEXTREADER_INPUT;
5375 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5376 return (reader);
5380 * xmlReaderForFd:
5381 * @fd: an open file descriptor
5382 * @URL: the base URL to use for the document
5383 * @encoding: the document encoding, or NULL
5384 * @options: a combination of xmlParserOption
5386 * Create an xmltextReader for an XML from a file descriptor.
5387 * The parsing flags @options are a combination of xmlParserOption.
5388 * NOTE that the file descriptor will not be closed when the
5389 * reader is closed or reset.
5391 * Returns the new reader or NULL in case of error.
5393 xmlTextReaderPtr
5394 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5396 xmlTextReaderPtr reader;
5397 xmlParserInputBufferPtr input;
5399 if (fd < 0)
5400 return (NULL);
5402 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5403 if (input == NULL)
5404 return (NULL);
5405 input->closecallback = NULL;
5406 reader = xmlNewTextReader(input, URL);
5407 if (reader == NULL) {
5408 xmlFreeParserInputBuffer(input);
5409 return (NULL);
5411 reader->allocs |= XML_TEXTREADER_INPUT;
5412 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5413 return (reader);
5417 * xmlReaderForIO:
5418 * @ioread: an I/O read function
5419 * @ioclose: an I/O close function
5420 * @ioctx: an I/O handler
5421 * @URL: the base URL to use for the document
5422 * @encoding: the document encoding, or NULL
5423 * @options: a combination of xmlParserOption
5425 * Create an xmltextReader for an XML document from I/O functions and source.
5426 * The parsing flags @options are a combination of xmlParserOption.
5428 * Returns the new reader or NULL in case of error.
5430 xmlTextReaderPtr
5431 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5432 void *ioctx, const char *URL, const char *encoding,
5433 int options)
5435 xmlTextReaderPtr reader;
5436 xmlParserInputBufferPtr input;
5438 if (ioread == NULL)
5439 return (NULL);
5441 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5442 XML_CHAR_ENCODING_NONE);
5443 if (input == NULL) {
5444 if (ioclose != NULL)
5445 ioclose(ioctx);
5446 return (NULL);
5448 reader = xmlNewTextReader(input, URL);
5449 if (reader == NULL) {
5450 xmlFreeParserInputBuffer(input);
5451 return (NULL);
5453 reader->allocs |= XML_TEXTREADER_INPUT;
5454 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5455 return (reader);
5459 * xmlReaderNewWalker:
5460 * @reader: an XML reader
5461 * @doc: a preparsed document
5463 * Setup an xmltextReader to parse a preparsed XML document.
5464 * This reuses the existing @reader xmlTextReader.
5466 * Returns 0 in case of success and -1 in case of error
5469 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5471 if (doc == NULL)
5472 return (-1);
5473 if (reader == NULL)
5474 return (-1);
5476 if (reader->input != NULL) {
5477 xmlFreeParserInputBuffer(reader->input);
5479 if (reader->ctxt != NULL) {
5480 xmlCtxtReset(reader->ctxt);
5483 reader->entNr = 0;
5484 reader->input = NULL;
5485 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5486 reader->node = NULL;
5487 reader->curnode = NULL;
5488 reader->base = 0;
5489 reader->cur = 0;
5490 reader->allocs = XML_TEXTREADER_CTXT;
5491 reader->doc = doc;
5492 reader->state = XML_TEXTREADER_START;
5493 if (reader->dict == NULL) {
5494 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5495 reader->dict = reader->ctxt->dict;
5496 else
5497 reader->dict = xmlDictCreate();
5499 return(0);
5503 * xmlReaderNewDoc:
5504 * @reader: an XML reader
5505 * @cur: a pointer to a zero terminated string
5506 * @URL: the base URL to use for the document
5507 * @encoding: the document encoding, or NULL
5508 * @options: a combination of xmlParserOption
5510 * Setup an xmltextReader to parse an XML in-memory document.
5511 * The parsing flags @options are a combination of xmlParserOption.
5512 * This reuses the existing @reader xmlTextReader.
5514 * Returns 0 in case of success and -1 in case of error
5517 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5518 const char *URL, const char *encoding, int options)
5521 int len;
5523 if (cur == NULL)
5524 return (-1);
5525 if (reader == NULL)
5526 return (-1);
5528 len = xmlStrlen(cur);
5529 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5530 URL, encoding, options));
5534 * xmlReaderNewFile:
5535 * @reader: an XML reader
5536 * @filename: a file or URL
5537 * @encoding: the document encoding, or NULL
5538 * @options: a combination of xmlParserOption
5540 * parse an XML file from the filesystem or the network.
5541 * The parsing flags @options are a combination of xmlParserOption.
5542 * This reuses the existing @reader xmlTextReader.
5544 * Returns 0 in case of success and -1 in case of error
5547 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5548 const char *encoding, int options)
5550 xmlParserInputBufferPtr input;
5552 if (filename == NULL)
5553 return (-1);
5554 if (reader == NULL)
5555 return (-1);
5557 input =
5558 xmlParserInputBufferCreateFilename(filename,
5559 XML_CHAR_ENCODING_NONE);
5560 if (input == NULL)
5561 return (-1);
5562 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5566 * xmlReaderNewMemory:
5567 * @reader: an XML reader
5568 * @buffer: a pointer to a char array
5569 * @size: the size of the array
5570 * @URL: the base URL to use for the document
5571 * @encoding: the document encoding, or NULL
5572 * @options: a combination of xmlParserOption
5574 * Setup an xmltextReader to parse an XML in-memory document.
5575 * The parsing flags @options are a combination of xmlParserOption.
5576 * This reuses the existing @reader xmlTextReader.
5578 * Returns 0 in case of success and -1 in case of error
5581 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5582 const char *URL, const char *encoding, int options)
5584 xmlParserInputBufferPtr input;
5586 if (reader == NULL)
5587 return (-1);
5588 if (buffer == NULL)
5589 return (-1);
5591 input = xmlParserInputBufferCreateStatic(buffer, size,
5592 XML_CHAR_ENCODING_NONE);
5593 if (input == NULL) {
5594 return (-1);
5596 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5600 * xmlReaderNewFd:
5601 * @reader: an XML reader
5602 * @fd: an open file descriptor
5603 * @URL: the base URL to use for the document
5604 * @encoding: the document encoding, or NULL
5605 * @options: a combination of xmlParserOption
5607 * Setup an xmltextReader to parse an XML from a file descriptor.
5608 * NOTE that the file descriptor will not be closed when the
5609 * reader is closed or reset.
5610 * The parsing flags @options are a combination of xmlParserOption.
5611 * This reuses the existing @reader xmlTextReader.
5613 * Returns 0 in case of success and -1 in case of error
5616 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5617 const char *URL, const char *encoding, int options)
5619 xmlParserInputBufferPtr input;
5621 if (fd < 0)
5622 return (-1);
5623 if (reader == NULL)
5624 return (-1);
5626 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5627 if (input == NULL)
5628 return (-1);
5629 input->closecallback = NULL;
5630 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5634 * xmlReaderNewIO:
5635 * @reader: an XML reader
5636 * @ioread: an I/O read function
5637 * @ioclose: an I/O close function
5638 * @ioctx: an I/O handler
5639 * @URL: the base URL to use for the document
5640 * @encoding: the document encoding, or NULL
5641 * @options: a combination of xmlParserOption
5643 * Setup an xmltextReader to parse an XML document from I/O functions
5644 * and source.
5645 * The parsing flags @options are a combination of xmlParserOption.
5646 * This reuses the existing @reader xmlTextReader.
5648 * Returns 0 in case of success and -1 in case of error
5651 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5652 xmlInputCloseCallback ioclose, void *ioctx,
5653 const char *URL, const char *encoding, int options)
5655 xmlParserInputBufferPtr input;
5657 if (ioread == NULL)
5658 return (-1);
5659 if (reader == NULL)
5660 return (-1);
5662 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5663 XML_CHAR_ENCODING_NONE);
5664 if (input == NULL) {
5665 if (ioclose != NULL)
5666 ioclose(ioctx);
5667 return (-1);
5669 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5672 /************************************************************************
5674 * Utilities *
5676 ************************************************************************/
5677 #ifdef NOT_USED_YET
5680 * xmlBase64Decode:
5681 * @in: the input buffer
5682 * @inlen: the size of the input (in), the size read from it (out)
5683 * @to: the output buffer
5684 * @tolen: the size of the output (in), the size written to (out)
5686 * Base64 decoder, reads from @in and save in @to
5687 * TODO: tell jody when this is actually exported
5689 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5690 * 2 if there wasn't enough space on the output or -1 in case of error.
5692 static int
5693 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5694 unsigned char *to, unsigned long *tolen)
5696 unsigned long incur; /* current index in in[] */
5698 unsigned long inblk; /* last block index in in[] */
5700 unsigned long outcur; /* current index in out[] */
5702 unsigned long inmax; /* size of in[] */
5704 unsigned long outmax; /* size of out[] */
5706 unsigned char cur; /* the current value read from in[] */
5708 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5710 int nbintmp; /* number of byte in intmp[] */
5712 int is_ignore; /* cur should be ignored */
5714 int is_end = 0; /* the end of the base64 was found */
5716 int retval = 1;
5718 int i;
5720 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5721 return (-1);
5723 incur = 0;
5724 inblk = 0;
5725 outcur = 0;
5726 inmax = *inlen;
5727 outmax = *tolen;
5728 nbintmp = 0;
5730 while (1) {
5731 if (incur >= inmax)
5732 break;
5733 cur = in[incur++];
5734 is_ignore = 0;
5735 if ((cur >= 'A') && (cur <= 'Z'))
5736 cur = cur - 'A';
5737 else if ((cur >= 'a') && (cur <= 'z'))
5738 cur = cur - 'a' + 26;
5739 else if ((cur >= '0') && (cur <= '9'))
5740 cur = cur - '0' + 52;
5741 else if (cur == '+')
5742 cur = 62;
5743 else if (cur == '/')
5744 cur = 63;
5745 else if (cur == '.')
5746 cur = 0;
5747 else if (cur == '=') /*no op , end of the base64 stream */
5748 is_end = 1;
5749 else {
5750 is_ignore = 1;
5751 if (nbintmp == 0)
5752 inblk = incur;
5755 if (!is_ignore) {
5756 int nbouttmp = 3;
5758 int is_break = 0;
5760 if (is_end) {
5761 if (nbintmp == 0)
5762 break;
5763 if ((nbintmp == 1) || (nbintmp == 2))
5764 nbouttmp = 1;
5765 else
5766 nbouttmp = 2;
5767 nbintmp = 3;
5768 is_break = 1;
5770 intmp[nbintmp++] = cur;
5772 * if intmp is full, push the 4byte sequence as a 3 byte
5773 * sequence out
5775 if (nbintmp == 4) {
5776 nbintmp = 0;
5777 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5778 outtmp[1] =
5779 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5780 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5781 if (outcur + 3 >= outmax) {
5782 retval = 2;
5783 break;
5786 for (i = 0; i < nbouttmp; i++)
5787 to[outcur++] = outtmp[i];
5788 inblk = incur;
5791 if (is_break) {
5792 retval = 0;
5793 break;
5798 *tolen = outcur;
5799 *inlen = inblk;
5800 return (retval);
5804 * Test routine for the xmlBase64Decode function
5806 #if 0
5808 main(int argc, char **argv)
5810 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5812 char output[100];
5814 char output2[100];
5816 char output3[100];
5818 unsigned long inlen = strlen(input);
5820 unsigned long outlen = 100;
5822 int ret;
5824 unsigned long cons, tmp, tmp2, prod;
5827 * Direct
5829 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5831 output[outlen] = 0;
5832 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5833 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5837 * output chunking
5839 cons = 0;
5840 prod = 0;
5841 while (cons < inlen) {
5842 tmp = 5;
5843 tmp2 = inlen - cons;
5845 printf("%ld %ld\n", cons, prod);
5846 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5847 cons += tmp2;
5848 prod += tmp;
5849 printf("%ld %ld\n", cons, prod);
5851 output2[outlen] = 0;
5852 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5853 prod, output2);
5856 * input chunking
5858 cons = 0;
5859 prod = 0;
5860 while (cons < inlen) {
5861 tmp = 100 - prod;
5862 tmp2 = inlen - cons;
5863 if (tmp2 > 5)
5864 tmp2 = 5;
5866 printf("%ld %ld\n", cons, prod);
5867 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5868 cons += tmp2;
5869 prod += tmp;
5870 printf("%ld %ld\n", cons, prod);
5872 output3[outlen] = 0;
5873 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5874 prod, output3);
5875 return (0);
5878 #endif
5879 #endif /* NOT_USED_YET */
5881 #endif /* LIBXML_READER_ENABLED */