VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/xmlreader.c

Last change on this file was 104106, checked in by vboxsync, 8 weeks ago

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

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

© 2023 Oracle
ContactPrivacy policyTerms of Use