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