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