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