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