VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/xmlreader.c@ 105681

最後變更 在這個檔案從105681是 105420,由 vboxsync 提交於 4 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

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

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