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