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