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