VirtualBox

source: vbox/trunk/src/libs/libxml2-2.9.14/xmlreader.c@ 98103

Last change on this file since 98103 was 95312, checked in by vboxsync, 2 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

  • Property svn:eol-style set to native
File size: 166.5 KB
Line 
1/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
4 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
8 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
13/*
14 * TODOs:
15 * - XML Schemas validation
16 */
17#define IN_LIBXML
18#include "libxml.h"
19
20#ifdef LIBXML_READER_ENABLED
21#include <string.h> /* for memset() only ! */
22#include <stdarg.h>
23
24#ifdef HAVE_CTYPE_H
25#include <ctype.h>
26#endif
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#include <libxml/xmlmemory.h>
32#include <libxml/xmlIO.h>
33#include <libxml/xmlreader.h>
34#include <libxml/parserInternals.h>
35#ifdef LIBXML_SCHEMAS_ENABLED
36#include <libxml/relaxng.h>
37#include <libxml/xmlschemas.h>
38#endif
39#include <libxml/uri.h>
40#ifdef LIBXML_XINCLUDE_ENABLED
41#include <libxml/xinclude.h>
42#endif
43#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
46
47#include "buf.h"
48
49#define MAX_ERR_MSG_SIZE 64000
50
51#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
52/* Keeping free objects can hide memory errors. */
53#define MAX_FREE_NODES 1
54#else
55#define MAX_FREE_NODES 100
56#endif
57
58/*
59 * The following VA_COPY was coded following an example in
60 * the Samba project. It may not be sufficient for some
61 * esoteric implementations of va_list but (hopefully) will
62 * be sufficient for libxml2.
63 */
64#ifndef VA_COPY
65 #ifdef HAVE_VA_COPY
66 #define VA_COPY(dest, src) va_copy(dest, src)
67 #else
68 #ifdef HAVE___VA_COPY
69 #define VA_COPY(dest,src) __va_copy(dest, src)
70 #else
71 #ifndef VA_LIST_IS_ARRAY
72 #define VA_COPY(dest,src) (dest) = (src)
73 #else
74 #include <string.h>
75 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
76 #endif
77 #endif
78 #endif
79#endif
80
81/* #define DEBUG_CALLBACKS */
82/* #define DEBUG_READER */
83
84/**
85 * TODO:
86 *
87 * macro to flag unimplemented blocks
88 */
89#define TODO \
90 xmlGenericError(xmlGenericErrorContext, \
91 "Unimplemented block at %s:%d\n", \
92 __FILE__, __LINE__);
93
94#ifdef DEBUG_READER
95#define DUMP_READER xmlTextReaderDebug(reader);
96#else
97#define DUMP_READER
98#endif
99
100#define CHUNK_SIZE 512
101/************************************************************************
102 * *
103 * The parser: maps the Text Reader API on top of the existing *
104 * parsing routines building a tree *
105 * *
106 ************************************************************************/
107
108#define XML_TEXTREADER_INPUT 1
109#define XML_TEXTREADER_CTXT 2
110
111typedef enum {
112 XML_TEXTREADER_NONE = -1,
113 XML_TEXTREADER_START= 0,
114 XML_TEXTREADER_ELEMENT= 1,
115 XML_TEXTREADER_END= 2,
116 XML_TEXTREADER_EMPTY= 3,
117 XML_TEXTREADER_BACKTRACK= 4,
118 XML_TEXTREADER_DONE= 5,
119 XML_TEXTREADER_ERROR= 6
120} xmlTextReaderState;
121
122typedef enum {
123 XML_TEXTREADER_NOT_VALIDATE = 0,
124 XML_TEXTREADER_VALIDATE_DTD = 1,
125 XML_TEXTREADER_VALIDATE_RNG = 2,
126 XML_TEXTREADER_VALIDATE_XSD = 4
127} xmlTextReaderValidate;
128
129struct _xmlTextReader {
130 int mode; /* the parsing mode */
131 xmlDocPtr doc; /* when walking an existing doc */
132 xmlTextReaderValidate validate;/* is there any validation */
133 int allocs; /* what structure were deallocated */
134 xmlTextReaderState state;
135 xmlParserCtxtPtr ctxt; /* the parser context */
136 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
137 xmlParserInputBufferPtr input; /* the input */
138 startElementSAXFunc startElement;/* initial SAX callbacks */
139 endElementSAXFunc endElement; /* idem */
140 startElementNsSAX2Func startElementNs;/* idem */
141 endElementNsSAX2Func endElementNs; /* idem */
142 charactersSAXFunc characters;
143 cdataBlockSAXFunc cdataBlock;
144 unsigned int base; /* base of the segment in the input */
145 unsigned int cur; /* current position in the input */
146 xmlNodePtr node; /* current node */
147 xmlNodePtr curnode;/* current attribute node */
148 int depth; /* depth of the current node */
149 xmlNodePtr faketext;/* fake xmlNs chld */
150 int preserve;/* preserve the resulting document */
151 xmlBufPtr buffer; /* used to return const xmlChar * */
152 xmlDictPtr dict; /* the context dictionary */
153
154 /* entity stack when traversing entities content */
155 xmlNodePtr ent; /* Current Entity Ref Node */
156 int entNr; /* Depth of the entities stack */
157 int entMax; /* Max depth of the entities stack */
158 xmlNodePtr *entTab; /* array of entities */
159
160 /* error handling */
161 xmlTextReaderErrorFunc errorFunc; /* callback function */
162 void *errorFuncArg; /* callback function user argument */
163
164#ifdef LIBXML_SCHEMAS_ENABLED
165 /* Handling of RelaxNG validation */
166 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
167 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
168 int rngPreserveCtxt; /* 1 if the context was provided by the user */
169 int rngValidErrors;/* The number of errors detected */
170 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
171 /* Handling of Schemas validation */
172 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
173 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
174 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
175 int xsdValidErrors;/* The number of errors detected */
176 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
177#endif
178#ifdef LIBXML_XINCLUDE_ENABLED
179 /* Handling of XInclude processing */
180 int xinclude; /* is xinclude asked for */
181 const xmlChar * xinclude_name; /* the xinclude name from dict */
182 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
183 int in_xinclude; /* counts for xinclude */
184#endif
185#ifdef LIBXML_PATTERN_ENABLED
186 int patternNr; /* number of preserve patterns */
187 int patternMax; /* max preserve patterns */
188 xmlPatternPtr *patternTab; /* array of preserve patterns */
189#endif
190 int preserves; /* level of preserves */
191 int parserFlags; /* the set of options set */
192 /* Structured error handling */
193 xmlStructuredErrorFunc sErrorFunc; /* callback function */
194};
195
196#define NODE_IS_EMPTY 0x1
197#define NODE_IS_PRESERVED 0x2
198#define NODE_IS_SPRESERVED 0x4
199
200/**
201 * CONSTSTR:
202 *
203 * Macro used to return an interned string
204 */
205#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
206#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
207
208static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
209static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
210
211/************************************************************************
212 * *
213 * Our own version of the freeing routines as we recycle nodes *
214 * *
215 ************************************************************************/
216/**
217 * DICT_FREE:
218 * @str: a string
219 *
220 * Free a string if it is not owned by the "dict" dictionary in the
221 * current scope
222 */
223#define DICT_FREE(str) \
224 if ((str) && ((!dict) || \
225 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
226 xmlFree((char *)(str));
227
228static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
229static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
230
231/**
232 * xmlFreeID:
233 * @not: A id
234 *
235 * Deallocate the memory used by an id definition
236 */
237static void
238xmlFreeID(xmlIDPtr id) {
239 xmlDictPtr dict = NULL;
240
241 if (id == NULL) return;
242
243 if (id->doc != NULL)
244 dict = id->doc->dict;
245
246 if (id->value != NULL)
247 DICT_FREE(id->value)
248 if (id->name != NULL)
249 DICT_FREE(id->name)
250 xmlFree(id);
251}
252
253/**
254 * xmlTextReaderRemoveID:
255 * @doc: the document
256 * @attr: the attribute
257 *
258 * Remove the given attribute from the ID table maintained internally.
259 *
260 * Returns -1 if the lookup failed and 0 otherwise
261 */
262static int
263xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
264 xmlIDTablePtr table;
265 xmlIDPtr id;
266 xmlChar *ID;
267
268 if (doc == NULL) return(-1);
269 if (attr == NULL) return(-1);
270 table = (xmlIDTablePtr) doc->ids;
271 if (table == NULL)
272 return(-1);
273
274 ID = xmlNodeListGetString(doc, attr->children, 1);
275 if (ID == NULL)
276 return(-1);
277 id = xmlHashLookup(table, ID);
278 xmlFree(ID);
279 if (id == NULL || id->attr != attr) {
280 return(-1);
281 }
282 id->name = attr->name;
283 attr->name = NULL;
284 id->attr = NULL;
285 return(0);
286}
287
288/**
289 * xmlTextReaderWalkRemoveRef:
290 * @data: Contents of current link
291 * @user: Value supplied by the user
292 *
293 * Returns 0 to abort the walk or 1 to continue
294 */
295static int
296xmlTextReaderWalkRemoveRef(const void *data, void *user)
297{
298 xmlRefPtr ref = (xmlRefPtr)data;
299 xmlAttrPtr attr = (xmlAttrPtr)user;
300
301 if (ref->attr == attr) { /* Matched: remove and terminate walk */
302 ref->name = xmlStrdup(attr->name);
303 ref->attr = NULL;
304 return 0;
305 }
306 return 1;
307}
308
309/**
310 * xmlTextReaderRemoveRef:
311 * @doc: the document
312 * @attr: the attribute
313 *
314 * Remove the given attribute from the Ref table maintained internally.
315 *
316 * Returns -1 if the lookup failed and 0 otherwise
317 */
318static int
319xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
320 xmlListPtr ref_list;
321 xmlRefTablePtr table;
322 xmlChar *ID;
323
324 if (doc == NULL) return(-1);
325 if (attr == NULL) return(-1);
326 table = (xmlRefTablePtr) doc->refs;
327 if (table == NULL)
328 return(-1);
329
330 ID = xmlNodeListGetString(doc, attr->children, 1);
331 if (ID == NULL)
332 return(-1);
333 ref_list = xmlHashLookup(table, ID);
334 xmlFree(ID);
335 if(ref_list == NULL)
336 return (-1);
337 xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
338 return(0);
339}
340
341/**
342 * xmlTextReaderFreeProp:
343 * @reader: the xmlTextReaderPtr used
344 * @cur: the node
345 *
346 * Free a node.
347 */
348static void
349xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
350 xmlDictPtr dict;
351
352 if ((reader != NULL) && (reader->ctxt != NULL))
353 dict = reader->ctxt->dict;
354 else
355 dict = NULL;
356 if (cur == NULL) return;
357
358 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
359 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
360
361 /* Check for ID removal -> leading to invalid references ! */
362 if ((cur->parent != NULL) && (cur->parent->doc != NULL)) {
363 if (xmlIsID(cur->parent->doc, cur->parent, cur))
364 xmlTextReaderRemoveID(cur->parent->doc, cur);
365 if (((cur->parent->doc->intSubset != NULL) ||
366 (cur->parent->doc->extSubset != NULL)) &&
367 (xmlIsRef(cur->parent->doc, cur->parent, cur)))
368 xmlTextReaderRemoveRef(cur->parent->doc, cur);
369 }
370 if (cur->children != NULL)
371 xmlTextReaderFreeNodeList(reader, cur->children);
372
373 DICT_FREE(cur->name);
374 if ((reader != NULL) && (reader->ctxt != NULL) &&
375 (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
376 cur->next = reader->ctxt->freeAttrs;
377 reader->ctxt->freeAttrs = cur;
378 reader->ctxt->freeAttrsNr++;
379 } else {
380 xmlFree(cur);
381 }
382}
383
384/**
385 * xmlTextReaderFreePropList:
386 * @reader: the xmlTextReaderPtr used
387 * @cur: the first property in the list
388 *
389 * Free a property and all its siblings, all the children are freed too.
390 */
391static void
392xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
393 xmlAttrPtr next;
394
395 while (cur != NULL) {
396 next = cur->next;
397 xmlTextReaderFreeProp(reader, cur);
398 cur = next;
399 }
400}
401
402/**
403 * xmlTextReaderFreeNodeList:
404 * @reader: the xmlTextReaderPtr used
405 * @cur: the first node in the list
406 *
407 * Free a node and all its siblings, this is a recursive behaviour, all
408 * the children are freed too.
409 */
410static void
411xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
412 xmlNodePtr next;
413 xmlNodePtr parent;
414 xmlDictPtr dict;
415 size_t depth = 0;
416
417 if ((reader != NULL) && (reader->ctxt != NULL))
418 dict = reader->ctxt->dict;
419 else
420 dict = NULL;
421 if (cur == NULL) return;
422 if (cur->type == XML_NAMESPACE_DECL) {
423 xmlFreeNsList((xmlNsPtr) cur);
424 return;
425 }
426 if ((cur->type == XML_DOCUMENT_NODE) ||
427 (cur->type == XML_HTML_DOCUMENT_NODE)) {
428 xmlFreeDoc((xmlDocPtr) cur);
429 return;
430 }
431 while (1) {
432 while ((cur->type != XML_DTD_NODE) &&
433 (cur->type != XML_ENTITY_REF_NODE) &&
434 (cur->children != NULL) &&
435 (cur->children->parent == cur)) {
436 cur = cur->children;
437 depth += 1;
438 }
439
440 next = cur->next;
441 parent = cur->parent;
442
443 /* unroll to speed up freeing the document */
444 if (cur->type != XML_DTD_NODE) {
445
446 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
447 xmlDeregisterNodeDefaultValue(cur);
448
449 if (((cur->type == XML_ELEMENT_NODE) ||
450 (cur->type == XML_XINCLUDE_START) ||
451 (cur->type == XML_XINCLUDE_END)) &&
452 (cur->properties != NULL))
453 xmlTextReaderFreePropList(reader, cur->properties);
454 if ((cur->content != (xmlChar *) &(cur->properties)) &&
455 (cur->type != XML_ELEMENT_NODE) &&
456 (cur->type != XML_XINCLUDE_START) &&
457 (cur->type != XML_XINCLUDE_END) &&
458 (cur->type != XML_ENTITY_REF_NODE)) {
459 DICT_FREE(cur->content);
460 }
461 if (((cur->type == XML_ELEMENT_NODE) ||
462 (cur->type == XML_XINCLUDE_START) ||
463 (cur->type == XML_XINCLUDE_END)) &&
464 (cur->nsDef != NULL))
465 xmlFreeNsList(cur->nsDef);
466
467 /*
468 * we don't free element names here they are interned now
469 */
470 if ((cur->type != XML_TEXT_NODE) &&
471 (cur->type != XML_COMMENT_NODE))
472 DICT_FREE(cur->name);
473 if (((cur->type == XML_ELEMENT_NODE) ||
474 (cur->type == XML_TEXT_NODE)) &&
475 (reader != NULL) && (reader->ctxt != NULL) &&
476 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
477 cur->next = reader->ctxt->freeElems;
478 reader->ctxt->freeElems = cur;
479 reader->ctxt->freeElemsNr++;
480 } else {
481 xmlFree(cur);
482 }
483 }
484
485 if (next != NULL) {
486 cur = next;
487 } else {
488 if ((depth == 0) || (parent == NULL))
489 break;
490 depth -= 1;
491 cur = parent;
492 cur->children = NULL;
493 }
494 }
495}
496
497/**
498 * xmlTextReaderFreeNode:
499 * @reader: the xmlTextReaderPtr used
500 * @cur: the node
501 *
502 * Free a node, this is a recursive behaviour, all the children are freed too.
503 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
504 */
505static void
506xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
507 xmlDictPtr dict;
508
509 if ((reader != NULL) && (reader->ctxt != NULL))
510 dict = reader->ctxt->dict;
511 else
512 dict = NULL;
513 if (cur->type == XML_DTD_NODE) {
514 xmlFreeDtd((xmlDtdPtr) cur);
515 return;
516 }
517 if (cur->type == XML_NAMESPACE_DECL) {
518 xmlFreeNs((xmlNsPtr) cur);
519 return;
520 }
521 if (cur->type == XML_ATTRIBUTE_NODE) {
522 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
523 return;
524 }
525
526 if ((cur->children != NULL) &&
527 (cur->type != XML_ENTITY_REF_NODE)) {
528 if (cur->children->parent == cur)
529 xmlTextReaderFreeNodeList(reader, cur->children);
530 cur->children = NULL;
531 }
532
533 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
534 xmlDeregisterNodeDefaultValue(cur);
535
536 if (((cur->type == XML_ELEMENT_NODE) ||
537 (cur->type == XML_XINCLUDE_START) ||
538 (cur->type == XML_XINCLUDE_END)) &&
539 (cur->properties != NULL))
540 xmlTextReaderFreePropList(reader, cur->properties);
541 if ((cur->content != (xmlChar *) &(cur->properties)) &&
542 (cur->type != XML_ELEMENT_NODE) &&
543 (cur->type != XML_XINCLUDE_START) &&
544 (cur->type != XML_XINCLUDE_END) &&
545 (cur->type != XML_ENTITY_REF_NODE)) {
546 DICT_FREE(cur->content);
547 }
548 if (((cur->type == XML_ELEMENT_NODE) ||
549 (cur->type == XML_XINCLUDE_START) ||
550 (cur->type == XML_XINCLUDE_END)) &&
551 (cur->nsDef != NULL))
552 xmlFreeNsList(cur->nsDef);
553
554 /*
555 * we don't free names here they are interned now
556 */
557 if ((cur->type != XML_TEXT_NODE) &&
558 (cur->type != XML_COMMENT_NODE))
559 DICT_FREE(cur->name);
560
561 if (((cur->type == XML_ELEMENT_NODE) ||
562 (cur->type == XML_TEXT_NODE)) &&
563 (reader != NULL) && (reader->ctxt != NULL) &&
564 (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
565 cur->next = reader->ctxt->freeElems;
566 reader->ctxt->freeElems = cur;
567 reader->ctxt->freeElemsNr++;
568 } else {
569 xmlFree(cur);
570 }
571}
572
573static void
574xmlTextReaderFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) {
575 xmlFreeID((xmlIDPtr) id);
576}
577
578/**
579 * xmlTextReaderFreeIDTable:
580 * @table: An id table
581 *
582 * Deallocate the memory used by an ID hash table.
583 */
584static void
585xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
586 xmlHashFree(table, xmlTextReaderFreeIDTableEntry);
587}
588
589/**
590 * xmlTextReaderFreeDoc:
591 * @reader: the xmlTextReaderPtr used
592 * @cur: pointer to the document
593 *
594 * Free up all the structures used by a document, tree included.
595 */
596static void
597xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
598 xmlDtdPtr extSubset, intSubset;
599
600 if (cur == NULL) return;
601
602 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
603 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
604
605 /*
606 * Do this before freeing the children list to avoid ID lookups
607 */
608 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
609 cur->ids = NULL;
610 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
611 cur->refs = NULL;
612 extSubset = cur->extSubset;
613 intSubset = cur->intSubset;
614 if (intSubset == extSubset)
615 extSubset = NULL;
616 if (extSubset != NULL) {
617 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
618 cur->extSubset = NULL;
619 xmlFreeDtd(extSubset);
620 }
621 if (intSubset != NULL) {
622 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
623 cur->intSubset = NULL;
624 xmlFreeDtd(intSubset);
625 }
626
627 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
628
629 if (cur->version != NULL) xmlFree((char *) cur->version);
630 if (cur->name != NULL) xmlFree((char *) cur->name);
631 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
632 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
633 if (cur->URL != NULL) xmlFree((char *) cur->URL);
634 if (cur->dict != NULL) xmlDictFree(cur->dict);
635
636 xmlFree(cur);
637}
638
639/************************************************************************
640 * *
641 * The reader core parser *
642 * *
643 ************************************************************************/
644#ifdef DEBUG_READER
645static void
646xmlTextReaderDebug(xmlTextReaderPtr reader) {
647 if ((reader == NULL) || (reader->ctxt == NULL)) {
648 fprintf(stderr, "xmlTextReader NULL\n");
649 return;
650 }
651 fprintf(stderr, "xmlTextReader: state %d depth %d ",
652 reader->state, reader->depth);
653 if (reader->node == NULL) {
654 fprintf(stderr, "node = NULL\n");
655 } else {
656 fprintf(stderr, "node %s\n", reader->node->name);
657 }
658 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
659 reader->base, reader->cur, reader->ctxt->nodeNr);
660 if (reader->input->buffer == NULL) {
661 fprintf(stderr, "buffer is NULL\n");
662 } else {
663#ifdef LIBXML_DEBUG_ENABLED
664 xmlDebugDumpString(stderr,
665 &reader->input->buffer->content[reader->cur]);
666#endif
667 fprintf(stderr, "\n");
668 }
669}
670#endif
671
672/**
673 * xmlTextReaderEntPush:
674 * @reader: the xmlTextReaderPtr used
675 * @value: the entity reference node
676 *
677 * Pushes a new entity reference node on top of the entities stack
678 *
679 * Returns 0 in case of error, the index in the stack otherwise
680 */
681static int
682xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
683{
684 if (reader->entMax <= 0) {
685 reader->entMax = 10;
686 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
687 sizeof(reader->entTab[0]));
688 if (reader->entTab == NULL) {
689 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
690 return (0);
691 }
692 }
693 if (reader->entNr >= reader->entMax) {
694 reader->entMax *= 2;
695 reader->entTab =
696 (xmlNodePtr *) xmlRealloc(reader->entTab,
697 reader->entMax *
698 sizeof(reader->entTab[0]));
699 if (reader->entTab == NULL) {
700 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
701 return (0);
702 }
703 }
704 reader->entTab[reader->entNr] = value;
705 reader->ent = value;
706 return (reader->entNr++);
707}
708
709/**
710 * xmlTextReaderEntPop:
711 * @reader: the xmlTextReaderPtr used
712 *
713 * Pops the top element entity from the entities stack
714 *
715 * Returns the entity just removed
716 */
717static xmlNodePtr
718xmlTextReaderEntPop(xmlTextReaderPtr reader)
719{
720 xmlNodePtr ret;
721
722 if (reader->entNr <= 0)
723 return (NULL);
724 reader->entNr--;
725 if (reader->entNr > 0)
726 reader->ent = reader->entTab[reader->entNr - 1];
727 else
728 reader->ent = NULL;
729 ret = reader->entTab[reader->entNr];
730 reader->entTab[reader->entNr] = NULL;
731 return (ret);
732}
733
734/**
735 * xmlTextReaderStartElement:
736 * @ctx: the user data (XML parser context)
737 * @fullname: The element name, including namespace prefix
738 * @atts: An array of name/value attributes pairs, NULL terminated
739 *
740 * called when an opening tag has been processed.
741 */
742static void
743xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
744 const xmlChar **atts) {
745 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
746 xmlTextReaderPtr reader = ctxt->_private;
747
748#ifdef DEBUG_CALLBACKS
749 printf("xmlTextReaderStartElement(%s)\n", fullname);
750#endif
751 if ((reader != NULL) && (reader->startElement != NULL)) {
752 reader->startElement(ctx, fullname, atts);
753 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
754 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
755 (ctxt->input->cur[1] == '>'))
756 ctxt->node->extra = NODE_IS_EMPTY;
757 }
758 if (reader != NULL)
759 reader->state = XML_TEXTREADER_ELEMENT;
760}
761
762/**
763 * xmlTextReaderEndElement:
764 * @ctx: the user data (XML parser context)
765 * @fullname: The element name, including namespace prefix
766 *
767 * called when an ending tag has been processed.
768 */
769static void
770xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
771 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
772 xmlTextReaderPtr reader = ctxt->_private;
773
774#ifdef DEBUG_CALLBACKS
775 printf("xmlTextReaderEndElement(%s)\n", fullname);
776#endif
777 if ((reader != NULL) && (reader->endElement != NULL)) {
778 reader->endElement(ctx, fullname);
779 }
780}
781
782/**
783 * xmlTextReaderStartElementNs:
784 * @ctx: the user data (XML parser context)
785 * @localname: the local name of the element
786 * @prefix: the element namespace prefix if available
787 * @URI: the element namespace name if available
788 * @nb_namespaces: number of namespace definitions on that node
789 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
790 * @nb_attributes: the number of attributes on that node
791 * nb_defaulted: the number of defaulted attributes.
792 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
793 * attribute values.
794 *
795 * called when an opening tag has been processed.
796 */
797static void
798xmlTextReaderStartElementNs(void *ctx,
799 const xmlChar *localname,
800 const xmlChar *prefix,
801 const xmlChar *URI,
802 int nb_namespaces,
803 const xmlChar **namespaces,
804 int nb_attributes,
805 int nb_defaulted,
806 const xmlChar **attributes)
807{
808 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
809 xmlTextReaderPtr reader = ctxt->_private;
810
811#ifdef DEBUG_CALLBACKS
812 printf("xmlTextReaderStartElementNs(%s)\n", localname);
813#endif
814 if ((reader != NULL) && (reader->startElementNs != NULL)) {
815 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
816 namespaces, nb_attributes, nb_defaulted,
817 attributes);
818 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
819 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
820 (ctxt->input->cur[1] == '>'))
821 ctxt->node->extra = NODE_IS_EMPTY;
822 }
823 if (reader != NULL)
824 reader->state = XML_TEXTREADER_ELEMENT;
825}
826
827/**
828 * xmlTextReaderEndElementNs:
829 * @ctx: the user data (XML parser context)
830 * @localname: the local name of the element
831 * @prefix: the element namespace prefix if available
832 * @URI: the element namespace name if available
833 *
834 * called when an ending tag has been processed.
835 */
836static void
837xmlTextReaderEndElementNs(void *ctx,
838 const xmlChar * localname,
839 const xmlChar * prefix,
840 const xmlChar * URI)
841{
842 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
843 xmlTextReaderPtr reader = ctxt->_private;
844
845#ifdef DEBUG_CALLBACKS
846 printf("xmlTextReaderEndElementNs(%s)\n", localname);
847#endif
848 if ((reader != NULL) && (reader->endElementNs != NULL)) {
849 reader->endElementNs(ctx, localname, prefix, URI);
850 }
851}
852
853
854/**
855 * xmlTextReaderCharacters:
856 * @ctx: the user data (XML parser context)
857 * @ch: a xmlChar string
858 * @len: the number of xmlChar
859 *
860 * receiving some chars from the parser.
861 */
862static void
863xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
864{
865 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
866 xmlTextReaderPtr reader = ctxt->_private;
867
868#ifdef DEBUG_CALLBACKS
869 printf("xmlTextReaderCharacters()\n");
870#endif
871 if ((reader != NULL) && (reader->characters != NULL)) {
872 reader->characters(ctx, ch, len);
873 }
874}
875
876/**
877 * xmlTextReaderCDataBlock:
878 * @ctx: the user data (XML parser context)
879 * @value: The pcdata content
880 * @len: the block length
881 *
882 * called when a pcdata block has been parsed
883 */
884static void
885xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
886{
887 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
888 xmlTextReaderPtr reader = ctxt->_private;
889
890#ifdef DEBUG_CALLBACKS
891 printf("xmlTextReaderCDataBlock()\n");
892#endif
893 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
894 reader->cdataBlock(ctx, ch, len);
895 }
896}
897
898/**
899 * xmlTextReaderPushData:
900 * @reader: the xmlTextReaderPtr used
901 *
902 * Push data down the progressive parser until a significant callback
903 * got raised.
904 *
905 * Returns -1 in case of failure, 0 otherwise
906 */
907static int
908xmlTextReaderPushData(xmlTextReaderPtr reader) {
909 xmlBufPtr inbuf;
910 int val, s;
911 xmlTextReaderState oldstate;
912 int alloc;
913
914 if ((reader->input == NULL) || (reader->input->buffer == NULL))
915 return(-1);
916
917 oldstate = reader->state;
918 reader->state = XML_TEXTREADER_NONE;
919 inbuf = reader->input->buffer;
920 alloc = xmlBufGetAllocationScheme(inbuf);
921
922 while (reader->state == XML_TEXTREADER_NONE) {
923 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
924 /*
925 * Refill the buffer unless we are at the end of the stream
926 */
927 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
928 val = xmlParserInputBufferRead(reader->input, 4096);
929 if ((val == 0) &&
930 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
931 if (xmlBufUse(inbuf) == reader->cur) {
932 reader->mode = XML_TEXTREADER_MODE_EOF;
933 reader->state = oldstate;
934 }
935 } else if (val < 0) {
936 reader->mode = XML_TEXTREADER_MODE_EOF;
937 reader->state = oldstate;
938 if ((oldstate != XML_TEXTREADER_START) ||
939 (reader->ctxt->myDoc != NULL))
940 return(val);
941 } else if (val == 0) {
942 /* mark the end of the stream and process the remains */
943 reader->mode = XML_TEXTREADER_MODE_EOF;
944 break;
945 }
946
947 } else
948 break;
949 }
950 /*
951 * parse by block of CHUNK_SIZE bytes, various tests show that
952 * it's the best tradeoff at least on a 1.2GH Duron
953 */
954 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
955 val = xmlParseChunk(reader->ctxt,
956 (const char *) xmlBufContent(inbuf) + reader->cur,
957 CHUNK_SIZE, 0);
958 reader->cur += CHUNK_SIZE;
959 if (val != 0)
960 reader->ctxt->wellFormed = 0;
961 if (reader->ctxt->wellFormed == 0)
962 break;
963 } else {
964 s = xmlBufUse(inbuf) - reader->cur;
965 val = xmlParseChunk(reader->ctxt,
966 (const char *) xmlBufContent(inbuf) + reader->cur,
967 s, 0);
968 reader->cur += s;
969 if (val != 0)
970 reader->ctxt->wellFormed = 0;
971 break;
972 }
973 }
974
975 /*
976 * Discard the consumed input when needed and possible
977 */
978 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
979 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
980 if ((reader->cur >= 4096) &&
981 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
982 val = xmlBufShrink(inbuf, reader->cur);
983 if (val >= 0) {
984 reader->cur -= val;
985 }
986 }
987 }
988 }
989
990 /*
991 * At the end of the stream signal that the work is done to the Push
992 * parser.
993 */
994 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
995 if (reader->state != XML_TEXTREADER_DONE) {
996 s = xmlBufUse(inbuf) - reader->cur;
997 val = xmlParseChunk(reader->ctxt,
998 (const char *) xmlBufContent(inbuf) + reader->cur,
999 s, 1);
1000 reader->cur = xmlBufUse(inbuf);
1001 reader->state = XML_TEXTREADER_DONE;
1002 if (val != 0) {
1003 if (reader->ctxt->wellFormed)
1004 reader->ctxt->wellFormed = 0;
1005 else
1006 return(-1);
1007 }
1008 }
1009 }
1010 reader->state = oldstate;
1011 if (reader->ctxt->wellFormed == 0) {
1012 reader->mode = XML_TEXTREADER_MODE_EOF;
1013 return(-1);
1014 }
1015
1016 return(0);
1017}
1018
1019#ifdef LIBXML_REGEXP_ENABLED
1020/**
1021 * xmlTextReaderValidatePush:
1022 * @reader: the xmlTextReaderPtr used
1023 *
1024 * Push the current node for validation
1025 */
1026static void
1027xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
1028 xmlNodePtr node = reader->node;
1029
1030#ifdef LIBXML_VALID_ENABLED
1031 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1032 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1033 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1034 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
1035 reader->ctxt->myDoc, node, node->name);
1036 } else {
1037 /* TODO use the BuildQName interface */
1038 xmlChar *qname;
1039
1040 qname = xmlStrdup(node->ns->prefix);
1041 qname = xmlStrcat(qname, BAD_CAST ":");
1042 qname = xmlStrcat(qname, node->name);
1043 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
1044 reader->ctxt->myDoc, node, qname);
1045 if (qname != NULL)
1046 xmlFree(qname);
1047 }
1048 }
1049#endif /* LIBXML_VALID_ENABLED */
1050#ifdef LIBXML_SCHEMAS_ENABLED
1051 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1052 (reader->rngValidCtxt != NULL)) {
1053 int ret;
1054
1055 if (reader->rngFullNode != NULL) return;
1056 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
1057 reader->ctxt->myDoc,
1058 node);
1059 if (ret == 0) {
1060 /*
1061 * this element requires a full tree
1062 */
1063 node = xmlTextReaderExpand(reader);
1064 if (node == NULL) {
1065 ret = -1;
1066 } else {
1067 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
1068 reader->ctxt->myDoc,
1069 node);
1070 reader->rngFullNode = node;
1071 }
1072 }
1073 if (ret != 1)
1074 reader->rngValidErrors++;
1075 }
1076#endif
1077}
1078
1079/**
1080 * xmlTextReaderValidateCData:
1081 * @reader: the xmlTextReaderPtr used
1082 * @data: pointer to the CData
1083 * @len: length of the CData block in bytes.
1084 *
1085 * Push some CData for validation
1086 */
1087static void
1088xmlTextReaderValidateCData(xmlTextReaderPtr reader,
1089 const xmlChar *data, int len) {
1090#ifdef LIBXML_VALID_ENABLED
1091 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1092 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1093 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1094 data, len);
1095 }
1096#endif /* LIBXML_VALID_ENABLED */
1097#ifdef LIBXML_SCHEMAS_ENABLED
1098 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1099 (reader->rngValidCtxt != NULL)) {
1100 int ret;
1101
1102 if (reader->rngFullNode != NULL) return;
1103 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1104 if (ret != 1)
1105 reader->rngValidErrors++;
1106 }
1107#endif
1108}
1109
1110/**
1111 * xmlTextReaderValidatePop:
1112 * @reader: the xmlTextReaderPtr used
1113 *
1114 * Pop the current node from validation
1115 */
1116static void
1117xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1118 xmlNodePtr node = reader->node;
1119
1120#ifdef LIBXML_VALID_ENABLED
1121 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1122 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1123 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1124 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1125 reader->ctxt->myDoc, node, node->name);
1126 } else {
1127 /* TODO use the BuildQName interface */
1128 xmlChar *qname;
1129
1130 qname = xmlStrdup(node->ns->prefix);
1131 qname = xmlStrcat(qname, BAD_CAST ":");
1132 qname = xmlStrcat(qname, node->name);
1133 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1134 reader->ctxt->myDoc, node, qname);
1135 if (qname != NULL)
1136 xmlFree(qname);
1137 }
1138 }
1139#endif /* LIBXML_VALID_ENABLED */
1140#ifdef LIBXML_SCHEMAS_ENABLED
1141 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1142 (reader->rngValidCtxt != NULL)) {
1143 int ret;
1144
1145 if (reader->rngFullNode != NULL) {
1146 if (node == reader->rngFullNode)
1147 reader->rngFullNode = NULL;
1148 return;
1149 }
1150 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1151 reader->ctxt->myDoc,
1152 node);
1153 if (ret != 1)
1154 reader->rngValidErrors++;
1155 }
1156#endif
1157}
1158
1159/**
1160 * xmlTextReaderValidateEntity:
1161 * @reader: the xmlTextReaderPtr used
1162 *
1163 * Handle the validation when an entity reference is encountered and
1164 * entity substitution is not activated. As a result the parser interface
1165 * must walk through the entity and do the validation calls
1166 */
1167static void
1168xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1169 xmlNodePtr oldnode = reader->node;
1170 xmlNodePtr node = reader->node;
1171
1172 do {
1173 if (node->type == XML_ENTITY_REF_NODE) {
1174 if ((node->children != NULL) &&
1175 (node->children->type == XML_ENTITY_DECL) &&
1176 (node->children->children != NULL)) {
1177 xmlTextReaderEntPush(reader, node);
1178 node = node->children->children;
1179 continue;
1180 } else {
1181 /*
1182 * The error has probably been raised already.
1183 */
1184 if (node == oldnode)
1185 break;
1186 goto skip_children;
1187 }
1188#ifdef LIBXML_REGEXP_ENABLED
1189 } else if (node->type == XML_ELEMENT_NODE) {
1190 reader->node = node;
1191 xmlTextReaderValidatePush(reader);
1192 } else if ((node->type == XML_TEXT_NODE) ||
1193 (node->type == XML_CDATA_SECTION_NODE)) {
1194 xmlTextReaderValidateCData(reader, node->content,
1195 xmlStrlen(node->content));
1196#endif
1197 }
1198
1199 /*
1200 * go to next node
1201 */
1202 if (node->children != NULL) {
1203 node = node->children;
1204 continue;
1205 } else if (node->type == XML_ELEMENT_NODE) {
1206 xmlTextReaderValidatePop(reader);
1207 }
1208skip_children:
1209 if (node->next != NULL) {
1210 node = node->next;
1211 continue;
1212 }
1213 do {
1214 node = node->parent;
1215 if (node->type == XML_ELEMENT_NODE) {
1216 xmlNodePtr tmp;
1217 if (reader->entNr == 0) {
1218 while ((tmp = node->last) != NULL) {
1219 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1220 xmlUnlinkNode(tmp);
1221 xmlTextReaderFreeNode(reader, tmp);
1222 } else
1223 break;
1224 }
1225 }
1226 reader->node = node;
1227 xmlTextReaderValidatePop(reader);
1228 }
1229 if ((node->type == XML_ENTITY_DECL) &&
1230 (reader->ent != NULL) && (reader->ent->children == node)) {
1231 node = xmlTextReaderEntPop(reader);
1232 }
1233 if (node == oldnode)
1234 break;
1235 if (node->next != NULL) {
1236 node = node->next;
1237 break;
1238 }
1239 } while ((node != NULL) && (node != oldnode));
1240 } while ((node != NULL) && (node != oldnode));
1241 reader->node = oldnode;
1242}
1243#endif /* LIBXML_REGEXP_ENABLED */
1244
1245
1246/**
1247 * xmlTextReaderGetSuccessor:
1248 * @cur: the current node
1249 *
1250 * Get the successor of a node if available.
1251 *
1252 * Returns the successor node or NULL
1253 */
1254static xmlNodePtr
1255xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1256 if (cur == NULL) return(NULL) ; /* ERROR */
1257 if (cur->next != NULL) return(cur->next) ;
1258 do {
1259 cur = cur->parent;
1260 if (cur == NULL) break;
1261 if (cur->next != NULL) return(cur->next);
1262 } while (cur != NULL);
1263 return(cur);
1264}
1265
1266/**
1267 * xmlTextReaderDoExpand:
1268 * @reader: the xmlTextReaderPtr used
1269 *
1270 * Makes sure that the current node is fully read as well as all its
1271 * descendant. It means the full DOM subtree must be available at the
1272 * end of the call.
1273 *
1274 * Returns 1 if the node was expanded successfully, 0 if there is no more
1275 * nodes to read, or -1 in case of error
1276 */
1277static int
1278xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1279 int val;
1280
1281 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1282 return(-1);
1283 do {
1284 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1285
1286 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1287 return(1);
1288 if (reader->ctxt->nodeNr < reader->depth)
1289 return(1);
1290 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1291 return(1);
1292 val = xmlTextReaderPushData(reader);
1293 if (val < 0){
1294 reader->mode = XML_TEXTREADER_MODE_ERROR;
1295 return(-1);
1296 }
1297 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1298 return(1);
1299}
1300
1301/**
1302 * xmlTextReaderCollectSiblings:
1303 * @node: the first child
1304 *
1305 * Traverse depth-first through all sibling nodes and their children
1306 * nodes and concatenate their content. This is an auxiliary function
1307 * to xmlTextReaderReadString.
1308 *
1309 * Returns a string containing the content, or NULL in case of error.
1310 */
1311static xmlChar *
1312xmlTextReaderCollectSiblings(xmlNodePtr node)
1313{
1314 xmlBufferPtr buffer;
1315 xmlChar *ret;
1316
1317 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1318 return(NULL);
1319
1320 buffer = xmlBufferCreate();
1321 if (buffer == NULL)
1322 return NULL;
1323
1324 for ( ; node != NULL; node = node->next) {
1325 switch (node->type) {
1326 case XML_TEXT_NODE:
1327 case XML_CDATA_SECTION_NODE:
1328 xmlBufferCat(buffer, node->content);
1329 break;
1330 case XML_ELEMENT_NODE: {
1331 xmlChar *tmp;
1332
1333 tmp = xmlTextReaderCollectSiblings(node->children);
1334 xmlBufferCat(buffer, tmp);
1335 xmlFree(tmp);
1336 break;
1337 }
1338 default:
1339 break;
1340 }
1341 }
1342 ret = buffer->content;
1343 buffer->content = NULL;
1344 xmlBufferFree(buffer);
1345 return(ret);
1346}
1347
1348/**
1349 * xmlTextReaderRead:
1350 * @reader: the xmlTextReaderPtr used
1351 *
1352 * Moves the position of the current instance to the next node in
1353 * the stream, exposing its properties.
1354 *
1355 * Returns 1 if the node was read successfully, 0 if there is no more
1356 * nodes to read, or -1 in case of error
1357 */
1358int
1359xmlTextReaderRead(xmlTextReaderPtr reader) {
1360 int val, olddepth = 0;
1361 xmlTextReaderState oldstate = XML_TEXTREADER_START;
1362 xmlNodePtr oldnode = NULL;
1363
1364
1365 if (reader == NULL)
1366 return(-1);
1367 reader->curnode = NULL;
1368 if (reader->doc != NULL)
1369 return(xmlTextReaderReadTree(reader));
1370 if (reader->ctxt == NULL)
1371 return(-1);
1372
1373#ifdef DEBUG_READER
1374 fprintf(stderr, "\nREAD ");
1375 DUMP_READER
1376#endif
1377 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1378 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1379 /*
1380 * Initial state
1381 */
1382 do {
1383 val = xmlTextReaderPushData(reader);
1384 if (val < 0){
1385 reader->mode = XML_TEXTREADER_MODE_ERROR;
1386 reader->state = XML_TEXTREADER_ERROR;
1387 return(-1);
1388 }
1389 } while ((reader->ctxt->node == NULL) &&
1390 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1391 (reader->state != XML_TEXTREADER_DONE)));
1392 if (reader->ctxt->node == NULL) {
1393 if (reader->ctxt->myDoc != NULL) {
1394 reader->node = reader->ctxt->myDoc->children;
1395 }
1396 if (reader->node == NULL){
1397 reader->mode = XML_TEXTREADER_MODE_ERROR;
1398 reader->state = XML_TEXTREADER_ERROR;
1399 return(-1);
1400 }
1401 reader->state = XML_TEXTREADER_ELEMENT;
1402 } else {
1403 if (reader->ctxt->myDoc != NULL) {
1404 reader->node = reader->ctxt->myDoc->children;
1405 }
1406 if (reader->node == NULL)
1407 reader->node = reader->ctxt->nodeTab[0];
1408 reader->state = XML_TEXTREADER_ELEMENT;
1409 }
1410 reader->depth = 0;
1411 reader->ctxt->parseMode = XML_PARSE_READER;
1412 goto node_found;
1413 }
1414 oldstate = reader->state;
1415 olddepth = reader->ctxt->nodeNr;
1416 oldnode = reader->node;
1417
1418get_next_node:
1419 if (reader->node == NULL) {
1420 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1421 return(0);
1422 else
1423 return(-1);
1424 }
1425
1426 /*
1427 * If we are not backtracking on ancestors or examined nodes,
1428 * that the parser didn't finished or that we aren't at the end
1429 * of stream, continue processing.
1430 */
1431 while ((reader->node != NULL) && (reader->node->next == NULL) &&
1432 (reader->ctxt->nodeNr == olddepth) &&
1433 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1434 (reader->node->children == NULL) ||
1435 (reader->node->type == XML_ENTITY_REF_NODE) ||
1436 ((reader->node->children != NULL) &&
1437 (reader->node->children->type == XML_TEXT_NODE) &&
1438 (reader->node->children->next == NULL)) ||
1439 (reader->node->type == XML_DTD_NODE) ||
1440 (reader->node->type == XML_DOCUMENT_NODE) ||
1441 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1442 ((reader->ctxt->node == NULL) ||
1443 (reader->ctxt->node == reader->node) ||
1444 (reader->ctxt->node == reader->node->parent)) &&
1445 (reader->ctxt->instate != XML_PARSER_EOF)) {
1446 val = xmlTextReaderPushData(reader);
1447 if (val < 0){
1448 reader->mode = XML_TEXTREADER_MODE_ERROR;
1449 reader->state = XML_TEXTREADER_ERROR;
1450 return(-1);
1451 }
1452 if (reader->node == NULL)
1453 goto node_end;
1454 }
1455 if (oldstate != XML_TEXTREADER_BACKTRACK) {
1456 if ((reader->node->children != NULL) &&
1457 (reader->node->type != XML_ENTITY_REF_NODE) &&
1458 (reader->node->type != XML_XINCLUDE_START) &&
1459 (reader->node->type != XML_DTD_NODE)) {
1460 reader->node = reader->node->children;
1461 reader->depth++;
1462 reader->state = XML_TEXTREADER_ELEMENT;
1463 goto node_found;
1464 }
1465 }
1466 if (reader->node->next != NULL) {
1467 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1468 (reader->node->type == XML_ELEMENT_NODE) &&
1469 (reader->node->children == NULL) &&
1470 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1471#ifdef LIBXML_XINCLUDE_ENABLED
1472 && (reader->in_xinclude <= 0)
1473#endif
1474 ) {
1475 reader->state = XML_TEXTREADER_END;
1476 goto node_found;
1477 }
1478#ifdef LIBXML_REGEXP_ENABLED
1479 if ((reader->validate) &&
1480 (reader->node->type == XML_ELEMENT_NODE))
1481 xmlTextReaderValidatePop(reader);
1482#endif /* LIBXML_REGEXP_ENABLED */
1483 if ((reader->preserves > 0) &&
1484 (reader->node->extra & NODE_IS_SPRESERVED))
1485 reader->preserves--;
1486 reader->node = reader->node->next;
1487 reader->state = XML_TEXTREADER_ELEMENT;
1488
1489 /*
1490 * Cleanup of the old node
1491 */
1492 if ((reader->preserves == 0) &&
1493#ifdef LIBXML_XINCLUDE_ENABLED
1494 (reader->in_xinclude == 0) &&
1495#endif
1496 (reader->entNr == 0) &&
1497 (reader->node->prev != NULL) &&
1498 (reader->node->prev->type != XML_DTD_NODE)) {
1499 xmlNodePtr tmp = reader->node->prev;
1500 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1501 if (oldnode == tmp)
1502 oldnode = NULL;
1503 xmlUnlinkNode(tmp);
1504 xmlTextReaderFreeNode(reader, tmp);
1505 }
1506 }
1507
1508 goto node_found;
1509 }
1510 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1511 (reader->node->type == XML_ELEMENT_NODE) &&
1512 (reader->node->children == NULL) &&
1513 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1514 reader->state = XML_TEXTREADER_END;
1515 goto node_found;
1516 }
1517#ifdef LIBXML_REGEXP_ENABLED
1518 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1519 xmlTextReaderValidatePop(reader);
1520#endif /* LIBXML_REGEXP_ENABLED */
1521 if ((reader->preserves > 0) &&
1522 (reader->node->extra & NODE_IS_SPRESERVED))
1523 reader->preserves--;
1524 reader->node = reader->node->parent;
1525 if ((reader->node == NULL) ||
1526 (reader->node->type == XML_DOCUMENT_NODE) ||
1527#ifdef LIBXML_DOCB_ENABLED
1528 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1529#endif
1530 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1531 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1532 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1533 reader->state = XML_TEXTREADER_DONE;
1534 if (val != 0)
1535 return(-1);
1536 }
1537 reader->node = NULL;
1538 reader->depth = -1;
1539
1540 /*
1541 * Cleanup of the old node
1542 */
1543 if ((oldnode != NULL) && (reader->preserves == 0) &&
1544#ifdef LIBXML_XINCLUDE_ENABLED
1545 (reader->in_xinclude == 0) &&
1546#endif
1547 (reader->entNr == 0) &&
1548 (oldnode->type != XML_DTD_NODE) &&
1549 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1550 xmlUnlinkNode(oldnode);
1551 xmlTextReaderFreeNode(reader, oldnode);
1552 }
1553
1554 goto node_end;
1555 }
1556 if ((reader->preserves == 0) &&
1557#ifdef LIBXML_XINCLUDE_ENABLED
1558 (reader->in_xinclude == 0) &&
1559#endif
1560 (reader->entNr == 0) &&
1561 (reader->node->last != NULL) &&
1562 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1563 xmlNodePtr tmp = reader->node->last;
1564 xmlUnlinkNode(tmp);
1565 xmlTextReaderFreeNode(reader, tmp);
1566 }
1567 reader->depth--;
1568 reader->state = XML_TEXTREADER_BACKTRACK;
1569
1570node_found:
1571 DUMP_READER
1572
1573 /*
1574 * If we are in the middle of a piece of CDATA make sure it's finished
1575 */
1576 if ((reader->node != NULL) &&
1577 (reader->node->next == NULL) &&
1578 ((reader->node->type == XML_TEXT_NODE) ||
1579 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1580 if (xmlTextReaderExpand(reader) == NULL)
1581 return -1;
1582 }
1583
1584#ifdef LIBXML_XINCLUDE_ENABLED
1585 /*
1586 * Handle XInclude if asked for
1587 */
1588 if ((reader->xinclude) && (reader->in_xinclude == 0) &&
1589 (reader->node != NULL) &&
1590 (reader->node->type == XML_ELEMENT_NODE) &&
1591 (reader->node->ns != NULL) &&
1592 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1593 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1594 if (reader->xincctxt == NULL) {
1595 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1596 xmlXIncludeSetFlags(reader->xincctxt,
1597 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1598 }
1599 /*
1600 * expand that node and process it
1601 */
1602 if (xmlTextReaderExpand(reader) == NULL)
1603 return -1;
1604 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1605 }
1606 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1607 reader->in_xinclude++;
1608 goto get_next_node;
1609 }
1610 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1611 reader->in_xinclude--;
1612 goto get_next_node;
1613 }
1614#endif
1615 /*
1616 * Handle entities enter and exit when in entity replacement mode
1617 */
1618 if ((reader->node != NULL) &&
1619 (reader->node->type == XML_ENTITY_REF_NODE) &&
1620 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1621 if ((reader->node->children != NULL) &&
1622 (reader->node->children->type == XML_ENTITY_DECL) &&
1623 (reader->node->children->children != NULL)) {
1624 xmlTextReaderEntPush(reader, reader->node);
1625 reader->node = reader->node->children->children;
1626 }
1627#ifdef LIBXML_REGEXP_ENABLED
1628 } else if ((reader->node != NULL) &&
1629 (reader->node->type == XML_ENTITY_REF_NODE) &&
1630 (reader->ctxt != NULL) && (reader->validate)) {
1631 xmlTextReaderValidateEntity(reader);
1632#endif /* LIBXML_REGEXP_ENABLED */
1633 }
1634 if ((reader->node != NULL) &&
1635 (reader->node->type == XML_ENTITY_DECL) &&
1636 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1637 reader->node = xmlTextReaderEntPop(reader);
1638 reader->depth++;
1639 goto get_next_node;
1640 }
1641#ifdef LIBXML_REGEXP_ENABLED
1642 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1643 xmlNodePtr node = reader->node;
1644
1645 if ((node->type == XML_ELEMENT_NODE) &&
1646 ((reader->state != XML_TEXTREADER_END) &&
1647 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1648 xmlTextReaderValidatePush(reader);
1649 } else if ((node->type == XML_TEXT_NODE) ||
1650 (node->type == XML_CDATA_SECTION_NODE)) {
1651 xmlTextReaderValidateCData(reader, node->content,
1652 xmlStrlen(node->content));
1653 }
1654 }
1655#endif /* LIBXML_REGEXP_ENABLED */
1656#ifdef LIBXML_PATTERN_ENABLED
1657 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1658 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1659 int i;
1660 for (i = 0;i < reader->patternNr;i++) {
1661 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1662 xmlTextReaderPreserve(reader);
1663 break;
1664 }
1665 }
1666 }
1667#endif /* LIBXML_PATTERN_ENABLED */
1668#ifdef LIBXML_SCHEMAS_ENABLED
1669 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1670 (reader->xsdValidErrors == 0) &&
1671 (reader->xsdValidCtxt != NULL)) {
1672 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1673 }
1674#endif /* LIBXML_PATTERN_ENABLED */
1675 return(1);
1676node_end:
1677 reader->state = XML_TEXTREADER_DONE;
1678 return(0);
1679}
1680
1681/**
1682 * xmlTextReaderReadState:
1683 * @reader: the xmlTextReaderPtr used
1684 *
1685 * Gets the read state of the reader.
1686 *
1687 * Returns the state value, or -1 in case of error
1688 */
1689int
1690xmlTextReaderReadState(xmlTextReaderPtr reader) {
1691 if (reader == NULL)
1692 return(-1);
1693 return(reader->mode);
1694}
1695
1696/**
1697 * xmlTextReaderExpand:
1698 * @reader: the xmlTextReaderPtr used
1699 *
1700 * Reads the contents of the current node and the full subtree. It then makes
1701 * the subtree available until the next xmlTextReaderRead() call
1702 *
1703 * Returns a node pointer valid until the next xmlTextReaderRead() call
1704 * or NULL in case of error.
1705 */
1706xmlNodePtr
1707xmlTextReaderExpand(xmlTextReaderPtr reader) {
1708 if ((reader == NULL) || (reader->node == NULL))
1709 return(NULL);
1710 if (reader->doc != NULL)
1711 return(reader->node);
1712 if (reader->ctxt == NULL)
1713 return(NULL);
1714 if (xmlTextReaderDoExpand(reader) < 0)
1715 return(NULL);
1716 return(reader->node);
1717}
1718
1719/**
1720 * xmlTextReaderNext:
1721 * @reader: the xmlTextReaderPtr used
1722 *
1723 * Skip to the node following the current one in document order while
1724 * avoiding the subtree if any.
1725 *
1726 * Returns 1 if the node was read successfully, 0 if there is no more
1727 * nodes to read, or -1 in case of error
1728 */
1729int
1730xmlTextReaderNext(xmlTextReaderPtr reader) {
1731 int ret;
1732 xmlNodePtr cur;
1733
1734 if (reader == NULL)
1735 return(-1);
1736 if (reader->doc != NULL)
1737 return(xmlTextReaderNextTree(reader));
1738 cur = reader->node;
1739 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1740 return(xmlTextReaderRead(reader));
1741 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1742 return(xmlTextReaderRead(reader));
1743 if (cur->extra & NODE_IS_EMPTY)
1744 return(xmlTextReaderRead(reader));
1745 do {
1746 ret = xmlTextReaderRead(reader);
1747 if (ret != 1)
1748 return(ret);
1749 } while (reader->node != cur);
1750 return(xmlTextReaderRead(reader));
1751}
1752
1753#ifdef LIBXML_WRITER_ENABLED
1754/**
1755 * xmlTextReaderReadInnerXml:
1756 * @reader: the xmlTextReaderPtr used
1757 *
1758 * Reads the contents of the current node, including child nodes and markup.
1759 *
1760 * Returns a string containing the XML content, or NULL if the current node
1761 * is neither an element nor attribute, or has no child nodes. The
1762 * string must be deallocated by the caller.
1763 */
1764xmlChar *
1765xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1766{
1767 xmlChar *resbuf;
1768 xmlNodePtr node, cur_node;
1769 xmlBufferPtr buff, buff2;
1770 xmlDocPtr doc;
1771
1772 if (xmlTextReaderExpand(reader) == NULL) {
1773 return NULL;
1774 }
1775 doc = reader->node->doc;
1776 buff = xmlBufferCreate();
1777 if (buff == NULL)
1778 return NULL;
1779 for (cur_node = reader->node->children; cur_node != NULL;
1780 cur_node = cur_node->next) {
1781 /* XXX: Why is the node copied? */
1782 node = xmlDocCopyNode(cur_node, doc, 1);
1783 buff2 = xmlBufferCreate();
1784 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1785 xmlFreeNode(node);
1786 xmlBufferFree(buff2);
1787 xmlBufferFree(buff);
1788 return NULL;
1789 }
1790 xmlBufferCat(buff, buff2->content);
1791 xmlFreeNode(node);
1792 xmlBufferFree(buff2);
1793 }
1794 resbuf = buff->content;
1795 buff->content = NULL;
1796
1797 xmlBufferFree(buff);
1798 return resbuf;
1799}
1800#endif
1801
1802#ifdef LIBXML_WRITER_ENABLED
1803/**
1804 * xmlTextReaderReadOuterXml:
1805 * @reader: the xmlTextReaderPtr used
1806 *
1807 * Reads the contents of the current node, including child nodes and markup.
1808 *
1809 * Returns a string containing the node and any XML content, or NULL if the
1810 * current node cannot be serialized. The string must be deallocated
1811 * by the caller.
1812 */
1813xmlChar *
1814xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1815{
1816 xmlChar *resbuf;
1817 xmlNodePtr node;
1818 xmlBufferPtr buff;
1819 xmlDocPtr doc;
1820
1821 if (xmlTextReaderExpand(reader) == NULL) {
1822 return NULL;
1823 }
1824 node = reader->node;
1825 doc = node->doc;
1826 /* XXX: Why is the node copied? */
1827 if (node->type == XML_DTD_NODE) {
1828 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1829 } else {
1830 node = xmlDocCopyNode(node, doc, 1);
1831 }
1832 buff = xmlBufferCreate();
1833 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1834 xmlFreeNode(node);
1835 xmlBufferFree(buff);
1836 return NULL;
1837 }
1838
1839 resbuf = buff->content;
1840 buff->content = NULL;
1841
1842 xmlFreeNode(node);
1843 xmlBufferFree(buff);
1844 return resbuf;
1845}
1846#endif
1847
1848/**
1849 * xmlTextReaderReadString:
1850 * @reader: the xmlTextReaderPtr used
1851 *
1852 * Reads the contents of an element or a text node as a string.
1853 *
1854 * Returns a string containing the contents of the Element or Text node,
1855 * or NULL if the reader is positioned on any other type of node.
1856 * The string must be deallocated by the caller.
1857 */
1858xmlChar *
1859xmlTextReaderReadString(xmlTextReaderPtr reader)
1860{
1861 xmlNodePtr node;
1862
1863 if ((reader == NULL) || (reader->node == NULL))
1864 return(NULL);
1865
1866 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1867 switch (node->type) {
1868 case XML_TEXT_NODE:
1869 if (node->content != NULL)
1870 return(xmlStrdup(node->content));
1871 break;
1872 case XML_ELEMENT_NODE:
1873 if (xmlTextReaderDoExpand(reader) != -1) {
1874 return xmlTextReaderCollectSiblings(node->children);
1875 }
1876 break;
1877 case XML_ATTRIBUTE_NODE:
1878 TODO
1879 break;
1880 default:
1881 break;
1882 }
1883 return(NULL);
1884}
1885
1886#if 0
1887/**
1888 * xmlTextReaderReadBase64:
1889 * @reader: the xmlTextReaderPtr used
1890 * @array: a byte array to store the content.
1891 * @offset: the zero-based index into array where the method should
1892 * begin to write.
1893 * @len: the number of bytes to write.
1894 *
1895 * Reads and decodes the Base64 encoded contents of an element and
1896 * stores the result in a byte buffer.
1897 *
1898 * Returns the number of bytes written to array, or zero if the current
1899 * instance is not positioned on an element or -1 in case of error.
1900 */
1901int
1902xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1903 unsigned char *array ATTRIBUTE_UNUSED,
1904 int offset ATTRIBUTE_UNUSED,
1905 int len ATTRIBUTE_UNUSED) {
1906 if ((reader == NULL) || (reader->ctxt == NULL))
1907 return(-1);
1908 if (reader->ctxt->wellFormed != 1)
1909 return(-1);
1910
1911 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1912 return(0);
1913 TODO
1914 return(0);
1915}
1916
1917/**
1918 * xmlTextReaderReadBinHex:
1919 * @reader: the xmlTextReaderPtr used
1920 * @array: a byte array to store the content.
1921 * @offset: the zero-based index into array where the method should
1922 * begin to write.
1923 * @len: the number of bytes to write.
1924 *
1925 * Reads and decodes the BinHex encoded contents of an element and
1926 * stores the result in a byte buffer.
1927 *
1928 * Returns the number of bytes written to array, or zero if the current
1929 * instance is not positioned on an element or -1 in case of error.
1930 */
1931int
1932xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1933 unsigned char *array ATTRIBUTE_UNUSED,
1934 int offset ATTRIBUTE_UNUSED,
1935 int len ATTRIBUTE_UNUSED) {
1936 if ((reader == NULL) || (reader->ctxt == NULL))
1937 return(-1);
1938 if (reader->ctxt->wellFormed != 1)
1939 return(-1);
1940
1941 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1942 return(0);
1943 TODO
1944 return(0);
1945}
1946#endif
1947
1948/************************************************************************
1949 * *
1950 * Operating on a preparsed tree *
1951 * *
1952 ************************************************************************/
1953static int
1954xmlTextReaderNextTree(xmlTextReaderPtr reader)
1955{
1956 if (reader == NULL)
1957 return(-1);
1958
1959 if (reader->state == XML_TEXTREADER_END)
1960 return(0);
1961
1962 if (reader->node == NULL) {
1963 if (reader->doc->children == NULL) {
1964 reader->state = XML_TEXTREADER_END;
1965 return(0);
1966 }
1967
1968 reader->node = reader->doc->children;
1969 reader->state = XML_TEXTREADER_START;
1970 return(1);
1971 }
1972
1973 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1974 /* Here removed traversal to child, because we want to skip the subtree,
1975 replace with traversal to sibling to skip subtree */
1976 if (reader->node->next != 0) {
1977 /* Move to sibling if present,skipping sub-tree */
1978 reader->node = reader->node->next;
1979 reader->state = XML_TEXTREADER_START;
1980 return(1);
1981 }
1982
1983 /* if reader->node->next is NULL mean no subtree for current node,
1984 so need to move to sibling of parent node if present */
1985 reader->state = XML_TEXTREADER_BACKTRACK;
1986 /* This will move to parent if present */
1987 xmlTextReaderRead(reader);
1988 }
1989
1990 if (reader->node->next != 0) {
1991 reader->node = reader->node->next;
1992 reader->state = XML_TEXTREADER_START;
1993 return(1);
1994 }
1995
1996 if (reader->node->parent != 0) {
1997 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1998 reader->state = XML_TEXTREADER_END;
1999 return(0);
2000 }
2001
2002 reader->node = reader->node->parent;
2003 reader->depth--;
2004 reader->state = XML_TEXTREADER_BACKTRACK;
2005 /* Repeat process to move to sibling of parent node if present */
2006 xmlTextReaderNextTree(reader);
2007 }
2008
2009 reader->state = XML_TEXTREADER_END;
2010
2011 return(1);
2012}
2013
2014/**
2015 * xmlTextReaderReadTree:
2016 * @reader: the xmlTextReaderPtr used
2017 *
2018 * Moves the position of the current instance to the next node in
2019 * the stream, exposing its properties.
2020 *
2021 * Returns 1 if the node was read successfully, 0 if there is no more
2022 * nodes to read, or -1 in case of error
2023 */
2024static int
2025xmlTextReaderReadTree(xmlTextReaderPtr reader) {
2026 if (reader->state == XML_TEXTREADER_END)
2027 return(0);
2028
2029next_node:
2030 if (reader->node == NULL) {
2031 if (reader->doc->children == NULL) {
2032 reader->state = XML_TEXTREADER_END;
2033 return(0);
2034 }
2035
2036 reader->node = reader->doc->children;
2037 reader->state = XML_TEXTREADER_START;
2038 goto found_node;
2039 }
2040
2041 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
2042 (reader->node->type != XML_DTD_NODE) &&
2043 (reader->node->type != XML_XINCLUDE_START) &&
2044 (reader->node->type != XML_ENTITY_REF_NODE)) {
2045 if (reader->node->children != NULL) {
2046 reader->node = reader->node->children;
2047 reader->depth++;
2048 reader->state = XML_TEXTREADER_START;
2049 goto found_node;
2050 }
2051
2052 if (reader->node->type == XML_ATTRIBUTE_NODE) {
2053 reader->state = XML_TEXTREADER_BACKTRACK;
2054 goto found_node;
2055 }
2056 }
2057
2058 if (reader->node->next != NULL) {
2059 reader->node = reader->node->next;
2060 reader->state = XML_TEXTREADER_START;
2061 goto found_node;
2062 }
2063
2064 if (reader->node->parent != NULL) {
2065 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
2066 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2067 reader->state = XML_TEXTREADER_END;
2068 return(0);
2069 }
2070
2071 reader->node = reader->node->parent;
2072 reader->depth--;
2073 reader->state = XML_TEXTREADER_BACKTRACK;
2074 goto found_node;
2075 }
2076
2077 reader->state = XML_TEXTREADER_END;
2078
2079found_node:
2080 if ((reader->node->type == XML_XINCLUDE_START) ||
2081 (reader->node->type == XML_XINCLUDE_END))
2082 goto next_node;
2083
2084 return(1);
2085}
2086
2087/**
2088 * xmlTextReaderNextSibling:
2089 * @reader: the xmlTextReaderPtr used
2090 *
2091 * Skip to the node following the current one in document order while
2092 * avoiding the subtree if any.
2093 * Currently implemented only for Readers built on a document
2094 *
2095 * Returns 1 if the node was read successfully, 0 if there is no more
2096 * nodes to read, or -1 in case of error
2097 */
2098int
2099xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2100 if (reader == NULL)
2101 return(-1);
2102 if (reader->doc == NULL) {
2103 /* TODO */
2104 return(-1);
2105 }
2106
2107 if (reader->state == XML_TEXTREADER_END)
2108 return(0);
2109
2110 if (reader->node == NULL)
2111 return(xmlTextReaderNextTree(reader));
2112
2113 if (reader->node->next != NULL) {
2114 reader->node = reader->node->next;
2115 reader->state = XML_TEXTREADER_START;
2116 return(1);
2117 }
2118
2119 return(0);
2120}
2121
2122/************************************************************************
2123 * *
2124 * Constructor and destructors *
2125 * *
2126 ************************************************************************/
2127/**
2128 * xmlNewTextReader:
2129 * @input: the xmlParserInputBufferPtr used to read data
2130 * @URI: the URI information for the source if available
2131 *
2132 * Create an xmlTextReader structure fed with @input
2133 *
2134 * Returns the new xmlTextReaderPtr or NULL in case of error
2135 */
2136xmlTextReaderPtr
2137xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2138 xmlTextReaderPtr ret;
2139
2140 if (input == NULL)
2141 return(NULL);
2142 ret = xmlMalloc(sizeof(xmlTextReader));
2143 if (ret == NULL) {
2144 xmlGenericError(xmlGenericErrorContext,
2145 "xmlNewTextReader : malloc failed\n");
2146 return(NULL);
2147 }
2148 memset(ret, 0, sizeof(xmlTextReader));
2149 ret->doc = NULL;
2150 ret->entTab = NULL;
2151 ret->entMax = 0;
2152 ret->entNr = 0;
2153 ret->input = input;
2154 ret->buffer = xmlBufCreateSize(100);
2155 if (ret->buffer == NULL) {
2156 xmlFree(ret);
2157 xmlGenericError(xmlGenericErrorContext,
2158 "xmlNewTextReader : malloc failed\n");
2159 return(NULL);
2160 }
2161 /* no operation on a reader should require a huge buffer */
2162 xmlBufSetAllocationScheme(ret->buffer,
2163 XML_BUFFER_ALLOC_BOUNDED);
2164 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2165 if (ret->sax == NULL) {
2166 xmlBufFree(ret->buffer);
2167 xmlFree(ret);
2168 xmlGenericError(xmlGenericErrorContext,
2169 "xmlNewTextReader : malloc failed\n");
2170 return(NULL);
2171 }
2172 xmlSAXVersion(ret->sax, 2);
2173 ret->startElement = ret->sax->startElement;
2174 ret->sax->startElement = xmlTextReaderStartElement;
2175 ret->endElement = ret->sax->endElement;
2176 ret->sax->endElement = xmlTextReaderEndElement;
2177#ifdef LIBXML_SAX1_ENABLED
2178 if (ret->sax->initialized == XML_SAX2_MAGIC) {
2179#endif /* LIBXML_SAX1_ENABLED */
2180 ret->startElementNs = ret->sax->startElementNs;
2181 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2182 ret->endElementNs = ret->sax->endElementNs;
2183 ret->sax->endElementNs = xmlTextReaderEndElementNs;
2184#ifdef LIBXML_SAX1_ENABLED
2185 } else {
2186 ret->startElementNs = NULL;
2187 ret->endElementNs = NULL;
2188 }
2189#endif /* LIBXML_SAX1_ENABLED */
2190 ret->characters = ret->sax->characters;
2191 ret->sax->characters = xmlTextReaderCharacters;
2192 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2193 ret->cdataBlock = ret->sax->cdataBlock;
2194 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2195
2196 ret->mode = XML_TEXTREADER_MODE_INITIAL;
2197 ret->node = NULL;
2198 ret->curnode = NULL;
2199 if (xmlBufUse(ret->input->buffer) < 4) {
2200 xmlParserInputBufferRead(input, 4);
2201 }
2202 if (xmlBufUse(ret->input->buffer) >= 4) {
2203 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2204 (const char *) xmlBufContent(ret->input->buffer),
2205 4, URI);
2206 ret->base = 0;
2207 ret->cur = 4;
2208 } else {
2209 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2210 ret->base = 0;
2211 ret->cur = 0;
2212 }
2213
2214 if (ret->ctxt == NULL) {
2215 xmlGenericError(xmlGenericErrorContext,
2216 "xmlNewTextReader : malloc failed\n");
2217 xmlBufFree(ret->buffer);
2218 xmlFree(ret->sax);
2219 xmlFree(ret);
2220 return(NULL);
2221 }
2222 ret->ctxt->parseMode = XML_PARSE_READER;
2223 ret->ctxt->_private = ret;
2224 ret->ctxt->linenumbers = 1;
2225 ret->ctxt->dictNames = 1;
2226 ret->allocs = XML_TEXTREADER_CTXT;
2227 /*
2228 * use the parser dictionary to allocate all elements and attributes names
2229 */
2230 ret->ctxt->docdict = 1;
2231 ret->dict = ret->ctxt->dict;
2232#ifdef LIBXML_XINCLUDE_ENABLED
2233 ret->xinclude = 0;
2234#endif
2235#ifdef LIBXML_PATTERN_ENABLED
2236 ret->patternMax = 0;
2237 ret->patternTab = NULL;
2238#endif
2239 return(ret);
2240}
2241
2242/**
2243 * xmlNewTextReaderFilename:
2244 * @URI: the URI of the resource to process
2245 *
2246 * Create an xmlTextReader structure fed with the resource at @URI
2247 *
2248 * Returns the new xmlTextReaderPtr or NULL in case of error
2249 */
2250xmlTextReaderPtr
2251xmlNewTextReaderFilename(const char *URI) {
2252 xmlParserInputBufferPtr input;
2253 xmlTextReaderPtr ret;
2254 char *directory = NULL;
2255
2256 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2257 if (input == NULL)
2258 return(NULL);
2259 ret = xmlNewTextReader(input, URI);
2260 if (ret == NULL) {
2261 xmlFreeParserInputBuffer(input);
2262 return(NULL);
2263 }
2264 ret->allocs |= XML_TEXTREADER_INPUT;
2265 if (ret->ctxt->directory == NULL)
2266 directory = xmlParserGetDirectory(URI);
2267 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2268 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2269 if (directory != NULL)
2270 xmlFree(directory);
2271 return(ret);
2272}
2273
2274/**
2275 * xmlFreeTextReader:
2276 * @reader: the xmlTextReaderPtr
2277 *
2278 * Deallocate all the resources associated to the reader
2279 */
2280void
2281xmlFreeTextReader(xmlTextReaderPtr reader) {
2282 if (reader == NULL)
2283 return;
2284#ifdef LIBXML_SCHEMAS_ENABLED
2285 if (reader->rngSchemas != NULL) {
2286 xmlRelaxNGFree(reader->rngSchemas);
2287 reader->rngSchemas = NULL;
2288 }
2289 if (reader->rngValidCtxt != NULL) {
2290 if (! reader->rngPreserveCtxt)
2291 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2292 reader->rngValidCtxt = NULL;
2293 }
2294 if (reader->xsdPlug != NULL) {
2295 xmlSchemaSAXUnplug(reader->xsdPlug);
2296 reader->xsdPlug = NULL;
2297 }
2298 if (reader->xsdValidCtxt != NULL) {
2299 if (! reader->xsdPreserveCtxt)
2300 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2301 reader->xsdValidCtxt = NULL;
2302 }
2303 if (reader->xsdSchemas != NULL) {
2304 xmlSchemaFree(reader->xsdSchemas);
2305 reader->xsdSchemas = NULL;
2306 }
2307#endif
2308#ifdef LIBXML_XINCLUDE_ENABLED
2309 if (reader->xincctxt != NULL)
2310 xmlXIncludeFreeContext(reader->xincctxt);
2311#endif
2312#ifdef LIBXML_PATTERN_ENABLED
2313 if (reader->patternTab != NULL) {
2314 int i;
2315 for (i = 0;i < reader->patternNr;i++) {
2316 if (reader->patternTab[i] != NULL)
2317 xmlFreePattern(reader->patternTab[i]);
2318 }
2319 xmlFree(reader->patternTab);
2320 }
2321#endif
2322 if (reader->faketext != NULL) {
2323 xmlFreeNode(reader->faketext);
2324 }
2325 if (reader->ctxt != NULL) {
2326 if (reader->dict == reader->ctxt->dict)
2327 reader->dict = NULL;
2328#ifdef LIBXML_VALID_ENABLED
2329 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2330 (reader->ctxt->vctxt.vstateMax > 0)){
2331#ifdef LIBXML_REGEXP_ENABLED
2332 while (reader->ctxt->vctxt.vstateNr > 0)
2333 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
2334#endif /* LIBXML_REGEXP_ENABLED */
2335 xmlFree(reader->ctxt->vctxt.vstateTab);
2336 reader->ctxt->vctxt.vstateTab = NULL;
2337 reader->ctxt->vctxt.vstateMax = 0;
2338 }
2339#endif /* LIBXML_VALID_ENABLED */
2340 if (reader->ctxt->myDoc != NULL) {
2341 if (reader->preserve == 0)
2342 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2343 reader->ctxt->myDoc = NULL;
2344 }
2345 if (reader->allocs & XML_TEXTREADER_CTXT)
2346 xmlFreeParserCtxt(reader->ctxt);
2347 }
2348 if (reader->sax != NULL)
2349 xmlFree(reader->sax);
2350 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2351 xmlFreeParserInputBuffer(reader->input);
2352 if (reader->buffer != NULL)
2353 xmlBufFree(reader->buffer);
2354 if (reader->entTab != NULL)
2355 xmlFree(reader->entTab);
2356 if (reader->dict != NULL)
2357 xmlDictFree(reader->dict);
2358 xmlFree(reader);
2359}
2360
2361/************************************************************************
2362 * *
2363 * Methods for XmlTextReader *
2364 * *
2365 ************************************************************************/
2366/**
2367 * xmlTextReaderClose:
2368 * @reader: the xmlTextReaderPtr used
2369 *
2370 * This method releases any resources allocated by the current instance
2371 * changes the state to Closed and close any underlying input.
2372 *
2373 * Returns 0 or -1 in case of error
2374 */
2375int
2376xmlTextReaderClose(xmlTextReaderPtr reader) {
2377 if (reader == NULL)
2378 return(-1);
2379 reader->node = NULL;
2380 reader->curnode = NULL;
2381 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2382 if (reader->ctxt != NULL) {
2383 xmlStopParser(reader->ctxt);
2384 if (reader->ctxt->myDoc != NULL) {
2385 if (reader->preserve == 0)
2386 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2387 reader->ctxt->myDoc = NULL;
2388 }
2389 }
2390 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2391 xmlFreeParserInputBuffer(reader->input);
2392 reader->allocs -= XML_TEXTREADER_INPUT;
2393 }
2394 return(0);
2395}
2396
2397/**
2398 * xmlTextReaderGetAttributeNo:
2399 * @reader: the xmlTextReaderPtr used
2400 * @no: the zero-based index of the attribute relative to the containing element
2401 *
2402 * Provides the value of the attribute with the specified index relative
2403 * to the containing element.
2404 *
2405 * Returns a string containing the value of the specified attribute, or NULL
2406 * in case of error. The string must be deallocated by the caller.
2407 */
2408xmlChar *
2409xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2410 xmlChar *ret;
2411 int i;
2412 xmlAttrPtr cur;
2413 xmlNsPtr ns;
2414
2415 if (reader == NULL)
2416 return(NULL);
2417 if (reader->node == NULL)
2418 return(NULL);
2419 if (reader->curnode != NULL)
2420 return(NULL);
2421 /* TODO: handle the xmlDecl */
2422 if (reader->node->type != XML_ELEMENT_NODE)
2423 return(NULL);
2424
2425 ns = reader->node->nsDef;
2426 for (i = 0;(i < no) && (ns != NULL);i++) {
2427 ns = ns->next;
2428 }
2429 if (ns != NULL)
2430 return(xmlStrdup(ns->href));
2431
2432 cur = reader->node->properties;
2433 if (cur == NULL)
2434 return(NULL);
2435 for (;i < no;i++) {
2436 cur = cur->next;
2437 if (cur == NULL)
2438 return(NULL);
2439 }
2440 /* TODO walk the DTD if present */
2441
2442 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2443 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2444 return(ret);
2445}
2446
2447/**
2448 * xmlTextReaderGetAttribute:
2449 * @reader: the xmlTextReaderPtr used
2450 * @name: the qualified name of the attribute.
2451 *
2452 * Provides the value of the attribute with the specified qualified name.
2453 *
2454 * Returns a string containing the value of the specified attribute, or NULL
2455 * in case of error. The string must be deallocated by the caller.
2456 */
2457xmlChar *
2458xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2459 xmlChar *prefix = NULL;
2460 xmlChar *localname;
2461 xmlNsPtr ns;
2462 xmlChar *ret = NULL;
2463
2464 if ((reader == NULL) || (name == NULL))
2465 return(NULL);
2466 if (reader->node == NULL)
2467 return(NULL);
2468 if (reader->curnode != NULL)
2469 return(NULL);
2470
2471 /* TODO: handle the xmlDecl */
2472 if (reader->node->type != XML_ELEMENT_NODE)
2473 return(NULL);
2474
2475 localname = xmlSplitQName2(name, &prefix);
2476 if (localname == NULL) {
2477 /*
2478 * Namespace default decl
2479 */
2480 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2481 ns = reader->node->nsDef;
2482 while (ns != NULL) {
2483 if (ns->prefix == NULL) {
2484 return(xmlStrdup(ns->href));
2485 }
2486 ns = ns->next;
2487 }
2488 return NULL;
2489 }
2490 return(xmlGetNoNsProp(reader->node, name));
2491 }
2492
2493 /*
2494 * Namespace default decl
2495 */
2496 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2497 ns = reader->node->nsDef;
2498 while (ns != NULL) {
2499 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2500 ret = xmlStrdup(ns->href);
2501 break;
2502 }
2503 ns = ns->next;
2504 }
2505 } else {
2506 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2507 if (ns != NULL)
2508 ret = xmlGetNsProp(reader->node, localname, ns->href);
2509 }
2510
2511 xmlFree(localname);
2512 if (prefix != NULL)
2513 xmlFree(prefix);
2514 return(ret);
2515}
2516
2517
2518/**
2519 * xmlTextReaderGetAttributeNs:
2520 * @reader: the xmlTextReaderPtr used
2521 * @localName: the local name of the attribute.
2522 * @namespaceURI: the namespace URI of the attribute.
2523 *
2524 * Provides the value of the specified attribute
2525 *
2526 * Returns a string containing the value of the specified attribute, or NULL
2527 * in case of error. The string must be deallocated by the caller.
2528 */
2529xmlChar *
2530xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2531 const xmlChar *namespaceURI) {
2532 xmlChar *prefix = NULL;
2533 xmlNsPtr ns;
2534
2535 if ((reader == NULL) || (localName == NULL))
2536 return(NULL);
2537 if (reader->node == NULL)
2538 return(NULL);
2539 if (reader->curnode != NULL)
2540 return(NULL);
2541
2542 /* TODO: handle the xmlDecl */
2543 if (reader->node->type != XML_ELEMENT_NODE)
2544 return(NULL);
2545
2546 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2547 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2548 prefix = BAD_CAST localName;
2549 }
2550 ns = reader->node->nsDef;
2551 while (ns != NULL) {
2552 if ((prefix == NULL && ns->prefix == NULL) ||
2553 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2554 return xmlStrdup(ns->href);
2555 }
2556 ns = ns->next;
2557 }
2558 return NULL;
2559 }
2560
2561 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2562}
2563
2564/**
2565 * xmlTextReaderGetRemainder:
2566 * @reader: the xmlTextReaderPtr used
2567 *
2568 * Method to get the remainder of the buffered XML. this method stops the
2569 * parser, set its state to End Of File and return the input stream with
2570 * what is left that the parser did not use.
2571 *
2572 * The implementation is not good, the parser certainly progressed past
2573 * what's left in reader->input, and there is an allocation problem. Best
2574 * would be to rewrite it differently.
2575 *
2576 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2577 * in case of error.
2578 */
2579xmlParserInputBufferPtr
2580xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2581 xmlParserInputBufferPtr ret = NULL;
2582
2583 if (reader == NULL)
2584 return(NULL);
2585 if (reader->node == NULL)
2586 return(NULL);
2587
2588 reader->node = NULL;
2589 reader->curnode = NULL;
2590 reader->mode = XML_TEXTREADER_MODE_EOF;
2591 if (reader->ctxt != NULL) {
2592 xmlStopParser(reader->ctxt);
2593 if (reader->ctxt->myDoc != NULL) {
2594 if (reader->preserve == 0)
2595 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2596 reader->ctxt->myDoc = NULL;
2597 }
2598 }
2599 if (reader->allocs & XML_TEXTREADER_INPUT) {
2600 ret = reader->input;
2601 reader->input = NULL;
2602 reader->allocs -= XML_TEXTREADER_INPUT;
2603 } else {
2604 /*
2605 * Hum, one may need to duplicate the data structure because
2606 * without reference counting the input may be freed twice:
2607 * - by the layer which allocated it.
2608 * - by the layer to which would have been returned to.
2609 */
2610 TODO
2611 return(NULL);
2612 }
2613 return(ret);
2614}
2615
2616/**
2617 * xmlTextReaderLookupNamespace:
2618 * @reader: the xmlTextReaderPtr used
2619 * @prefix: the prefix whose namespace URI is to be resolved. To return
2620 * the default namespace, specify NULL
2621 *
2622 * Resolves a namespace prefix in the scope of the current element.
2623 *
2624 * Returns a string containing the namespace URI to which the prefix maps
2625 * or NULL in case of error. The string must be deallocated by the caller.
2626 */
2627xmlChar *
2628xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2629 xmlNsPtr ns;
2630
2631 if (reader == NULL)
2632 return(NULL);
2633 if (reader->node == NULL)
2634 return(NULL);
2635
2636 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2637 if (ns == NULL)
2638 return(NULL);
2639 return(xmlStrdup(ns->href));
2640}
2641
2642/**
2643 * xmlTextReaderMoveToAttributeNo:
2644 * @reader: the xmlTextReaderPtr used
2645 * @no: the zero-based index of the attribute relative to the containing
2646 * element.
2647 *
2648 * Moves the position of the current instance to the attribute with
2649 * the specified index relative to the containing element.
2650 *
2651 * Returns 1 in case of success, -1 in case of error, 0 if not found
2652 */
2653int
2654xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2655 int i;
2656 xmlAttrPtr cur;
2657 xmlNsPtr ns;
2658
2659 if (reader == NULL)
2660 return(-1);
2661 if (reader->node == NULL)
2662 return(-1);
2663 /* TODO: handle the xmlDecl */
2664 if (reader->node->type != XML_ELEMENT_NODE)
2665 return(-1);
2666
2667 reader->curnode = NULL;
2668
2669 ns = reader->node->nsDef;
2670 for (i = 0;(i < no) && (ns != NULL);i++) {
2671 ns = ns->next;
2672 }
2673 if (ns != NULL) {
2674 reader->curnode = (xmlNodePtr) ns;
2675 return(1);
2676 }
2677
2678 cur = reader->node->properties;
2679 if (cur == NULL)
2680 return(0);
2681 for (;i < no;i++) {
2682 cur = cur->next;
2683 if (cur == NULL)
2684 return(0);
2685 }
2686 /* TODO walk the DTD if present */
2687
2688 reader->curnode = (xmlNodePtr) cur;
2689 return(1);
2690}
2691
2692/**
2693 * xmlTextReaderMoveToAttribute:
2694 * @reader: the xmlTextReaderPtr used
2695 * @name: the qualified name of the attribute.
2696 *
2697 * Moves the position of the current instance to the attribute with
2698 * the specified qualified name.
2699 *
2700 * Returns 1 in case of success, -1 in case of error, 0 if not found
2701 */
2702int
2703xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2704 xmlChar *prefix = NULL;
2705 xmlChar *localname;
2706 xmlNsPtr ns;
2707 xmlAttrPtr prop;
2708
2709 if ((reader == NULL) || (name == NULL))
2710 return(-1);
2711 if (reader->node == NULL)
2712 return(-1);
2713
2714 /* TODO: handle the xmlDecl */
2715 if (reader->node->type != XML_ELEMENT_NODE)
2716 return(0);
2717
2718 localname = xmlSplitQName2(name, &prefix);
2719 if (localname == NULL) {
2720 /*
2721 * Namespace default decl
2722 */
2723 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2724 ns = reader->node->nsDef;
2725 while (ns != NULL) {
2726 if (ns->prefix == NULL) {
2727 reader->curnode = (xmlNodePtr) ns;
2728 return(1);
2729 }
2730 ns = ns->next;
2731 }
2732 return(0);
2733 }
2734
2735 prop = reader->node->properties;
2736 while (prop != NULL) {
2737 /*
2738 * One need to have
2739 * - same attribute names
2740 * - and the attribute carrying that namespace
2741 */
2742 if ((xmlStrEqual(prop->name, name)) &&
2743 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2744 reader->curnode = (xmlNodePtr) prop;
2745 return(1);
2746 }
2747 prop = prop->next;
2748 }
2749 return(0);
2750 }
2751
2752 /*
2753 * Namespace default decl
2754 */
2755 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2756 ns = reader->node->nsDef;
2757 while (ns != NULL) {
2758 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2759 reader->curnode = (xmlNodePtr) ns;
2760 goto found;
2761 }
2762 ns = ns->next;
2763 }
2764 goto not_found;
2765 }
2766 prop = reader->node->properties;
2767 while (prop != NULL) {
2768 /*
2769 * One need to have
2770 * - same attribute names
2771 * - and the attribute carrying that namespace
2772 */
2773 if ((xmlStrEqual(prop->name, localname)) &&
2774 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2775 reader->curnode = (xmlNodePtr) prop;
2776 goto found;
2777 }
2778 prop = prop->next;
2779 }
2780not_found:
2781 if (localname != NULL)
2782 xmlFree(localname);
2783 if (prefix != NULL)
2784 xmlFree(prefix);
2785 return(0);
2786
2787found:
2788 if (localname != NULL)
2789 xmlFree(localname);
2790 if (prefix != NULL)
2791 xmlFree(prefix);
2792 return(1);
2793}
2794
2795/**
2796 * xmlTextReaderMoveToAttributeNs:
2797 * @reader: the xmlTextReaderPtr used
2798 * @localName: the local name of the attribute.
2799 * @namespaceURI: the namespace URI of the attribute.
2800 *
2801 * Moves the position of the current instance to the attribute with the
2802 * specified local name and namespace URI.
2803 *
2804 * Returns 1 in case of success, -1 in case of error, 0 if not found
2805 */
2806int
2807xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2808 const xmlChar *localName, const xmlChar *namespaceURI) {
2809 xmlAttrPtr prop;
2810 xmlNodePtr node;
2811 xmlNsPtr ns;
2812 xmlChar *prefix = NULL;
2813
2814 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2815 return(-1);
2816 if (reader->node == NULL)
2817 return(-1);
2818 if (reader->node->type != XML_ELEMENT_NODE)
2819 return(0);
2820 node = reader->node;
2821
2822 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2823 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2824 prefix = BAD_CAST localName;
2825 }
2826 ns = reader->node->nsDef;
2827 while (ns != NULL) {
2828 if ((prefix == NULL && ns->prefix == NULL) ||
2829 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2830 reader->curnode = (xmlNodePtr) ns;
2831 return(1);
2832 }
2833 ns = ns->next;
2834 }
2835 return(0);
2836 }
2837
2838 prop = node->properties;
2839 while (prop != NULL) {
2840 /*
2841 * One need to have
2842 * - same attribute names
2843 * - and the attribute carrying that namespace
2844 */
2845 if (xmlStrEqual(prop->name, localName) &&
2846 ((prop->ns != NULL) &&
2847 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2848 reader->curnode = (xmlNodePtr) prop;
2849 return(1);
2850 }
2851 prop = prop->next;
2852 }
2853 return(0);
2854}
2855
2856/**
2857 * xmlTextReaderMoveToFirstAttribute:
2858 * @reader: the xmlTextReaderPtr used
2859 *
2860 * Moves the position of the current instance to the first attribute
2861 * associated with the current node.
2862 *
2863 * Returns 1 in case of success, -1 in case of error, 0 if not found
2864 */
2865int
2866xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2867 if (reader == NULL)
2868 return(-1);
2869 if (reader->node == NULL)
2870 return(-1);
2871 if (reader->node->type != XML_ELEMENT_NODE)
2872 return(0);
2873
2874 if (reader->node->nsDef != NULL) {
2875 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2876 return(1);
2877 }
2878 if (reader->node->properties != NULL) {
2879 reader->curnode = (xmlNodePtr) reader->node->properties;
2880 return(1);
2881 }
2882 return(0);
2883}
2884
2885/**
2886 * xmlTextReaderMoveToNextAttribute:
2887 * @reader: the xmlTextReaderPtr used
2888 *
2889 * Moves the position of the current instance to the next attribute
2890 * associated with the current node.
2891 *
2892 * Returns 1 in case of success, -1 in case of error, 0 if not found
2893 */
2894int
2895xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2896 if (reader == NULL)
2897 return(-1);
2898 if (reader->node == NULL)
2899 return(-1);
2900 if (reader->node->type != XML_ELEMENT_NODE)
2901 return(0);
2902 if (reader->curnode == NULL)
2903 return(xmlTextReaderMoveToFirstAttribute(reader));
2904
2905 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2906 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2907 if (ns->next != NULL) {
2908 reader->curnode = (xmlNodePtr) ns->next;
2909 return(1);
2910 }
2911 if (reader->node->properties != NULL) {
2912 reader->curnode = (xmlNodePtr) reader->node->properties;
2913 return(1);
2914 }
2915 return(0);
2916 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2917 (reader->curnode->next != NULL)) {
2918 reader->curnode = reader->curnode->next;
2919 return(1);
2920 }
2921 return(0);
2922}
2923
2924/**
2925 * xmlTextReaderMoveToElement:
2926 * @reader: the xmlTextReaderPtr used
2927 *
2928 * Moves the position of the current instance to the node that
2929 * contains the current Attribute node.
2930 *
2931 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2932 */
2933int
2934xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2935 if (reader == NULL)
2936 return(-1);
2937 if (reader->node == NULL)
2938 return(-1);
2939 if (reader->node->type != XML_ELEMENT_NODE)
2940 return(0);
2941 if (reader->curnode != NULL) {
2942 reader->curnode = NULL;
2943 return(1);
2944 }
2945 return(0);
2946}
2947
2948/**
2949 * xmlTextReaderReadAttributeValue:
2950 * @reader: the xmlTextReaderPtr used
2951 *
2952 * Parses an attribute value into one or more Text and EntityReference nodes.
2953 *
2954 * Returns 1 in case of success, 0 if the reader was not positioned on an
2955 * attribute node or all the attribute values have been read, or -1
2956 * in case of error.
2957 */
2958int
2959xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2960 if (reader == NULL)
2961 return(-1);
2962 if (reader->node == NULL)
2963 return(-1);
2964 if (reader->curnode == NULL)
2965 return(0);
2966 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2967 if (reader->curnode->children == NULL)
2968 return(0);
2969 reader->curnode = reader->curnode->children;
2970 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2971 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2972
2973 if (reader->faketext == NULL) {
2974 reader->faketext = xmlNewDocText(reader->node->doc,
2975 ns->href);
2976 } else {
2977 if ((reader->faketext->content != NULL) &&
2978 (reader->faketext->content !=
2979 (xmlChar *) &(reader->faketext->properties)))
2980 xmlFree(reader->faketext->content);
2981 reader->faketext->content = xmlStrdup(ns->href);
2982 }
2983 reader->curnode = reader->faketext;
2984 } else {
2985 if (reader->curnode->next == NULL)
2986 return(0);
2987 reader->curnode = reader->curnode->next;
2988 }
2989 return(1);
2990}
2991
2992/**
2993 * xmlTextReaderConstEncoding:
2994 * @reader: the xmlTextReaderPtr used
2995 *
2996 * Determine the encoding of the document being read.
2997 *
2998 * Returns a string containing the encoding of the document or NULL in
2999 * case of error. The string is deallocated with the reader.
3000 */
3001const xmlChar *
3002xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
3003 xmlDocPtr doc = NULL;
3004 if (reader == NULL)
3005 return(NULL);
3006 if (reader->doc != NULL)
3007 doc = reader->doc;
3008 else if (reader->ctxt != NULL)
3009 doc = reader->ctxt->myDoc;
3010 if (doc == NULL)
3011 return(NULL);
3012
3013 if (doc->encoding == NULL)
3014 return(NULL);
3015 else
3016 return(CONSTSTR(doc->encoding));
3017}
3018
3019
3020/************************************************************************
3021 * *
3022 * Access API to the current node *
3023 * *
3024 ************************************************************************/
3025/**
3026 * xmlTextReaderAttributeCount:
3027 * @reader: the xmlTextReaderPtr used
3028 *
3029 * Provides the number of attributes of the current node
3030 *
3031 * Returns 0 i no attributes, -1 in case of error or the attribute count
3032 */
3033int
3034xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
3035 int ret;
3036 xmlAttrPtr attr;
3037 xmlNsPtr ns;
3038 xmlNodePtr node;
3039
3040 if (reader == NULL)
3041 return(-1);
3042 if (reader->node == NULL)
3043 return(0);
3044
3045 if (reader->curnode != NULL)
3046 node = reader->curnode;
3047 else
3048 node = reader->node;
3049
3050 if (node->type != XML_ELEMENT_NODE)
3051 return(0);
3052 if ((reader->state == XML_TEXTREADER_END) ||
3053 (reader->state == XML_TEXTREADER_BACKTRACK))
3054 return(0);
3055 ret = 0;
3056 attr = node->properties;
3057 while (attr != NULL) {
3058 ret++;
3059 attr = attr->next;
3060 }
3061 ns = node->nsDef;
3062 while (ns != NULL) {
3063 ret++;
3064 ns = ns->next;
3065 }
3066 return(ret);
3067}
3068
3069/**
3070 * xmlTextReaderNodeType:
3071 * @reader: the xmlTextReaderPtr used
3072 *
3073 * Get the node type of the current node
3074 * Reference:
3075 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
3076 *
3077 * Returns the xmlReaderTypes of the current node or -1 in case of error
3078 */
3079int
3080xmlTextReaderNodeType(xmlTextReaderPtr reader) {
3081 xmlNodePtr node;
3082
3083 if (reader == NULL)
3084 return(-1);
3085 if (reader->node == NULL)
3086 return(XML_READER_TYPE_NONE);
3087 if (reader->curnode != NULL)
3088 node = reader->curnode;
3089 else
3090 node = reader->node;
3091 switch (node->type) {
3092 case XML_ELEMENT_NODE:
3093 if ((reader->state == XML_TEXTREADER_END) ||
3094 (reader->state == XML_TEXTREADER_BACKTRACK))
3095 return(XML_READER_TYPE_END_ELEMENT);
3096 return(XML_READER_TYPE_ELEMENT);
3097 case XML_NAMESPACE_DECL:
3098 case XML_ATTRIBUTE_NODE:
3099 return(XML_READER_TYPE_ATTRIBUTE);
3100 case XML_TEXT_NODE:
3101 if (xmlIsBlankNode(reader->node)) {
3102 if (xmlNodeGetSpacePreserve(reader->node))
3103 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3104 else
3105 return(XML_READER_TYPE_WHITESPACE);
3106 } else {
3107 return(XML_READER_TYPE_TEXT);
3108 }
3109 case XML_CDATA_SECTION_NODE:
3110 return(XML_READER_TYPE_CDATA);
3111 case XML_ENTITY_REF_NODE:
3112 return(XML_READER_TYPE_ENTITY_REFERENCE);
3113 case XML_ENTITY_NODE:
3114 return(XML_READER_TYPE_ENTITY);
3115 case XML_PI_NODE:
3116 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3117 case XML_COMMENT_NODE:
3118 return(XML_READER_TYPE_COMMENT);
3119 case XML_DOCUMENT_NODE:
3120 case XML_HTML_DOCUMENT_NODE:
3121#ifdef LIBXML_DOCB_ENABLED
3122 case XML_DOCB_DOCUMENT_NODE:
3123#endif
3124 return(XML_READER_TYPE_DOCUMENT);
3125 case XML_DOCUMENT_FRAG_NODE:
3126 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3127 case XML_NOTATION_NODE:
3128 return(XML_READER_TYPE_NOTATION);
3129 case XML_DOCUMENT_TYPE_NODE:
3130 case XML_DTD_NODE:
3131 return(XML_READER_TYPE_DOCUMENT_TYPE);
3132
3133 case XML_ELEMENT_DECL:
3134 case XML_ATTRIBUTE_DECL:
3135 case XML_ENTITY_DECL:
3136 case XML_XINCLUDE_START:
3137 case XML_XINCLUDE_END:
3138 return(XML_READER_TYPE_NONE);
3139 }
3140 return(-1);
3141}
3142
3143/**
3144 * xmlTextReaderIsEmptyElement:
3145 * @reader: the xmlTextReaderPtr used
3146 *
3147 * Check if the current node is empty
3148 *
3149 * Returns 1 if empty, 0 if not and -1 in case of error
3150 */
3151int
3152xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3153 if ((reader == NULL) || (reader->node == NULL))
3154 return(-1);
3155 if (reader->node->type != XML_ELEMENT_NODE)
3156 return(0);
3157 if (reader->curnode != NULL)
3158 return(0);
3159 if (reader->node->children != NULL)
3160 return(0);
3161 if (reader->state == XML_TEXTREADER_END)
3162 return(0);
3163 if (reader->doc != NULL)
3164 return(1);
3165#ifdef LIBXML_XINCLUDE_ENABLED
3166 if (reader->in_xinclude > 0)
3167 return(1);
3168#endif
3169 return((reader->node->extra & NODE_IS_EMPTY) != 0);
3170}
3171
3172/**
3173 * xmlTextReaderLocalName:
3174 * @reader: the xmlTextReaderPtr used
3175 *
3176 * The local name of the node.
3177 *
3178 * Returns the local name or NULL if not available,
3179 * if non NULL it need to be freed by the caller.
3180 */
3181xmlChar *
3182xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3183 xmlNodePtr node;
3184 if ((reader == NULL) || (reader->node == NULL))
3185 return(NULL);
3186 if (reader->curnode != NULL)
3187 node = reader->curnode;
3188 else
3189 node = reader->node;
3190 if (node->type == XML_NAMESPACE_DECL) {
3191 xmlNsPtr ns = (xmlNsPtr) node;
3192 if (ns->prefix == NULL)
3193 return(xmlStrdup(BAD_CAST "xmlns"));
3194 else
3195 return(xmlStrdup(ns->prefix));
3196 }
3197 if ((node->type != XML_ELEMENT_NODE) &&
3198 (node->type != XML_ATTRIBUTE_NODE))
3199 return(xmlTextReaderName(reader));
3200 return(xmlStrdup(node->name));
3201}
3202
3203/**
3204 * xmlTextReaderConstLocalName:
3205 * @reader: the xmlTextReaderPtr used
3206 *
3207 * The local name of the node.
3208 *
3209 * Returns the local name or NULL if not available, the
3210 * string will be deallocated with the reader.
3211 */
3212const xmlChar *
3213xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3214 xmlNodePtr node;
3215 if ((reader == NULL) || (reader->node == NULL))
3216 return(NULL);
3217 if (reader->curnode != NULL)
3218 node = reader->curnode;
3219 else
3220 node = reader->node;
3221 if (node->type == XML_NAMESPACE_DECL) {
3222 xmlNsPtr ns = (xmlNsPtr) node;
3223 if (ns->prefix == NULL)
3224 return(CONSTSTR(BAD_CAST "xmlns"));
3225 else
3226 return(ns->prefix);
3227 }
3228 if ((node->type != XML_ELEMENT_NODE) &&
3229 (node->type != XML_ATTRIBUTE_NODE))
3230 return(xmlTextReaderConstName(reader));
3231 return(node->name);
3232}
3233
3234/**
3235 * xmlTextReaderName:
3236 * @reader: the xmlTextReaderPtr used
3237 *
3238 * The qualified name of the node, equal to Prefix :LocalName.
3239 *
3240 * Returns the local name or NULL if not available,
3241 * if non NULL it need to be freed by the caller.
3242 */
3243xmlChar *
3244xmlTextReaderName(xmlTextReaderPtr reader) {
3245 xmlNodePtr node;
3246 xmlChar *ret;
3247
3248 if ((reader == NULL) || (reader->node == NULL))
3249 return(NULL);
3250 if (reader->curnode != NULL)
3251 node = reader->curnode;
3252 else
3253 node = reader->node;
3254 switch (node->type) {
3255 case XML_ELEMENT_NODE:
3256 case XML_ATTRIBUTE_NODE:
3257 if ((node->ns == NULL) ||
3258 (node->ns->prefix == NULL))
3259 return(xmlStrdup(node->name));
3260
3261 ret = xmlStrdup(node->ns->prefix);
3262 ret = xmlStrcat(ret, BAD_CAST ":");
3263 ret = xmlStrcat(ret, node->name);
3264 return(ret);
3265 case XML_TEXT_NODE:
3266 return(xmlStrdup(BAD_CAST "#text"));
3267 case XML_CDATA_SECTION_NODE:
3268 return(xmlStrdup(BAD_CAST "#cdata-section"));
3269 case XML_ENTITY_NODE:
3270 case XML_ENTITY_REF_NODE:
3271 return(xmlStrdup(node->name));
3272 case XML_PI_NODE:
3273 return(xmlStrdup(node->name));
3274 case XML_COMMENT_NODE:
3275 return(xmlStrdup(BAD_CAST "#comment"));
3276 case XML_DOCUMENT_NODE:
3277 case XML_HTML_DOCUMENT_NODE:
3278#ifdef LIBXML_DOCB_ENABLED
3279 case XML_DOCB_DOCUMENT_NODE:
3280#endif
3281 return(xmlStrdup(BAD_CAST "#document"));
3282 case XML_DOCUMENT_FRAG_NODE:
3283 return(xmlStrdup(BAD_CAST "#document-fragment"));
3284 case XML_NOTATION_NODE:
3285 return(xmlStrdup(node->name));
3286 case XML_DOCUMENT_TYPE_NODE:
3287 case XML_DTD_NODE:
3288 return(xmlStrdup(node->name));
3289 case XML_NAMESPACE_DECL: {
3290 xmlNsPtr ns = (xmlNsPtr) node;
3291
3292 ret = xmlStrdup(BAD_CAST "xmlns");
3293 if (ns->prefix == NULL)
3294 return(ret);
3295 ret = xmlStrcat(ret, BAD_CAST ":");
3296 ret = xmlStrcat(ret, ns->prefix);
3297 return(ret);
3298 }
3299
3300 case XML_ELEMENT_DECL:
3301 case XML_ATTRIBUTE_DECL:
3302 case XML_ENTITY_DECL:
3303 case XML_XINCLUDE_START:
3304 case XML_XINCLUDE_END:
3305 return(NULL);
3306 }
3307 return(NULL);
3308}
3309
3310/**
3311 * xmlTextReaderConstName:
3312 * @reader: the xmlTextReaderPtr used
3313 *
3314 * The qualified name of the node, equal to Prefix :LocalName.
3315 *
3316 * Returns the local name or NULL if not available, the string is
3317 * deallocated with the reader.
3318 */
3319const xmlChar *
3320xmlTextReaderConstName(xmlTextReaderPtr reader) {
3321 xmlNodePtr node;
3322
3323 if ((reader == NULL) || (reader->node == NULL))
3324 return(NULL);
3325 if (reader->curnode != NULL)
3326 node = reader->curnode;
3327 else
3328 node = reader->node;
3329 switch (node->type) {
3330 case XML_ELEMENT_NODE:
3331 case XML_ATTRIBUTE_NODE:
3332 if ((node->ns == NULL) ||
3333 (node->ns->prefix == NULL))
3334 return(node->name);
3335 return(CONSTQSTR(node->ns->prefix, node->name));
3336 case XML_TEXT_NODE:
3337 return(CONSTSTR(BAD_CAST "#text"));
3338 case XML_CDATA_SECTION_NODE:
3339 return(CONSTSTR(BAD_CAST "#cdata-section"));
3340 case XML_ENTITY_NODE:
3341 case XML_ENTITY_REF_NODE:
3342 return(CONSTSTR(node->name));
3343 case XML_PI_NODE:
3344 return(CONSTSTR(node->name));
3345 case XML_COMMENT_NODE:
3346 return(CONSTSTR(BAD_CAST "#comment"));
3347 case XML_DOCUMENT_NODE:
3348 case XML_HTML_DOCUMENT_NODE:
3349#ifdef LIBXML_DOCB_ENABLED
3350 case XML_DOCB_DOCUMENT_NODE:
3351#endif
3352 return(CONSTSTR(BAD_CAST "#document"));
3353 case XML_DOCUMENT_FRAG_NODE:
3354 return(CONSTSTR(BAD_CAST "#document-fragment"));
3355 case XML_NOTATION_NODE:
3356 return(CONSTSTR(node->name));
3357 case XML_DOCUMENT_TYPE_NODE:
3358 case XML_DTD_NODE:
3359 return(CONSTSTR(node->name));
3360 case XML_NAMESPACE_DECL: {
3361 xmlNsPtr ns = (xmlNsPtr) node;
3362
3363 if (ns->prefix == NULL)
3364 return(CONSTSTR(BAD_CAST "xmlns"));
3365 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3366 }
3367
3368 case XML_ELEMENT_DECL:
3369 case XML_ATTRIBUTE_DECL:
3370 case XML_ENTITY_DECL:
3371 case XML_XINCLUDE_START:
3372 case XML_XINCLUDE_END:
3373 return(NULL);
3374 }
3375 return(NULL);
3376}
3377
3378/**
3379 * xmlTextReaderPrefix:
3380 * @reader: the xmlTextReaderPtr used
3381 *
3382 * A shorthand reference to the namespace associated with the node.
3383 *
3384 * Returns the prefix or NULL if not available,
3385 * if non NULL it need to be freed by the caller.
3386 */
3387xmlChar *
3388xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3389 xmlNodePtr node;
3390 if ((reader == NULL) || (reader->node == NULL))
3391 return(NULL);
3392 if (reader->curnode != NULL)
3393 node = reader->curnode;
3394 else
3395 node = reader->node;
3396 if (node->type == XML_NAMESPACE_DECL) {
3397 xmlNsPtr ns = (xmlNsPtr) node;
3398 if (ns->prefix == NULL)
3399 return(NULL);
3400 return(xmlStrdup(BAD_CAST "xmlns"));
3401 }
3402 if ((node->type != XML_ELEMENT_NODE) &&
3403 (node->type != XML_ATTRIBUTE_NODE))
3404 return(NULL);
3405 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3406 return(xmlStrdup(node->ns->prefix));
3407 return(NULL);
3408}
3409
3410/**
3411 * xmlTextReaderConstPrefix:
3412 * @reader: the xmlTextReaderPtr used
3413 *
3414 * A shorthand reference to the namespace associated with the node.
3415 *
3416 * Returns the prefix or NULL if not available, the string is deallocated
3417 * with the reader.
3418 */
3419const xmlChar *
3420xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3421 xmlNodePtr node;
3422 if ((reader == NULL) || (reader->node == NULL))
3423 return(NULL);
3424 if (reader->curnode != NULL)
3425 node = reader->curnode;
3426 else
3427 node = reader->node;
3428 if (node->type == XML_NAMESPACE_DECL) {
3429 xmlNsPtr ns = (xmlNsPtr) node;
3430 if (ns->prefix == NULL)
3431 return(NULL);
3432 return(CONSTSTR(BAD_CAST "xmlns"));
3433 }
3434 if ((node->type != XML_ELEMENT_NODE) &&
3435 (node->type != XML_ATTRIBUTE_NODE))
3436 return(NULL);
3437 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3438 return(CONSTSTR(node->ns->prefix));
3439 return(NULL);
3440}
3441
3442/**
3443 * xmlTextReaderNamespaceUri:
3444 * @reader: the xmlTextReaderPtr used
3445 *
3446 * The URI defining the namespace associated with the node.
3447 *
3448 * Returns the namespace URI or NULL if not available,
3449 * if non NULL it need to be freed by the caller.
3450 */
3451xmlChar *
3452xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3453 xmlNodePtr node;
3454 if ((reader == NULL) || (reader->node == NULL))
3455 return(NULL);
3456 if (reader->curnode != NULL)
3457 node = reader->curnode;
3458 else
3459 node = reader->node;
3460 if (node->type == XML_NAMESPACE_DECL)
3461 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3462 if ((node->type != XML_ELEMENT_NODE) &&
3463 (node->type != XML_ATTRIBUTE_NODE))
3464 return(NULL);
3465 if (node->ns != NULL)
3466 return(xmlStrdup(node->ns->href));
3467 return(NULL);
3468}
3469
3470/**
3471 * xmlTextReaderConstNamespaceUri:
3472 * @reader: the xmlTextReaderPtr used
3473 *
3474 * The URI defining the namespace associated with the node.
3475 *
3476 * Returns the namespace URI or NULL if not available, the string
3477 * will be deallocated with the reader
3478 */
3479const xmlChar *
3480xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3481 xmlNodePtr node;
3482 if ((reader == NULL) || (reader->node == NULL))
3483 return(NULL);
3484 if (reader->curnode != NULL)
3485 node = reader->curnode;
3486 else
3487 node = reader->node;
3488 if (node->type == XML_NAMESPACE_DECL)
3489 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3490 if ((node->type != XML_ELEMENT_NODE) &&
3491 (node->type != XML_ATTRIBUTE_NODE))
3492 return(NULL);
3493 if (node->ns != NULL)
3494 return(CONSTSTR(node->ns->href));
3495 return(NULL);
3496}
3497
3498/**
3499 * xmlTextReaderBaseUri:
3500 * @reader: the xmlTextReaderPtr used
3501 *
3502 * The base URI of the node.
3503 *
3504 * Returns the base URI or NULL if not available,
3505 * if non NULL it need to be freed by the caller.
3506 */
3507xmlChar *
3508xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3509 if ((reader == NULL) || (reader->node == NULL))
3510 return(NULL);
3511 return(xmlNodeGetBase(NULL, reader->node));
3512}
3513
3514/**
3515 * xmlTextReaderConstBaseUri:
3516 * @reader: the xmlTextReaderPtr used
3517 *
3518 * The base URI of the node.
3519 *
3520 * Returns the base URI or NULL if not available, the string
3521 * will be deallocated with the reader
3522 */
3523const xmlChar *
3524xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3525 xmlChar *tmp;
3526 const xmlChar *ret;
3527
3528 if ((reader == NULL) || (reader->node == NULL))
3529 return(NULL);
3530 tmp = xmlNodeGetBase(NULL, reader->node);
3531 if (tmp == NULL)
3532 return(NULL);
3533 ret = CONSTSTR(tmp);
3534 xmlFree(tmp);
3535 return(ret);
3536}
3537
3538/**
3539 * xmlTextReaderDepth:
3540 * @reader: the xmlTextReaderPtr used
3541 *
3542 * The depth of the node in the tree.
3543 *
3544 * Returns the depth or -1 in case of error
3545 */
3546int
3547xmlTextReaderDepth(xmlTextReaderPtr reader) {
3548 if (reader == NULL)
3549 return(-1);
3550 if (reader->node == NULL)
3551 return(0);
3552
3553 if (reader->curnode != NULL) {
3554 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3555 (reader->curnode->type == XML_NAMESPACE_DECL))
3556 return(reader->depth + 1);
3557 return(reader->depth + 2);
3558 }
3559 return(reader->depth);
3560}
3561
3562/**
3563 * xmlTextReaderHasAttributes:
3564 * @reader: the xmlTextReaderPtr used
3565 *
3566 * Whether the node has attributes.
3567 *
3568 * Returns 1 if true, 0 if false, and -1 in case or error
3569 */
3570int
3571xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3572 xmlNodePtr node;
3573 if (reader == NULL)
3574 return(-1);
3575 if (reader->node == NULL)
3576 return(0);
3577 if (reader->curnode != NULL)
3578 node = reader->curnode;
3579 else
3580 node = reader->node;
3581
3582 if ((node->type == XML_ELEMENT_NODE) &&
3583 ((node->properties != NULL) || (node->nsDef != NULL)))
3584 return(1);
3585 /* TODO: handle the xmlDecl */
3586 return(0);
3587}
3588
3589/**
3590 * xmlTextReaderHasValue:
3591 * @reader: the xmlTextReaderPtr used
3592 *
3593 * Whether the node can have a text value.
3594 *
3595 * Returns 1 if true, 0 if false, and -1 in case or error
3596 */
3597int
3598xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3599 xmlNodePtr node;
3600 if (reader == NULL)
3601 return(-1);
3602 if (reader->node == NULL)
3603 return(0);
3604 if (reader->curnode != NULL)
3605 node = reader->curnode;
3606 else
3607 node = reader->node;
3608
3609 switch (node->type) {
3610 case XML_ATTRIBUTE_NODE:
3611 case XML_TEXT_NODE:
3612 case XML_CDATA_SECTION_NODE:
3613 case XML_PI_NODE:
3614 case XML_COMMENT_NODE:
3615 case XML_NAMESPACE_DECL:
3616 return(1);
3617 default:
3618 break;
3619 }
3620 return(0);
3621}
3622
3623/**
3624 * xmlTextReaderValue:
3625 * @reader: the xmlTextReaderPtr used
3626 *
3627 * Provides the text value of the node if present
3628 *
3629 * Returns the string or NULL if not available. The result must be deallocated
3630 * with xmlFree()
3631 */
3632xmlChar *
3633xmlTextReaderValue(xmlTextReaderPtr reader) {
3634 xmlNodePtr node;
3635 if (reader == NULL)
3636 return(NULL);
3637 if (reader->node == NULL)
3638 return(NULL);
3639 if (reader->curnode != NULL)
3640 node = reader->curnode;
3641 else
3642 node = reader->node;
3643
3644 switch (node->type) {
3645 case XML_NAMESPACE_DECL:
3646 return(xmlStrdup(((xmlNsPtr) node)->href));
3647 case XML_ATTRIBUTE_NODE:{
3648 xmlAttrPtr attr = (xmlAttrPtr) node;
3649
3650 if (attr->parent != NULL)
3651 return (xmlNodeListGetString
3652 (attr->parent->doc, attr->children, 1));
3653 else
3654 return (xmlNodeListGetString(NULL, attr->children, 1));
3655 break;
3656 }
3657 case XML_TEXT_NODE:
3658 case XML_CDATA_SECTION_NODE:
3659 case XML_PI_NODE:
3660 case XML_COMMENT_NODE:
3661 if (node->content != NULL)
3662 return (xmlStrdup(node->content));
3663 default:
3664 break;
3665 }
3666 return(NULL);
3667}
3668
3669/**
3670 * xmlTextReaderConstValue:
3671 * @reader: the xmlTextReaderPtr used
3672 *
3673 * Provides the text value of the node if present
3674 *
3675 * Returns the string or NULL if not available. The result will be
3676 * deallocated on the next Read() operation.
3677 */
3678const xmlChar *
3679xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3680 xmlNodePtr node;
3681 if (reader == NULL)
3682 return(NULL);
3683 if (reader->node == NULL)
3684 return(NULL);
3685 if (reader->curnode != NULL)
3686 node = reader->curnode;
3687 else
3688 node = reader->node;
3689
3690 switch (node->type) {
3691 case XML_NAMESPACE_DECL:
3692 return(((xmlNsPtr) node)->href);
3693 case XML_ATTRIBUTE_NODE:{
3694 xmlAttrPtr attr = (xmlAttrPtr) node;
3695 const xmlChar *ret;
3696
3697 if ((attr->children != NULL) &&
3698 (attr->children->type == XML_TEXT_NODE) &&
3699 (attr->children->next == NULL))
3700 return(attr->children->content);
3701 else {
3702 if (reader->buffer == NULL) {
3703 reader->buffer = xmlBufCreateSize(100);
3704 if (reader->buffer == NULL) {
3705 xmlGenericError(xmlGenericErrorContext,
3706 "xmlTextReaderSetup : malloc failed\n");
3707 return (NULL);
3708 }
3709 xmlBufSetAllocationScheme(reader->buffer,
3710 XML_BUFFER_ALLOC_BOUNDED);
3711 } else
3712 xmlBufEmpty(reader->buffer);
3713 xmlBufGetNodeContent(reader->buffer, node);
3714 ret = xmlBufContent(reader->buffer);
3715 if (ret == NULL) {
3716 /* error on the buffer best to reallocate */
3717 xmlBufFree(reader->buffer);
3718 reader->buffer = xmlBufCreateSize(100);
3719 xmlBufSetAllocationScheme(reader->buffer,
3720 XML_BUFFER_ALLOC_BOUNDED);
3721 ret = BAD_CAST "";
3722 }
3723 return(ret);
3724 }
3725 break;
3726 }
3727 case XML_TEXT_NODE:
3728 case XML_CDATA_SECTION_NODE:
3729 case XML_PI_NODE:
3730 case XML_COMMENT_NODE:
3731 return(node->content);
3732 default:
3733 break;
3734 }
3735 return(NULL);
3736}
3737
3738/**
3739 * xmlTextReaderIsDefault:
3740 * @reader: the xmlTextReaderPtr used
3741 *
3742 * Whether an Attribute node was generated from the default value
3743 * defined in the DTD or schema.
3744 *
3745 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3746 */
3747int
3748xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3749 if (reader == NULL)
3750 return(-1);
3751 return(0);
3752}
3753
3754/**
3755 * xmlTextReaderQuoteChar:
3756 * @reader: the xmlTextReaderPtr used
3757 *
3758 * The quotation mark character used to enclose the value of an attribute.
3759 *
3760 * Returns " or ' and -1 in case of error
3761 */
3762int
3763xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3764 if (reader == NULL)
3765 return(-1);
3766 /* TODO maybe lookup the attribute value for " first */
3767 return((int) '"');
3768}
3769
3770/**
3771 * xmlTextReaderXmlLang:
3772 * @reader: the xmlTextReaderPtr used
3773 *
3774 * The xml:lang scope within which the node resides.
3775 *
3776 * Returns the xml:lang value or NULL if none exists.,
3777 * if non NULL it need to be freed by the caller.
3778 */
3779xmlChar *
3780xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3781 if (reader == NULL)
3782 return(NULL);
3783 if (reader->node == NULL)
3784 return(NULL);
3785 return(xmlNodeGetLang(reader->node));
3786}
3787
3788/**
3789 * xmlTextReaderConstXmlLang:
3790 * @reader: the xmlTextReaderPtr used
3791 *
3792 * The xml:lang scope within which the node resides.
3793 *
3794 * Returns the xml:lang value or NULL if none exists.
3795 */
3796const xmlChar *
3797xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3798 xmlChar *tmp;
3799 const xmlChar *ret;
3800
3801 if (reader == NULL)
3802 return(NULL);
3803 if (reader->node == NULL)
3804 return(NULL);
3805 tmp = xmlNodeGetLang(reader->node);
3806 if (tmp == NULL)
3807 return(NULL);
3808 ret = CONSTSTR(tmp);
3809 xmlFree(tmp);
3810 return(ret);
3811}
3812
3813/**
3814 * xmlTextReaderConstString:
3815 * @reader: the xmlTextReaderPtr used
3816 * @str: the string to intern.
3817 *
3818 * Get an interned string from the reader, allows for example to
3819 * speedup string name comparisons
3820 *
3821 * Returns an interned copy of the string or NULL in case of error. The
3822 * string will be deallocated with the reader.
3823 */
3824const xmlChar *
3825xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3826 if (reader == NULL)
3827 return(NULL);
3828 return(CONSTSTR(str));
3829}
3830
3831/**
3832 * xmlTextReaderNormalization:
3833 * @reader: the xmlTextReaderPtr used
3834 *
3835 * The value indicating whether to normalize white space and attribute values.
3836 * Since attribute value and end of line normalizations are a MUST in the XML
3837 * specification only the value true is accepted. The broken behaviour of
3838 * accepting out of range character entities like &#0; is of course not
3839 * supported either.
3840 *
3841 * Returns 1 or -1 in case of error.
3842 */
3843int
3844xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3845 if (reader == NULL)
3846 return(-1);
3847 return(1);
3848}
3849
3850/************************************************************************
3851 * *
3852 * Extensions to the base APIs *
3853 * *
3854 ************************************************************************/
3855
3856/**
3857 * xmlTextReaderSetParserProp:
3858 * @reader: the xmlTextReaderPtr used
3859 * @prop: the xmlParserProperties to set
3860 * @value: usually 0 or 1 to (de)activate it
3861 *
3862 * Change the parser processing behaviour by changing some of its internal
3863 * properties. Note that some properties can only be changed before any
3864 * read has been done.
3865 *
3866 * Returns 0 if the call was successful, or -1 in case of error
3867 */
3868int
3869xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3870 xmlParserProperties p = (xmlParserProperties) prop;
3871 xmlParserCtxtPtr ctxt;
3872
3873 if ((reader == NULL) || (reader->ctxt == NULL))
3874 return(-1);
3875 ctxt = reader->ctxt;
3876
3877 switch (p) {
3878 case XML_PARSER_LOADDTD:
3879 if (value != 0) {
3880 if (ctxt->loadsubset == 0) {
3881 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3882 return(-1);
3883 ctxt->loadsubset = XML_DETECT_IDS;
3884 }
3885 } else {
3886 ctxt->loadsubset = 0;
3887 }
3888 return(0);
3889 case XML_PARSER_DEFAULTATTRS:
3890 if (value != 0) {
3891 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3892 } else {
3893 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3894 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3895 }
3896 return(0);
3897 case XML_PARSER_VALIDATE:
3898 if (value != 0) {
3899 ctxt->options |= XML_PARSE_DTDVALID;
3900 ctxt->validate = 1;
3901 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3902 } else {
3903 ctxt->options &= ~XML_PARSE_DTDVALID;
3904 ctxt->validate = 0;
3905 }
3906 return(0);
3907 case XML_PARSER_SUBST_ENTITIES:
3908 if (value != 0) {
3909 ctxt->options |= XML_PARSE_NOENT;
3910 ctxt->replaceEntities = 1;
3911 } else {
3912 ctxt->options &= ~XML_PARSE_NOENT;
3913 ctxt->replaceEntities = 0;
3914 }
3915 return(0);
3916 }
3917 return(-1);
3918}
3919
3920/**
3921 * xmlTextReaderGetParserProp:
3922 * @reader: the xmlTextReaderPtr used
3923 * @prop: the xmlParserProperties to get
3924 *
3925 * Read the parser internal property.
3926 *
3927 * Returns the value, usually 0 or 1, or -1 in case of error.
3928 */
3929int
3930xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3931 xmlParserProperties p = (xmlParserProperties) prop;
3932 xmlParserCtxtPtr ctxt;
3933
3934 if ((reader == NULL) || (reader->ctxt == NULL))
3935 return(-1);
3936 ctxt = reader->ctxt;
3937
3938 switch (p) {
3939 case XML_PARSER_LOADDTD:
3940 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3941 return(1);
3942 return(0);
3943 case XML_PARSER_DEFAULTATTRS:
3944 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3945 return(1);
3946 return(0);
3947 case XML_PARSER_VALIDATE:
3948 return(reader->validate);
3949 case XML_PARSER_SUBST_ENTITIES:
3950 return(ctxt->replaceEntities);
3951 }
3952 return(-1);
3953}
3954
3955
3956/**
3957 * xmlTextReaderGetParserLineNumber:
3958 * @reader: the user data (XML reader context)
3959 *
3960 * Provide the line number of the current parsing point.
3961 *
3962 * Returns an int or 0 if not available
3963 */
3964int
3965xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3966{
3967 if ((reader == NULL) || (reader->ctxt == NULL) ||
3968 (reader->ctxt->input == NULL)) {
3969 return (0);
3970 }
3971 return (reader->ctxt->input->line);
3972}
3973
3974/**
3975 * xmlTextReaderGetParserColumnNumber:
3976 * @reader: the user data (XML reader context)
3977 *
3978 * Provide the column number of the current parsing point.
3979 *
3980 * Returns an int or 0 if not available
3981 */
3982int
3983xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3984{
3985 if ((reader == NULL) || (reader->ctxt == NULL) ||
3986 (reader->ctxt->input == NULL)) {
3987 return (0);
3988 }
3989 return (reader->ctxt->input->col);
3990}
3991
3992/**
3993 * xmlTextReaderCurrentNode:
3994 * @reader: the xmlTextReaderPtr used
3995 *
3996 * Hacking interface allowing to get the xmlNodePtr corresponding to the
3997 * current node being accessed by the xmlTextReader. This is dangerous
3998 * because the underlying node may be destroyed on the next Reads.
3999 *
4000 * Returns the xmlNodePtr or NULL in case of error.
4001 */
4002xmlNodePtr
4003xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
4004 if (reader == NULL)
4005 return(NULL);
4006
4007 if (reader->curnode != NULL)
4008 return(reader->curnode);
4009 return(reader->node);
4010}
4011
4012/**
4013 * xmlTextReaderPreserve:
4014 * @reader: the xmlTextReaderPtr used
4015 *
4016 * This tells the XML Reader to preserve the current node.
4017 * The caller must also use xmlTextReaderCurrentDoc() to
4018 * keep an handle on the resulting document once parsing has finished
4019 *
4020 * Returns the xmlNodePtr or NULL in case of error.
4021 */
4022xmlNodePtr
4023xmlTextReaderPreserve(xmlTextReaderPtr reader) {
4024 xmlNodePtr cur, parent;
4025
4026 if (reader == NULL)
4027 return(NULL);
4028
4029 if (reader->curnode != NULL)
4030 cur = reader->curnode;
4031 else
4032 cur = reader->node;
4033 if (cur == NULL)
4034 return(NULL);
4035
4036 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
4037 cur->extra |= NODE_IS_PRESERVED;
4038 cur->extra |= NODE_IS_SPRESERVED;
4039 }
4040 reader->preserves++;
4041
4042 parent = cur->parent;;
4043 while (parent != NULL) {
4044 if (parent->type == XML_ELEMENT_NODE)
4045 parent->extra |= NODE_IS_PRESERVED;
4046 parent = parent->parent;
4047 }
4048 return(cur);
4049}
4050
4051#ifdef LIBXML_PATTERN_ENABLED
4052/**
4053 * xmlTextReaderPreservePattern:
4054 * @reader: the xmlTextReaderPtr used
4055 * @pattern: an XPath subset pattern
4056 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
4057 *
4058 * This tells the XML Reader to preserve all nodes matched by the
4059 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
4060 * keep an handle on the resulting document once parsing has finished
4061 *
4062 * Returns a non-negative number in case of success and -1 in case of error
4063 */
4064int
4065xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
4066 const xmlChar **namespaces)
4067{
4068 xmlPatternPtr comp;
4069
4070 if ((reader == NULL) || (pattern == NULL))
4071 return(-1);
4072
4073 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
4074 if (comp == NULL)
4075 return(-1);
4076
4077 if (reader->patternMax <= 0) {
4078 reader->patternMax = 4;
4079 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4080 sizeof(reader->patternTab[0]));
4081 if (reader->patternTab == NULL) {
4082 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4083 return (-1);
4084 }
4085 }
4086 if (reader->patternNr >= reader->patternMax) {
4087 xmlPatternPtr *tmp;
4088 reader->patternMax *= 2;
4089 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4090 reader->patternMax *
4091 sizeof(reader->patternTab[0]));
4092 if (tmp == NULL) {
4093 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4094 reader->patternMax /= 2;
4095 return (-1);
4096 }
4097 reader->patternTab = tmp;
4098 }
4099 reader->patternTab[reader->patternNr] = comp;
4100 return(reader->patternNr++);
4101}
4102#endif
4103
4104/**
4105 * xmlTextReaderCurrentDoc:
4106 * @reader: the xmlTextReaderPtr used
4107 *
4108 * Hacking interface allowing to get the xmlDocPtr corresponding to the
4109 * current document being accessed by the xmlTextReader.
4110 * NOTE: as a result of this call, the reader will not destroy the
4111 * associated XML document and calling xmlFreeDoc() on the result
4112 * is needed once the reader parsing has finished.
4113 *
4114 * Returns the xmlDocPtr or NULL in case of error.
4115 */
4116xmlDocPtr
4117xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4118 if (reader == NULL)
4119 return(NULL);
4120 if (reader->doc != NULL)
4121 return(reader->doc);
4122 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4123 return(NULL);
4124
4125 reader->preserve = 1;
4126 return(reader->ctxt->myDoc);
4127}
4128
4129#ifdef LIBXML_SCHEMAS_ENABLED
4130static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
4131
4132static void XMLCDECL
4133xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4134
4135static void XMLCDECL
4136xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4137
4138static void XMLCDECL
4139xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4140
4141static void XMLCDECL
4142xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4143
4144static void XMLCDECL
4145xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4146{
4147 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4148
4149 char *str;
4150
4151 va_list ap;
4152
4153 va_start(ap, msg);
4154 str = xmlTextReaderBuildMessage(msg, ap);
4155 if (!reader->errorFunc) {
4156 xmlTextReaderValidityError(ctx, "%s", str);
4157 } else {
4158 reader->errorFunc(reader->errorFuncArg, str,
4159 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4160 NULL /* locator */ );
4161 }
4162 if (str != NULL)
4163 xmlFree(str);
4164 va_end(ap);
4165}
4166
4167static void XMLCDECL
4168xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4169{
4170 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4171
4172 char *str;
4173
4174 va_list ap;
4175
4176 va_start(ap, msg);
4177 str = xmlTextReaderBuildMessage(msg, ap);
4178 if (!reader->errorFunc) {
4179 xmlTextReaderValidityWarning(ctx, "%s", str);
4180 } else {
4181 reader->errorFunc(reader->errorFuncArg, str,
4182 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4183 NULL /* locator */ );
4184 }
4185 if (str != NULL)
4186 xmlFree(str);
4187 va_end(ap);
4188}
4189
4190static void
4191 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4192
4193static void
4194xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4195{
4196 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4197
4198 if (reader->sErrorFunc) {
4199 reader->sErrorFunc(reader->errorFuncArg, error);
4200 } else {
4201 xmlTextReaderStructuredError(reader, error);
4202 }
4203}
4204/**
4205 * xmlTextReaderRelaxNGSetSchema:
4206 * @reader: the xmlTextReaderPtr used
4207 * @schema: a precompiled RelaxNG schema
4208 *
4209 * Use RelaxNG to validate the document as it is processed.
4210 * Activation is only possible before the first Read().
4211 * if @schema is NULL, then RelaxNG validation is deactivated.
4212 @ The @schema should not be freed until the reader is deallocated
4213 * or its use has been deactivated.
4214 *
4215 * Returns 0 in case the RelaxNG validation could be (de)activated and
4216 * -1 in case of error.
4217 */
4218int
4219xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4220 if (reader == NULL)
4221 return(-1);
4222 if (schema == NULL) {
4223 if (reader->rngSchemas != NULL) {
4224 xmlRelaxNGFree(reader->rngSchemas);
4225 reader->rngSchemas = NULL;
4226 }
4227 if (reader->rngValidCtxt != NULL) {
4228 if (! reader->rngPreserveCtxt)
4229 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4230 reader->rngValidCtxt = NULL;
4231 }
4232 reader->rngPreserveCtxt = 0;
4233 return(0);
4234 }
4235 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4236 return(-1);
4237 if (reader->rngSchemas != NULL) {
4238 xmlRelaxNGFree(reader->rngSchemas);
4239 reader->rngSchemas = NULL;
4240 }
4241 if (reader->rngValidCtxt != NULL) {
4242 if (! reader->rngPreserveCtxt)
4243 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4244 reader->rngValidCtxt = NULL;
4245 }
4246 reader->rngPreserveCtxt = 0;
4247 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4248 if (reader->rngValidCtxt == NULL)
4249 return(-1);
4250 if (reader->errorFunc != NULL) {
4251 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4252 xmlTextReaderValidityErrorRelay,
4253 xmlTextReaderValidityWarningRelay,
4254 reader);
4255 }
4256 if (reader->sErrorFunc != NULL) {
4257 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4258 xmlTextReaderValidityStructuredRelay,
4259 reader);
4260 }
4261 reader->rngValidErrors = 0;
4262 reader->rngFullNode = NULL;
4263 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4264 return(0);
4265}
4266
4267/**
4268 * xmlTextReaderLocator:
4269 * @ctx: the xmlTextReaderPtr used
4270 * @file: returned file information
4271 * @line: returned line information
4272 *
4273 * Internal locator function for the readers
4274 *
4275 * Returns 0 in case the Schema validation could be (de)activated and
4276 * -1 in case of error.
4277 */
4278static int
4279xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4280 xmlTextReaderPtr reader;
4281
4282 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4283 return(-1);
4284
4285 if (file != NULL)
4286 *file = NULL;
4287 if (line != NULL)
4288 *line = 0;
4289
4290 reader = (xmlTextReaderPtr) ctx;
4291 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4292 if (file != NULL)
4293 *file = reader->ctxt->input->filename;
4294 if (line != NULL)
4295 *line = reader->ctxt->input->line;
4296 return(0);
4297 }
4298 if (reader->node != NULL) {
4299 long res;
4300 int ret = 0;
4301
4302 if (line != NULL) {
4303 res = xmlGetLineNo(reader->node);
4304 if (res > 0)
4305 *line = (unsigned long) res;
4306 else
4307 ret = -1;
4308 }
4309 if (file != NULL) {
4310 xmlDocPtr doc = reader->node->doc;
4311 if ((doc != NULL) && (doc->URL != NULL))
4312 *file = (const char *) doc->URL;
4313 else
4314 ret = -1;
4315 }
4316 return(ret);
4317 }
4318 return(-1);
4319}
4320
4321/**
4322 * xmlTextReaderSetSchema:
4323 * @reader: the xmlTextReaderPtr used
4324 * @schema: a precompiled Schema schema
4325 *
4326 * Use XSD Schema to validate the document as it is processed.
4327 * Activation is only possible before the first Read().
4328 * if @schema is NULL, then Schema validation is deactivated.
4329 * The @schema should not be freed until the reader is deallocated
4330 * or its use has been deactivated.
4331 *
4332 * Returns 0 in case the Schema validation could be (de)activated and
4333 * -1 in case of error.
4334 */
4335int
4336xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4337 if (reader == NULL)
4338 return(-1);
4339 if (schema == NULL) {
4340 if (reader->xsdPlug != NULL) {
4341 xmlSchemaSAXUnplug(reader->xsdPlug);
4342 reader->xsdPlug = NULL;
4343 }
4344 if (reader->xsdValidCtxt != NULL) {
4345 if (! reader->xsdPreserveCtxt)
4346 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4347 reader->xsdValidCtxt = NULL;
4348 }
4349 reader->xsdPreserveCtxt = 0;
4350 if (reader->xsdSchemas != NULL) {
4351 xmlSchemaFree(reader->xsdSchemas);
4352 reader->xsdSchemas = NULL;
4353 }
4354 return(0);
4355 }
4356 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4357 return(-1);
4358 if (reader->xsdPlug != NULL) {
4359 xmlSchemaSAXUnplug(reader->xsdPlug);
4360 reader->xsdPlug = NULL;
4361 }
4362 if (reader->xsdValidCtxt != NULL) {
4363 if (! reader->xsdPreserveCtxt)
4364 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4365 reader->xsdValidCtxt = NULL;
4366 }
4367 reader->xsdPreserveCtxt = 0;
4368 if (reader->xsdSchemas != NULL) {
4369 xmlSchemaFree(reader->xsdSchemas);
4370 reader->xsdSchemas = NULL;
4371 }
4372 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4373 if (reader->xsdValidCtxt == NULL) {
4374 xmlSchemaFree(reader->xsdSchemas);
4375 reader->xsdSchemas = NULL;
4376 return(-1);
4377 }
4378 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4379 &(reader->ctxt->sax),
4380 &(reader->ctxt->userData));
4381 if (reader->xsdPlug == NULL) {
4382 xmlSchemaFree(reader->xsdSchemas);
4383 reader->xsdSchemas = NULL;
4384 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4385 reader->xsdValidCtxt = NULL;
4386 return(-1);
4387 }
4388 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4389 xmlTextReaderLocator,
4390 (void *) reader);
4391
4392 if (reader->errorFunc != NULL) {
4393 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4394 xmlTextReaderValidityErrorRelay,
4395 xmlTextReaderValidityWarningRelay,
4396 reader);
4397 }
4398 if (reader->sErrorFunc != NULL) {
4399 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4400 xmlTextReaderValidityStructuredRelay,
4401 reader);
4402 }
4403 reader->xsdValidErrors = 0;
4404 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4405 return(0);
4406}
4407
4408/**
4409 * xmlTextReaderRelaxNGValidateInternal:
4410 * @reader: the xmlTextReaderPtr used
4411 * @rng: the path to a RelaxNG schema or NULL
4412 * @ctxt: the RelaxNG schema validation context or NULL
4413 * @options: options (not yet used)
4414 *
4415 * Use RelaxNG to validate the document as it is processed.
4416 * Activation is only possible before the first Read().
4417 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4418 *
4419 * Returns 0 in case the RelaxNG validation could be (de)activated and
4420 * -1 in case of error.
4421 */
4422static int
4423xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4424 const char *rng,
4425 xmlRelaxNGValidCtxtPtr ctxt,
4426 int options ATTRIBUTE_UNUSED)
4427{
4428 if (reader == NULL)
4429 return(-1);
4430
4431 if ((rng != NULL) && (ctxt != NULL))
4432 return (-1);
4433
4434 if (((rng != NULL) || (ctxt != NULL)) &&
4435 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4436 (reader->ctxt == NULL)))
4437 return(-1);
4438
4439 /* Cleanup previous validation stuff. */
4440 if (reader->rngValidCtxt != NULL) {
4441 if ( !reader->rngPreserveCtxt)
4442 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4443 reader->rngValidCtxt = NULL;
4444 }
4445 reader->rngPreserveCtxt = 0;
4446 if (reader->rngSchemas != NULL) {
4447 xmlRelaxNGFree(reader->rngSchemas);
4448 reader->rngSchemas = NULL;
4449 }
4450
4451 if ((rng == NULL) && (ctxt == NULL)) {
4452 /* We just want to deactivate the validation, so get out. */
4453 return(0);
4454 }
4455
4456
4457 if (rng != NULL) {
4458 xmlRelaxNGParserCtxtPtr pctxt;
4459 /* Parse the schema and create validation environment. */
4460
4461 pctxt = xmlRelaxNGNewParserCtxt(rng);
4462 if (reader->errorFunc != NULL) {
4463 xmlRelaxNGSetParserErrors(pctxt,
4464 xmlTextReaderValidityErrorRelay,
4465 xmlTextReaderValidityWarningRelay,
4466 reader);
4467 }
4468 if (reader->sErrorFunc != NULL) {
4469 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4470 xmlTextReaderValidityStructuredRelay,
4471 reader);
4472 }
4473 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4474 xmlRelaxNGFreeParserCtxt(pctxt);
4475 if (reader->rngSchemas == NULL)
4476 return(-1);
4477 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4478 if (reader->rngValidCtxt == NULL) {
4479 xmlRelaxNGFree(reader->rngSchemas);
4480 reader->rngSchemas = NULL;
4481 return(-1);
4482 }
4483 } else {
4484 /* Use the given validation context. */
4485 reader->rngValidCtxt = ctxt;
4486 reader->rngPreserveCtxt = 1;
4487 }
4488 /*
4489 * Redirect the validation context's error channels to use
4490 * the reader channels.
4491 * TODO: In case the user provides the validation context we
4492 * could make this redirection optional.
4493 */
4494 if (reader->errorFunc != NULL) {
4495 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4496 xmlTextReaderValidityErrorRelay,
4497 xmlTextReaderValidityWarningRelay,
4498 reader);
4499 }
4500 if (reader->sErrorFunc != NULL) {
4501 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4502 xmlTextReaderValidityStructuredRelay,
4503 reader);
4504 }
4505 reader->rngValidErrors = 0;
4506 reader->rngFullNode = NULL;
4507 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4508 return(0);
4509}
4510
4511/**
4512 * xmlTextReaderSchemaValidateInternal:
4513 * @reader: the xmlTextReaderPtr used
4514 * @xsd: the path to a W3C XSD schema or NULL
4515 * @ctxt: the XML Schema validation context or NULL
4516 * @options: options (not used yet)
4517 *
4518 * Validate the document as it is processed using XML Schema.
4519 * Activation is only possible before the first Read().
4520 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4521 *
4522 * Returns 0 in case the schemas validation could be (de)activated and
4523 * -1 in case of error.
4524 */
4525static int
4526xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4527 const char *xsd,
4528 xmlSchemaValidCtxtPtr ctxt,
4529 int options ATTRIBUTE_UNUSED)
4530{
4531 if (reader == NULL)
4532 return(-1);
4533
4534 if ((xsd != NULL) && (ctxt != NULL))
4535 return(-1);
4536
4537 if (((xsd != NULL) || (ctxt != NULL)) &&
4538 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4539 (reader->ctxt == NULL)))
4540 return(-1);
4541
4542 /* Cleanup previous validation stuff. */
4543 if (reader->xsdPlug != NULL) {
4544 xmlSchemaSAXUnplug(reader->xsdPlug);
4545 reader->xsdPlug = NULL;
4546 }
4547 if (reader->xsdValidCtxt != NULL) {
4548 if (! reader->xsdPreserveCtxt)
4549 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4550 reader->xsdValidCtxt = NULL;
4551 }
4552 reader->xsdPreserveCtxt = 0;
4553 if (reader->xsdSchemas != NULL) {
4554 xmlSchemaFree(reader->xsdSchemas);
4555 reader->xsdSchemas = NULL;
4556 }
4557
4558 if ((xsd == NULL) && (ctxt == NULL)) {
4559 /* We just want to deactivate the validation, so get out. */
4560 return(0);
4561 }
4562
4563 if (xsd != NULL) {
4564 xmlSchemaParserCtxtPtr pctxt;
4565 /* Parse the schema and create validation environment. */
4566 pctxt = xmlSchemaNewParserCtxt(xsd);
4567 if (reader->errorFunc != NULL) {
4568 xmlSchemaSetParserErrors(pctxt,
4569 xmlTextReaderValidityErrorRelay,
4570 xmlTextReaderValidityWarningRelay,
4571 reader);
4572 }
4573 reader->xsdSchemas = xmlSchemaParse(pctxt);
4574 xmlSchemaFreeParserCtxt(pctxt);
4575 if (reader->xsdSchemas == NULL)
4576 return(-1);
4577 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4578 if (reader->xsdValidCtxt == NULL) {
4579 xmlSchemaFree(reader->xsdSchemas);
4580 reader->xsdSchemas = NULL;
4581 return(-1);
4582 }
4583 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4584 &(reader->ctxt->sax),
4585 &(reader->ctxt->userData));
4586 if (reader->xsdPlug == NULL) {
4587 xmlSchemaFree(reader->xsdSchemas);
4588 reader->xsdSchemas = NULL;
4589 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4590 reader->xsdValidCtxt = NULL;
4591 return(-1);
4592 }
4593 } else {
4594 /* Use the given validation context. */
4595 reader->xsdValidCtxt = ctxt;
4596 reader->xsdPreserveCtxt = 1;
4597 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4598 &(reader->ctxt->sax),
4599 &(reader->ctxt->userData));
4600 if (reader->xsdPlug == NULL) {
4601 reader->xsdValidCtxt = NULL;
4602 reader->xsdPreserveCtxt = 0;
4603 return(-1);
4604 }
4605 }
4606 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4607 xmlTextReaderLocator,
4608 (void *) reader);
4609 /*
4610 * Redirect the validation context's error channels to use
4611 * the reader channels.
4612 * TODO: In case the user provides the validation context we
4613 * could make this redirection optional.
4614 */
4615 if (reader->errorFunc != NULL) {
4616 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4617 xmlTextReaderValidityErrorRelay,
4618 xmlTextReaderValidityWarningRelay,
4619 reader);
4620 }
4621 if (reader->sErrorFunc != NULL) {
4622 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4623 xmlTextReaderValidityStructuredRelay,
4624 reader);
4625 }
4626 reader->xsdValidErrors = 0;
4627 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4628 return(0);
4629}
4630
4631/**
4632 * xmlTextReaderSchemaValidateCtxt:
4633 * @reader: the xmlTextReaderPtr used
4634 * @ctxt: the XML Schema validation context or NULL
4635 * @options: options (not used yet)
4636 *
4637 * Use W3C XSD schema context to validate the document as it is processed.
4638 * Activation is only possible before the first Read().
4639 * If @ctxt is NULL, then XML Schema validation is deactivated.
4640 *
4641 * Returns 0 in case the schemas validation could be (de)activated and
4642 * -1 in case of error.
4643 */
4644int
4645xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4646 xmlSchemaValidCtxtPtr ctxt,
4647 int options)
4648{
4649 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4650}
4651
4652/**
4653 * xmlTextReaderSchemaValidate:
4654 * @reader: the xmlTextReaderPtr used
4655 * @xsd: the path to a W3C XSD schema or NULL
4656 *
4657 * Use W3C XSD schema to validate the document as it is processed.
4658 * Activation is only possible before the first Read().
4659 * If @xsd is NULL, then XML Schema validation is deactivated.
4660 *
4661 * Returns 0 in case the schemas validation could be (de)activated and
4662 * -1 in case of error.
4663 */
4664int
4665xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4666{
4667 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4668}
4669
4670/**
4671 * xmlTextReaderRelaxNGValidateCtxt:
4672 * @reader: the xmlTextReaderPtr used
4673 * @ctxt: the RelaxNG schema validation context or NULL
4674 * @options: options (not used yet)
4675 *
4676 * Use RelaxNG schema context to validate the document as it is processed.
4677 * Activation is only possible before the first Read().
4678 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4679 *
4680 * Returns 0 in case the schemas validation could be (de)activated and
4681 * -1 in case of error.
4682 */
4683int
4684xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4685 xmlRelaxNGValidCtxtPtr ctxt,
4686 int options)
4687{
4688 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4689}
4690
4691/**
4692 * xmlTextReaderRelaxNGValidate:
4693 * @reader: the xmlTextReaderPtr used
4694 * @rng: the path to a RelaxNG schema or NULL
4695 *
4696 * Use RelaxNG schema to validate the document as it is processed.
4697 * Activation is only possible before the first Read().
4698 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4699 *
4700 * Returns 0 in case the schemas validation could be (de)activated and
4701 * -1 in case of error.
4702 */
4703int
4704xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4705{
4706 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4707}
4708
4709#endif
4710
4711/**
4712 * xmlTextReaderIsNamespaceDecl:
4713 * @reader: the xmlTextReaderPtr used
4714 *
4715 * Determine whether the current node is a namespace declaration
4716 * rather than a regular attribute.
4717 *
4718 * Returns 1 if the current node is a namespace declaration, 0 if it
4719 * is a regular attribute or other type of node, or -1 in case of
4720 * error.
4721 */
4722int
4723xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4724 xmlNodePtr node;
4725 if (reader == NULL)
4726 return(-1);
4727 if (reader->node == NULL)
4728 return(-1);
4729 if (reader->curnode != NULL)
4730 node = reader->curnode;
4731 else
4732 node = reader->node;
4733
4734 if (XML_NAMESPACE_DECL == node->type)
4735 return(1);
4736 else
4737 return(0);
4738}
4739
4740/**
4741 * xmlTextReaderConstXmlVersion:
4742 * @reader: the xmlTextReaderPtr used
4743 *
4744 * Determine the XML version of the document being read.
4745 *
4746 * Returns a string containing the XML version of the document or NULL
4747 * in case of error. The string is deallocated with the reader.
4748 */
4749const xmlChar *
4750xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4751 xmlDocPtr doc = NULL;
4752 if (reader == NULL)
4753 return(NULL);
4754 if (reader->doc != NULL)
4755 doc = reader->doc;
4756 else if (reader->ctxt != NULL)
4757 doc = reader->ctxt->myDoc;
4758 if (doc == NULL)
4759 return(NULL);
4760
4761 if (doc->version == NULL)
4762 return(NULL);
4763 else
4764 return(CONSTSTR(doc->version));
4765}
4766
4767/**
4768 * xmlTextReaderStandalone:
4769 * @reader: the xmlTextReaderPtr used
4770 *
4771 * Determine the standalone status of the document being read.
4772 *
4773 * Returns 1 if the document was declared to be standalone, 0 if it
4774 * was declared to be not standalone, or -1 if the document did not
4775 * specify its standalone status or in case of error.
4776 */
4777int
4778xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4779 xmlDocPtr doc = NULL;
4780 if (reader == NULL)
4781 return(-1);
4782 if (reader->doc != NULL)
4783 doc = reader->doc;
4784 else if (reader->ctxt != NULL)
4785 doc = reader->ctxt->myDoc;
4786 if (doc == NULL)
4787 return(-1);
4788
4789 return(doc->standalone);
4790}
4791
4792/************************************************************************
4793 * *
4794 * Error Handling Extensions *
4795 * *
4796 ************************************************************************/
4797
4798/* helper to build a xmlMalloc'ed string from a format and va_list */
4799static char *
4800xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4801 int size = 0;
4802 int chars;
4803 char *larger;
4804 char *str = NULL;
4805 va_list aq;
4806
4807 while (1) {
4808 VA_COPY(aq, ap);
4809 chars = vsnprintf(str, size, msg, aq);
4810 va_end(aq);
4811 if (chars < 0) {
4812 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4813 if (str)
4814 xmlFree(str);
4815 return NULL;
4816 }
4817 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4818 break;
4819 if (chars < MAX_ERR_MSG_SIZE)
4820 size = chars + 1;
4821 else
4822 size = MAX_ERR_MSG_SIZE;
4823 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4824 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4825 if (str)
4826 xmlFree(str);
4827 return NULL;
4828 }
4829 str = larger;
4830 }
4831
4832 return str;
4833}
4834
4835/**
4836 * xmlTextReaderLocatorLineNumber:
4837 * @locator: the xmlTextReaderLocatorPtr used
4838 *
4839 * Obtain the line number for the given locator.
4840 *
4841 * Returns the line number or -1 in case of error.
4842 */
4843int
4844xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4845 /* we know that locator is a xmlParserCtxtPtr */
4846 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4847 int ret = -1;
4848
4849 if (locator == NULL)
4850 return(-1);
4851 if (ctx->node != NULL) {
4852 ret = xmlGetLineNo(ctx->node);
4853 }
4854 else {
4855 /* inspired from error.c */
4856 xmlParserInputPtr input;
4857 input = ctx->input;
4858 if ((input->filename == NULL) && (ctx->inputNr > 1))
4859 input = ctx->inputTab[ctx->inputNr - 2];
4860 if (input != NULL) {
4861 ret = input->line;
4862 }
4863 else {
4864 ret = -1;
4865 }
4866 }
4867
4868 return ret;
4869}
4870
4871/**
4872 * xmlTextReaderLocatorBaseURI:
4873 * @locator: the xmlTextReaderLocatorPtr used
4874 *
4875 * Obtain the base URI for the given locator.
4876 *
4877 * Returns the base URI or NULL in case of error,
4878 * if non NULL it need to be freed by the caller.
4879 */
4880xmlChar *
4881xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4882 /* we know that locator is a xmlParserCtxtPtr */
4883 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4884 xmlChar *ret = NULL;
4885
4886 if (locator == NULL)
4887 return(NULL);
4888 if (ctx->node != NULL) {
4889 ret = xmlNodeGetBase(NULL,ctx->node);
4890 }
4891 else {
4892 /* inspired from error.c */
4893 xmlParserInputPtr input;
4894 input = ctx->input;
4895 if ((input->filename == NULL) && (ctx->inputNr > 1))
4896 input = ctx->inputTab[ctx->inputNr - 2];
4897 if (input != NULL) {
4898 ret = xmlStrdup(BAD_CAST input->filename);
4899 }
4900 else {
4901 ret = NULL;
4902 }
4903 }
4904
4905 return ret;
4906}
4907
4908static void
4909xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4910 char *str)
4911{
4912 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4913
4914 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4915
4916 if (str != NULL) {
4917 if (reader->errorFunc)
4918 reader->errorFunc(reader->errorFuncArg, str, severity,
4919 (xmlTextReaderLocatorPtr) ctx);
4920 xmlFree(str);
4921 }
4922}
4923
4924static void
4925xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4926{
4927 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4928
4929 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4930
4931 if (error && reader->sErrorFunc) {
4932 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4933 }
4934}
4935
4936static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4937xmlTextReaderError(void *ctxt, const char *msg, ...)
4938{
4939 va_list ap;
4940
4941 va_start(ap, msg);
4942 xmlTextReaderGenericError(ctxt,
4943 XML_PARSER_SEVERITY_ERROR,
4944 xmlTextReaderBuildMessage(msg, ap));
4945 va_end(ap);
4946
4947}
4948
4949static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4950xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4951{
4952 va_list ap;
4953
4954 va_start(ap, msg);
4955 xmlTextReaderGenericError(ctxt,
4956 XML_PARSER_SEVERITY_WARNING,
4957 xmlTextReaderBuildMessage(msg, ap));
4958 va_end(ap);
4959}
4960
4961static void XMLCDECL
4962xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4963{
4964 va_list ap;
4965
4966 int len = xmlStrlen((const xmlChar *) msg);
4967
4968 if ((len > 1) && (msg[len - 2] != ':')) {
4969 /*
4970 * some callbacks only report locator information:
4971 * skip them (mimicking behaviour in error.c)
4972 */
4973 va_start(ap, msg);
4974 xmlTextReaderGenericError(ctxt,
4975 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4976 xmlTextReaderBuildMessage(msg, ap));
4977 va_end(ap);
4978 }
4979}
4980
4981static void XMLCDECL
4982xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4983{
4984 va_list ap;
4985
4986 int len = xmlStrlen((const xmlChar *) msg);
4987
4988 if ((len != 0) && (msg[len - 1] != ':')) {
4989 /*
4990 * some callbacks only report locator information:
4991 * skip them (mimicking behaviour in error.c)
4992 */
4993 va_start(ap, msg);
4994 xmlTextReaderGenericError(ctxt,
4995 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4996 xmlTextReaderBuildMessage(msg, ap));
4997 va_end(ap);
4998 }
4999}
5000
5001/**
5002 * xmlTextReaderSetErrorHandler:
5003 * @reader: the xmlTextReaderPtr used
5004 * @f: the callback function to call on error and warnings
5005 * @arg: a user argument to pass to the callback function
5006 *
5007 * Register a callback function that will be called on error and warnings.
5008 *
5009 * If @f is NULL, the default error and warning handlers are restored.
5010 */
5011void
5012xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
5013 xmlTextReaderErrorFunc f, void *arg)
5014{
5015 if (f != NULL) {
5016 reader->ctxt->sax->error = xmlTextReaderError;
5017 reader->ctxt->sax->serror = NULL;
5018 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5019 reader->ctxt->sax->warning = xmlTextReaderWarning;
5020 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5021 reader->errorFunc = f;
5022 reader->sErrorFunc = NULL;
5023 reader->errorFuncArg = arg;
5024#ifdef LIBXML_SCHEMAS_ENABLED
5025 if (reader->rngValidCtxt) {
5026 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
5027 xmlTextReaderValidityErrorRelay,
5028 xmlTextReaderValidityWarningRelay,
5029 reader);
5030 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5031 reader);
5032 }
5033 if (reader->xsdValidCtxt) {
5034 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
5035 xmlTextReaderValidityErrorRelay,
5036 xmlTextReaderValidityWarningRelay,
5037 reader);
5038 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5039 reader);
5040 }
5041#endif
5042 } else {
5043 /* restore defaults */
5044 reader->ctxt->sax->error = xmlParserError;
5045 reader->ctxt->vctxt.error = xmlParserValidityError;
5046 reader->ctxt->sax->warning = xmlParserWarning;
5047 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5048 reader->errorFunc = NULL;
5049 reader->sErrorFunc = NULL;
5050 reader->errorFuncArg = NULL;
5051#ifdef LIBXML_SCHEMAS_ENABLED
5052 if (reader->rngValidCtxt) {
5053 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5054 reader);
5055 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5056 reader);
5057 }
5058 if (reader->xsdValidCtxt) {
5059 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5060 reader);
5061 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5062 reader);
5063 }
5064#endif
5065 }
5066}
5067
5068/**
5069* xmlTextReaderSetStructuredErrorHandler:
5070 * @reader: the xmlTextReaderPtr used
5071 * @f: the callback function to call on error and warnings
5072 * @arg: a user argument to pass to the callback function
5073 *
5074 * Register a callback function that will be called on error and warnings.
5075 *
5076 * If @f is NULL, the default error and warning handlers are restored.
5077 */
5078void
5079xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5080 xmlStructuredErrorFunc f, void *arg)
5081{
5082 if (f != NULL) {
5083 reader->ctxt->sax->error = NULL;
5084 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5085 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5086 reader->ctxt->sax->warning = xmlTextReaderWarning;
5087 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5088 reader->sErrorFunc = f;
5089 reader->errorFunc = NULL;
5090 reader->errorFuncArg = arg;
5091#ifdef LIBXML_SCHEMAS_ENABLED
5092 if (reader->rngValidCtxt) {
5093 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5094 reader);
5095 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5096 xmlTextReaderValidityStructuredRelay,
5097 reader);
5098 }
5099 if (reader->xsdValidCtxt) {
5100 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5101 reader);
5102 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5103 xmlTextReaderValidityStructuredRelay,
5104 reader);
5105 }
5106#endif
5107 } else {
5108 /* restore defaults */
5109 reader->ctxt->sax->error = xmlParserError;
5110 reader->ctxt->sax->serror = NULL;
5111 reader->ctxt->vctxt.error = xmlParserValidityError;
5112 reader->ctxt->sax->warning = xmlParserWarning;
5113 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5114 reader->errorFunc = NULL;
5115 reader->sErrorFunc = NULL;
5116 reader->errorFuncArg = NULL;
5117#ifdef LIBXML_SCHEMAS_ENABLED
5118 if (reader->rngValidCtxt) {
5119 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5120 reader);
5121 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5122 reader);
5123 }
5124 if (reader->xsdValidCtxt) {
5125 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5126 reader);
5127 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5128 reader);
5129 }
5130#endif
5131 }
5132}
5133
5134/**
5135 * xmlTextReaderIsValid:
5136 * @reader: the xmlTextReaderPtr used
5137 *
5138 * Retrieve the validity status from the parser context
5139 *
5140 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5141 */
5142int
5143xmlTextReaderIsValid(xmlTextReaderPtr reader)
5144{
5145 if (reader == NULL)
5146 return (-1);
5147#ifdef LIBXML_SCHEMAS_ENABLED
5148 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5149 return (reader->rngValidErrors == 0);
5150 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5151 return (reader->xsdValidErrors == 0);
5152#endif
5153 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5154 return (reader->ctxt->valid);
5155 return (0);
5156}
5157
5158/**
5159 * xmlTextReaderGetErrorHandler:
5160 * @reader: the xmlTextReaderPtr used
5161 * @f: the callback function or NULL is no callback has been registered
5162 * @arg: a user argument
5163 *
5164 * Retrieve the error callback function and user argument.
5165 */
5166void
5167xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5168 xmlTextReaderErrorFunc * f, void **arg)
5169{
5170 if (f != NULL)
5171 *f = reader->errorFunc;
5172 if (arg != NULL)
5173 *arg = reader->errorFuncArg;
5174}
5175/************************************************************************
5176 * *
5177 * New set (2.6.0) of simpler and more flexible APIs *
5178 * *
5179 ************************************************************************/
5180
5181/**
5182 * xmlTextReaderSetup:
5183 * @reader: an XML reader
5184 * @input: xmlParserInputBufferPtr used to feed the reader, will
5185 * be destroyed with it.
5186 * @URL: the base URL to use for the document
5187 * @encoding: the document encoding, or NULL
5188 * @options: a combination of xmlParserOption
5189 *
5190 * Setup an XML reader with new options
5191 *
5192 * Returns 0 in case of success and -1 in case of error.
5193 */
5194int
5195xmlTextReaderSetup(xmlTextReaderPtr reader,
5196 xmlParserInputBufferPtr input, const char *URL,
5197 const char *encoding, int options)
5198{
5199 if (reader == NULL) {
5200 if (input != NULL)
5201 xmlFreeParserInputBuffer(input);
5202 return (-1);
5203 }
5204
5205 /*
5206 * we force the generation of compact text nodes on the reader
5207 * since usr applications should never modify the tree
5208 */
5209 options |= XML_PARSE_COMPACT;
5210
5211 reader->doc = NULL;
5212 reader->entNr = 0;
5213 reader->parserFlags = options;
5214 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5215 if ((input != NULL) && (reader->input != NULL) &&
5216 (reader->allocs & XML_TEXTREADER_INPUT)) {
5217 xmlFreeParserInputBuffer(reader->input);
5218 reader->input = NULL;
5219 reader->allocs -= XML_TEXTREADER_INPUT;
5220 }
5221 if (input != NULL) {
5222 reader->input = input;
5223 reader->allocs |= XML_TEXTREADER_INPUT;
5224 }
5225 if (reader->buffer == NULL)
5226 reader->buffer = xmlBufCreateSize(100);
5227 if (reader->buffer == NULL) {
5228 xmlGenericError(xmlGenericErrorContext,
5229 "xmlTextReaderSetup : malloc failed\n");
5230 return (-1);
5231 }
5232 /* no operation on a reader should require a huge buffer */
5233 xmlBufSetAllocationScheme(reader->buffer,
5234 XML_BUFFER_ALLOC_BOUNDED);
5235 if (reader->sax == NULL)
5236 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5237 if (reader->sax == NULL) {
5238 xmlGenericError(xmlGenericErrorContext,
5239 "xmlTextReaderSetup : malloc failed\n");
5240 return (-1);
5241 }
5242 xmlSAXVersion(reader->sax, 2);
5243 reader->startElement = reader->sax->startElement;
5244 reader->sax->startElement = xmlTextReaderStartElement;
5245 reader->endElement = reader->sax->endElement;
5246 reader->sax->endElement = xmlTextReaderEndElement;
5247#ifdef LIBXML_SAX1_ENABLED
5248 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5249#endif /* LIBXML_SAX1_ENABLED */
5250 reader->startElementNs = reader->sax->startElementNs;
5251 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5252 reader->endElementNs = reader->sax->endElementNs;
5253 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5254#ifdef LIBXML_SAX1_ENABLED
5255 } else {
5256 reader->startElementNs = NULL;
5257 reader->endElementNs = NULL;
5258 }
5259#endif /* LIBXML_SAX1_ENABLED */
5260 reader->characters = reader->sax->characters;
5261 reader->sax->characters = xmlTextReaderCharacters;
5262 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5263 reader->cdataBlock = reader->sax->cdataBlock;
5264 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5265
5266 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5267 reader->node = NULL;
5268 reader->curnode = NULL;
5269 if (input != NULL) {
5270 if (xmlBufUse(reader->input->buffer) < 4) {
5271 xmlParserInputBufferRead(input, 4);
5272 }
5273 if (reader->ctxt == NULL) {
5274 if (xmlBufUse(reader->input->buffer) >= 4) {
5275 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5276 (const char *) xmlBufContent(reader->input->buffer),
5277 4, URL);
5278 reader->base = 0;
5279 reader->cur = 4;
5280 } else {
5281 reader->ctxt =
5282 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5283 reader->base = 0;
5284 reader->cur = 0;
5285 }
5286 } else {
5287 xmlParserInputPtr inputStream;
5288 xmlParserInputBufferPtr buf;
5289 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5290
5291 xmlCtxtReset(reader->ctxt);
5292 buf = xmlAllocParserInputBuffer(enc);
5293 if (buf == NULL) return(-1);
5294 inputStream = xmlNewInputStream(reader->ctxt);
5295 if (inputStream == NULL) {
5296 xmlFreeParserInputBuffer(buf);
5297 return(-1);
5298 }
5299
5300 if (URL == NULL)
5301 inputStream->filename = NULL;
5302 else
5303 inputStream->filename = (char *)
5304 xmlCanonicPath((const xmlChar *) URL);
5305 inputStream->buf = buf;
5306 xmlBufResetInput(buf->buffer, inputStream);
5307
5308 inputPush(reader->ctxt, inputStream);
5309 reader->cur = 0;
5310 }
5311 if (reader->ctxt == NULL) {
5312 xmlGenericError(xmlGenericErrorContext,
5313 "xmlTextReaderSetup : malloc failed\n");
5314 return (-1);
5315 }
5316 }
5317 if (reader->dict != NULL) {
5318 if (reader->ctxt->dict != NULL) {
5319 if (reader->dict != reader->ctxt->dict) {
5320 xmlDictFree(reader->dict);
5321 reader->dict = reader->ctxt->dict;
5322 }
5323 } else {
5324 reader->ctxt->dict = reader->dict;
5325 }
5326 } else {
5327 if (reader->ctxt->dict == NULL)
5328 reader->ctxt->dict = xmlDictCreate();
5329 reader->dict = reader->ctxt->dict;
5330 }
5331 reader->ctxt->_private = reader;
5332 reader->ctxt->linenumbers = 1;
5333 reader->ctxt->dictNames = 1;
5334 /*
5335 * use the parser dictionary to allocate all elements and attributes names
5336 */
5337 reader->ctxt->docdict = 1;
5338 reader->ctxt->parseMode = XML_PARSE_READER;
5339
5340#ifdef LIBXML_XINCLUDE_ENABLED
5341 if (reader->xincctxt != NULL) {
5342 xmlXIncludeFreeContext(reader->xincctxt);
5343 reader->xincctxt = NULL;
5344 }
5345 if (options & XML_PARSE_XINCLUDE) {
5346 reader->xinclude = 1;
5347 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5348 options -= XML_PARSE_XINCLUDE;
5349 } else
5350 reader->xinclude = 0;
5351 reader->in_xinclude = 0;
5352#endif
5353#ifdef LIBXML_PATTERN_ENABLED
5354 if (reader->patternTab == NULL) {
5355 reader->patternNr = 0;
5356 reader->patternMax = 0;
5357 }
5358 while (reader->patternNr > 0) {
5359 reader->patternNr--;
5360 if (reader->patternTab[reader->patternNr] != NULL) {
5361 xmlFreePattern(reader->patternTab[reader->patternNr]);
5362 reader->patternTab[reader->patternNr] = NULL;
5363 }
5364 }
5365#endif
5366
5367 if (options & XML_PARSE_DTDVALID)
5368 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5369
5370 xmlCtxtUseOptions(reader->ctxt, options);
5371 if (encoding != NULL) {
5372 xmlCharEncodingHandlerPtr hdlr;
5373
5374 hdlr = xmlFindCharEncodingHandler(encoding);
5375 if (hdlr != NULL)
5376 xmlSwitchToEncoding(reader->ctxt, hdlr);
5377 }
5378 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5379 (reader->ctxt->input->filename == NULL))
5380 reader->ctxt->input->filename = (char *)
5381 xmlStrdup((const xmlChar *) URL);
5382
5383 reader->doc = NULL;
5384
5385 return (0);
5386}
5387
5388/**
5389 * xmlTextReaderByteConsumed:
5390 * @reader: an XML reader
5391 *
5392 * This function provides the current index of the parser used
5393 * by the reader, relative to the start of the current entity.
5394 * This function actually just wraps a call to xmlBytesConsumed()
5395 * for the parser context associated with the reader.
5396 * See xmlBytesConsumed() for more information.
5397 *
5398 * Returns the index in bytes from the beginning of the entity or -1
5399 * in case the index could not be computed.
5400 */
5401long
5402xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5403 if ((reader == NULL) || (reader->ctxt == NULL))
5404 return(-1);
5405 return(xmlByteConsumed(reader->ctxt));
5406}
5407
5408
5409/**
5410 * xmlReaderWalker:
5411 * @doc: a preparsed document
5412 *
5413 * Create an xmltextReader for a preparsed document.
5414 *
5415 * Returns the new reader or NULL in case of error.
5416 */
5417xmlTextReaderPtr
5418xmlReaderWalker(xmlDocPtr doc)
5419{
5420 xmlTextReaderPtr ret;
5421
5422 if (doc == NULL)
5423 return(NULL);
5424
5425 ret = xmlMalloc(sizeof(xmlTextReader));
5426 if (ret == NULL) {
5427 xmlGenericError(xmlGenericErrorContext,
5428 "xmlNewTextReader : malloc failed\n");
5429 return(NULL);
5430 }
5431 memset(ret, 0, sizeof(xmlTextReader));
5432 ret->entNr = 0;
5433 ret->input = NULL;
5434 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5435 ret->node = NULL;
5436 ret->curnode = NULL;
5437 ret->base = 0;
5438 ret->cur = 0;
5439 ret->allocs = XML_TEXTREADER_CTXT;
5440 ret->doc = doc;
5441 ret->state = XML_TEXTREADER_START;
5442 ret->dict = xmlDictCreate();
5443 return(ret);
5444}
5445
5446/**
5447 * xmlReaderForDoc:
5448 * @cur: a pointer to a zero terminated string
5449 * @URL: the base URL to use for the document
5450 * @encoding: the document encoding, or NULL
5451 * @options: a combination of xmlParserOption
5452 *
5453 * Create an xmltextReader for an XML in-memory document.
5454 * The parsing flags @options are a combination of xmlParserOption.
5455 *
5456 * Returns the new reader or NULL in case of error.
5457 */
5458xmlTextReaderPtr
5459xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5460 int options)
5461{
5462 int len;
5463
5464 if (cur == NULL)
5465 return (NULL);
5466 len = xmlStrlen(cur);
5467
5468 return (xmlReaderForMemory
5469 ((const char *) cur, len, URL, encoding, options));
5470}
5471
5472/**
5473 * xmlReaderForFile:
5474 * @filename: a file or URL
5475 * @encoding: the document encoding, or NULL
5476 * @options: a combination of xmlParserOption
5477 *
5478 * parse an XML file from the filesystem or the network.
5479 * The parsing flags @options are a combination of xmlParserOption.
5480 *
5481 * Returns the new reader or NULL in case of error.
5482 */
5483xmlTextReaderPtr
5484xmlReaderForFile(const char *filename, const char *encoding, int options)
5485{
5486 xmlTextReaderPtr reader;
5487
5488 reader = xmlNewTextReaderFilename(filename);
5489 if (reader == NULL)
5490 return (NULL);
5491 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5492 return (reader);
5493}
5494
5495/**
5496 * xmlReaderForMemory:
5497 * @buffer: a pointer to a char array
5498 * @size: the size of the array
5499 * @URL: the base URL to use for the document
5500 * @encoding: the document encoding, or NULL
5501 * @options: a combination of xmlParserOption
5502 *
5503 * Create an xmltextReader for an XML in-memory document.
5504 * The parsing flags @options are a combination of xmlParserOption.
5505 *
5506 * Returns the new reader or NULL in case of error.
5507 */
5508xmlTextReaderPtr
5509xmlReaderForMemory(const char *buffer, int size, const char *URL,
5510 const char *encoding, int options)
5511{
5512 xmlTextReaderPtr reader;
5513 xmlParserInputBufferPtr buf;
5514
5515 buf = xmlParserInputBufferCreateStatic(buffer, size,
5516 XML_CHAR_ENCODING_NONE);
5517 if (buf == NULL) {
5518 return (NULL);
5519 }
5520 reader = xmlNewTextReader(buf, URL);
5521 if (reader == NULL) {
5522 xmlFreeParserInputBuffer(buf);
5523 return (NULL);
5524 }
5525 reader->allocs |= XML_TEXTREADER_INPUT;
5526 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5527 return (reader);
5528}
5529
5530/**
5531 * xmlReaderForFd:
5532 * @fd: an open file descriptor
5533 * @URL: the base URL to use for the document
5534 * @encoding: the document encoding, or NULL
5535 * @options: a combination of xmlParserOption
5536 *
5537 * Create an xmltextReader for an XML from a file descriptor.
5538 * The parsing flags @options are a combination of xmlParserOption.
5539 * NOTE that the file descriptor will not be closed when the
5540 * reader is closed or reset.
5541 *
5542 * Returns the new reader or NULL in case of error.
5543 */
5544xmlTextReaderPtr
5545xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5546{
5547 xmlTextReaderPtr reader;
5548 xmlParserInputBufferPtr input;
5549
5550 if (fd < 0)
5551 return (NULL);
5552
5553 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5554 if (input == NULL)
5555 return (NULL);
5556 input->closecallback = NULL;
5557 reader = xmlNewTextReader(input, URL);
5558 if (reader == NULL) {
5559 xmlFreeParserInputBuffer(input);
5560 return (NULL);
5561 }
5562 reader->allocs |= XML_TEXTREADER_INPUT;
5563 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5564 return (reader);
5565}
5566
5567/**
5568 * xmlReaderForIO:
5569 * @ioread: an I/O read function
5570 * @ioclose: an I/O close function
5571 * @ioctx: an I/O handler
5572 * @URL: the base URL to use for the document
5573 * @encoding: the document encoding, or NULL
5574 * @options: a combination of xmlParserOption
5575 *
5576 * Create an xmltextReader for an XML document from I/O functions and source.
5577 * The parsing flags @options are a combination of xmlParserOption.
5578 *
5579 * Returns the new reader or NULL in case of error.
5580 */
5581xmlTextReaderPtr
5582xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5583 void *ioctx, const char *URL, const char *encoding,
5584 int options)
5585{
5586 xmlTextReaderPtr reader;
5587 xmlParserInputBufferPtr input;
5588
5589 if (ioread == NULL)
5590 return (NULL);
5591
5592 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5593 XML_CHAR_ENCODING_NONE);
5594 if (input == NULL) {
5595 if (ioclose != NULL)
5596 ioclose(ioctx);
5597 return (NULL);
5598 }
5599 reader = xmlNewTextReader(input, URL);
5600 if (reader == NULL) {
5601 xmlFreeParserInputBuffer(input);
5602 return (NULL);
5603 }
5604 reader->allocs |= XML_TEXTREADER_INPUT;
5605 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5606 return (reader);
5607}
5608
5609/**
5610 * xmlReaderNewWalker:
5611 * @reader: an XML reader
5612 * @doc: a preparsed document
5613 *
5614 * Setup an xmltextReader to parse a preparsed XML document.
5615 * This reuses the existing @reader xmlTextReader.
5616 *
5617 * Returns 0 in case of success and -1 in case of error
5618 */
5619int
5620xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5621{
5622 if (doc == NULL)
5623 return (-1);
5624 if (reader == NULL)
5625 return (-1);
5626
5627 if (reader->input != NULL) {
5628 xmlFreeParserInputBuffer(reader->input);
5629 }
5630 if (reader->ctxt != NULL) {
5631 xmlCtxtReset(reader->ctxt);
5632 }
5633
5634 reader->entNr = 0;
5635 reader->input = NULL;
5636 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5637 reader->node = NULL;
5638 reader->curnode = NULL;
5639 reader->base = 0;
5640 reader->cur = 0;
5641 reader->allocs = XML_TEXTREADER_CTXT;
5642 reader->doc = doc;
5643 reader->state = XML_TEXTREADER_START;
5644 if (reader->dict == NULL) {
5645 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5646 reader->dict = reader->ctxt->dict;
5647 else
5648 reader->dict = xmlDictCreate();
5649 }
5650 return(0);
5651}
5652
5653/**
5654 * xmlReaderNewDoc:
5655 * @reader: an XML reader
5656 * @cur: a pointer to a zero terminated string
5657 * @URL: the base URL to use for the document
5658 * @encoding: the document encoding, or NULL
5659 * @options: a combination of xmlParserOption
5660 *
5661 * Setup an xmltextReader to parse an XML in-memory document.
5662 * The parsing flags @options are a combination of xmlParserOption.
5663 * This reuses the existing @reader xmlTextReader.
5664 *
5665 * Returns 0 in case of success and -1 in case of error
5666 */
5667int
5668xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5669 const char *URL, const char *encoding, int options)
5670{
5671
5672 int len;
5673
5674 if (cur == NULL)
5675 return (-1);
5676 if (reader == NULL)
5677 return (-1);
5678
5679 len = xmlStrlen(cur);
5680 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5681 URL, encoding, options));
5682}
5683
5684/**
5685 * xmlReaderNewFile:
5686 * @reader: an XML reader
5687 * @filename: a file or URL
5688 * @encoding: the document encoding, or NULL
5689 * @options: a combination of xmlParserOption
5690 *
5691 * parse an XML file from the filesystem or the network.
5692 * The parsing flags @options are a combination of xmlParserOption.
5693 * This reuses the existing @reader xmlTextReader.
5694 *
5695 * Returns 0 in case of success and -1 in case of error
5696 */
5697int
5698xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5699 const char *encoding, int options)
5700{
5701 xmlParserInputBufferPtr input;
5702
5703 if (filename == NULL)
5704 return (-1);
5705 if (reader == NULL)
5706 return (-1);
5707
5708 input =
5709 xmlParserInputBufferCreateFilename(filename,
5710 XML_CHAR_ENCODING_NONE);
5711 if (input == NULL)
5712 return (-1);
5713 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5714}
5715
5716/**
5717 * xmlReaderNewMemory:
5718 * @reader: an XML reader
5719 * @buffer: a pointer to a char array
5720 * @size: the size of the array
5721 * @URL: the base URL to use for the document
5722 * @encoding: the document encoding, or NULL
5723 * @options: a combination of xmlParserOption
5724 *
5725 * Setup an xmltextReader to parse an XML in-memory document.
5726 * The parsing flags @options are a combination of xmlParserOption.
5727 * This reuses the existing @reader xmlTextReader.
5728 *
5729 * Returns 0 in case of success and -1 in case of error
5730 */
5731int
5732xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5733 const char *URL, const char *encoding, int options)
5734{
5735 xmlParserInputBufferPtr input;
5736
5737 if (reader == NULL)
5738 return (-1);
5739 if (buffer == NULL)
5740 return (-1);
5741
5742 input = xmlParserInputBufferCreateStatic(buffer, size,
5743 XML_CHAR_ENCODING_NONE);
5744 if (input == NULL) {
5745 return (-1);
5746 }
5747 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5748}
5749
5750/**
5751 * xmlReaderNewFd:
5752 * @reader: an XML reader
5753 * @fd: an open file descriptor
5754 * @URL: the base URL to use for the document
5755 * @encoding: the document encoding, or NULL
5756 * @options: a combination of xmlParserOption
5757 *
5758 * Setup an xmltextReader to parse an XML from a file descriptor.
5759 * NOTE that the file descriptor will not be closed when the
5760 * reader is closed or reset.
5761 * The parsing flags @options are a combination of xmlParserOption.
5762 * This reuses the existing @reader xmlTextReader.
5763 *
5764 * Returns 0 in case of success and -1 in case of error
5765 */
5766int
5767xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5768 const char *URL, const char *encoding, int options)
5769{
5770 xmlParserInputBufferPtr input;
5771
5772 if (fd < 0)
5773 return (-1);
5774 if (reader == NULL)
5775 return (-1);
5776
5777 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5778 if (input == NULL)
5779 return (-1);
5780 input->closecallback = NULL;
5781 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5782}
5783
5784/**
5785 * xmlReaderNewIO:
5786 * @reader: an XML reader
5787 * @ioread: an I/O read function
5788 * @ioclose: an I/O close function
5789 * @ioctx: an I/O handler
5790 * @URL: the base URL to use for the document
5791 * @encoding: the document encoding, or NULL
5792 * @options: a combination of xmlParserOption
5793 *
5794 * Setup an xmltextReader to parse an XML document from I/O functions
5795 * and source.
5796 * The parsing flags @options are a combination of xmlParserOption.
5797 * This reuses the existing @reader xmlTextReader.
5798 *
5799 * Returns 0 in case of success and -1 in case of error
5800 */
5801int
5802xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5803 xmlInputCloseCallback ioclose, void *ioctx,
5804 const char *URL, const char *encoding, int options)
5805{
5806 xmlParserInputBufferPtr input;
5807
5808 if (ioread == NULL)
5809 return (-1);
5810 if (reader == NULL)
5811 return (-1);
5812
5813 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5814 XML_CHAR_ENCODING_NONE);
5815 if (input == NULL) {
5816 if (ioclose != NULL)
5817 ioclose(ioctx);
5818 return (-1);
5819 }
5820 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5821}
5822
5823/************************************************************************
5824 * *
5825 * Utilities *
5826 * *
5827 ************************************************************************/
5828#ifdef NOT_USED_YET
5829
5830/**
5831 * xmlBase64Decode:
5832 * @in: the input buffer
5833 * @inlen: the size of the input (in), the size read from it (out)
5834 * @to: the output buffer
5835 * @tolen: the size of the output (in), the size written to (out)
5836 *
5837 * Base64 decoder, reads from @in and save in @to
5838 * TODO: tell jody when this is actually exported
5839 *
5840 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5841 * 2 if there wasn't enough space on the output or -1 in case of error.
5842 */
5843static int
5844xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5845 unsigned char *to, unsigned long *tolen)
5846{
5847 unsigned long incur; /* current index in in[] */
5848
5849 unsigned long inblk; /* last block index in in[] */
5850
5851 unsigned long outcur; /* current index in out[] */
5852
5853 unsigned long inmax; /* size of in[] */
5854
5855 unsigned long outmax; /* size of out[] */
5856
5857 unsigned char cur; /* the current value read from in[] */
5858
5859 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5860
5861 int nbintmp; /* number of byte in intmp[] */
5862
5863 int is_ignore; /* cur should be ignored */
5864
5865 int is_end = 0; /* the end of the base64 was found */
5866
5867 int retval = 1;
5868
5869 int i;
5870
5871 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5872 return (-1);
5873
5874 incur = 0;
5875 inblk = 0;
5876 outcur = 0;
5877 inmax = *inlen;
5878 outmax = *tolen;
5879 nbintmp = 0;
5880
5881 while (1) {
5882 if (incur >= inmax)
5883 break;
5884 cur = in[incur++];
5885 is_ignore = 0;
5886 if ((cur >= 'A') && (cur <= 'Z'))
5887 cur = cur - 'A';
5888 else if ((cur >= 'a') && (cur <= 'z'))
5889 cur = cur - 'a' + 26;
5890 else if ((cur >= '0') && (cur <= '9'))
5891 cur = cur - '0' + 52;
5892 else if (cur == '+')
5893 cur = 62;
5894 else if (cur == '/')
5895 cur = 63;
5896 else if (cur == '.')
5897 cur = 0;
5898 else if (cur == '=') /*no op , end of the base64 stream */
5899 is_end = 1;
5900 else {
5901 is_ignore = 1;
5902 if (nbintmp == 0)
5903 inblk = incur;
5904 }
5905
5906 if (!is_ignore) {
5907 int nbouttmp = 3;
5908
5909 int is_break = 0;
5910
5911 if (is_end) {
5912 if (nbintmp == 0)
5913 break;
5914 if ((nbintmp == 1) || (nbintmp == 2))
5915 nbouttmp = 1;
5916 else
5917 nbouttmp = 2;
5918 nbintmp = 3;
5919 is_break = 1;
5920 }
5921 intmp[nbintmp++] = cur;
5922 /*
5923 * if intmp is full, push the 4byte sequence as a 3 byte
5924 * sequence out
5925 */
5926 if (nbintmp == 4) {
5927 nbintmp = 0;
5928 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5929 outtmp[1] =
5930 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5931 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5932 if (outcur + 3 >= outmax) {
5933 retval = 2;
5934 break;
5935 }
5936
5937 for (i = 0; i < nbouttmp; i++)
5938 to[outcur++] = outtmp[i];
5939 inblk = incur;
5940 }
5941
5942 if (is_break) {
5943 retval = 0;
5944 break;
5945 }
5946 }
5947 }
5948
5949 *tolen = outcur;
5950 *inlen = inblk;
5951 return (retval);
5952}
5953
5954/*
5955 * Test routine for the xmlBase64Decode function
5956 */
5957#if 0
5958int
5959main(int argc, char **argv)
5960{
5961 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5962
5963 char output[100];
5964
5965 char output2[100];
5966
5967 char output3[100];
5968
5969 unsigned long inlen = strlen(input);
5970
5971 unsigned long outlen = 100;
5972
5973 int ret;
5974
5975 unsigned long cons, tmp, tmp2, prod;
5976
5977 /*
5978 * Direct
5979 */
5980 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5981
5982 output[outlen] = 0;
5983 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5984 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5985;
5986
5987 /*
5988 * output chunking
5989 */
5990 cons = 0;
5991 prod = 0;
5992 while (cons < inlen) {
5993 tmp = 5;
5994 tmp2 = inlen - cons;
5995
5996 printf("%ld %ld\n", cons, prod);
5997 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5998 cons += tmp2;
5999 prod += tmp;
6000 printf("%ld %ld\n", cons, prod);
6001 }
6002 output2[outlen] = 0;
6003 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
6004 prod, output2);
6005
6006 /*
6007 * input chunking
6008 */
6009 cons = 0;
6010 prod = 0;
6011 while (cons < inlen) {
6012 tmp = 100 - prod;
6013 tmp2 = inlen - cons;
6014 if (tmp2 > 5)
6015 tmp2 = 5;
6016
6017 printf("%ld %ld\n", cons, prod);
6018 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
6019 cons += tmp2;
6020 prod += tmp;
6021 printf("%ld %ld\n", cons, prod);
6022 }
6023 output3[outlen] = 0;
6024 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
6025 prod, output3);
6026 return (0);
6027
6028}
6029#endif
6030#endif /* NOT_USED_YET */
6031#define bottom_xmlreader
6032#include "elfgcchack.h"
6033#endif /* LIBXML_READER_ENABLED */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette