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