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