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