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