VirtualBox

source: vbox/trunk/src/libs/libxml2-2.6.30/xmlreader.c@ 8234

Last change on this file since 8234 was 6076, checked in by vboxsync, 17 years ago

Merged dmik/s2 branch (r25959:26751) to the trunk.

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