blob: 5fdf3a519800043f4f9463b67ed4171df7d90fe1 [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard067bae52003-01-05 01:27:54 +000015 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000016 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000017#define IN_LIBXML
18#include "libxml.h"
19
Daniel Veillard81273902003-09-30 00:43:48 +000020#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000022#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023
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>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000034#include <libxml/parserInternals.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000035#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +000036#include <libxml/relaxng.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000037#include <libxml/xmlschemas.h>
38#endif
Daniel Veillard198c1bf2003-10-20 17:07:41 +000039#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000040#ifdef LIBXML_XINCLUDE_ENABLED
41#include <libxml/xinclude.h>
42#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000046
47/* #define DEBUG_CALLBACKS */
48/* #define DEBUG_READER */
49
50/**
51 * TODO:
52 *
53 * macro to flag unimplemented blocks
54 */
55#define TODO \
56 xmlGenericError(xmlGenericErrorContext, \
57 "Unimplemented block at %s:%d\n", \
58 __FILE__, __LINE__);
59
60#ifdef DEBUG_READER
61#define DUMP_READER xmlTextReaderDebug(reader);
62#else
63#define DUMP_READER
64#endif
65
Daniel Veillarda880b122003-04-21 21:36:41 +000066#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000067/************************************************************************
68 * *
69 * The parser: maps the Text Reader API on top of the existing *
70 * parsing routines building a tree *
71 * *
72 ************************************************************************/
73
74#define XML_TEXTREADER_INPUT 1
75#define XML_TEXTREADER_CTXT 2
76
77typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +000078 XML_TEXTREADER_NONE = -1,
79 XML_TEXTREADER_START= 0,
80 XML_TEXTREADER_ELEMENT= 1,
81 XML_TEXTREADER_END= 2,
82 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000083 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000084 XML_TEXTREADER_DONE= 5,
85 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000086} xmlTextReaderState;
87
Daniel Veillardf4e55762003-04-15 23:32:22 +000088typedef enum {
89 XML_TEXTREADER_NOT_VALIDATE = 0,
90 XML_TEXTREADER_VALIDATE_DTD = 1,
Daniel Veillardf10ae122005-07-10 19:03:16 +000091 XML_TEXTREADER_VALIDATE_RNG = 2,
92 XML_TEXTREADER_VALIDATE_XSD = 4
Daniel Veillardf4e55762003-04-15 23:32:22 +000093} xmlTextReaderValidate;
94
Daniel Veillarde1ca5032002-12-09 14:13:43 +000095struct _xmlTextReader {
96 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +000097 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +000098 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000099 int allocs; /* what structure were deallocated */
100 xmlTextReaderState state;
101 xmlParserCtxtPtr ctxt; /* the parser context */
102 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
103 xmlParserInputBufferPtr input; /* the input */
104 startElementSAXFunc startElement;/* initial SAX callbacks */
105 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000106 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000107 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000108 charactersSAXFunc characters;
109 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000110 unsigned int base; /* base of the segment in the input */
111 unsigned int cur; /* current position in the input */
112 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000113 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000114 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000115 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000117 xmlBufferPtr buffer; /* used to return const xmlChar * */
118 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000119
120 /* entity stack when traversing entities content */
121 xmlNodePtr ent; /* Current Entity Ref Node */
122 int entNr; /* Depth of the entities stack */
123 int entMax; /* Max depth of the entities stack */
124 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000125
126 /* error handling */
127 xmlTextReaderErrorFunc errorFunc; /* callback function */
128 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000129
130#ifdef LIBXML_SCHEMAS_ENABLED
131 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000132 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
133 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
134 int rngValidErrors;/* The number of errors detected */
135 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000136 /* Handling of Schemas validation */
137 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
138 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
139 int xsdValidErrors;/* The number of errors detected */
140 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000141#endif
142#ifdef LIBXML_XINCLUDE_ENABLED
143 /* Handling of XInclude processing */
144 int xinclude; /* is xinclude asked for */
145 const xmlChar * xinclude_name; /* the xinclude name from dict */
146 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
147 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000148#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000149#ifdef LIBXML_PATTERN_ENABLED
150 int patternNr; /* number of preserve patterns */
151 int patternMax; /* max preserve patterns */
152 xmlPatternPtr *patternTab; /* array of preserve patterns */
153#endif
154 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000155 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000156 /* Structured error handling */
157 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000158};
159
Daniel Veillarde8039df2003-10-27 11:25:13 +0000160#define NODE_IS_EMPTY 0x1
161#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000162#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000163
Daniel Veillarde72c5082003-09-19 12:44:05 +0000164/**
165 * CONSTSTR:
166 *
167 * Macro used to return an interned string
168 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000169#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
170#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
171
172static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
173static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000174
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000175/************************************************************************
176 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000177 * Our own version of the freeing routines as we recycle nodes *
178 * *
179 ************************************************************************/
180/**
181 * DICT_FREE:
182 * @str: a string
183 *
184 * Free a string if it is not owned by the "dict" dictionnary in the
185 * current scope
186 */
187#define DICT_FREE(str) \
188 if ((str) && ((!dict) || \
189 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
190 xmlFree((char *)(str));
191
192static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
193static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
194
195/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000196 * xmlFreeID:
197 * @not: A id
198 *
199 * Deallocate the memory used by an id definition
200 */
201static void
202xmlFreeID(xmlIDPtr id) {
203 xmlDictPtr dict = NULL;
204
205 if (id == NULL) return;
206
207 if (id->doc != NULL)
208 dict = id->doc->dict;
209
210 if (id->value != NULL)
211 DICT_FREE(id->value)
212 xmlFree(id);
213}
214
215/**
216 * xmlTextReaderRemoveID:
217 * @doc: the document
218 * @attr: the attribute
219 *
220 * Remove the given attribute from the ID table maintained internally.
221 *
222 * Returns -1 if the lookup failed and 0 otherwise
223 */
224static int
225xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
226 xmlIDTablePtr table;
227 xmlIDPtr id;
228 xmlChar *ID;
229
230 if (doc == NULL) return(-1);
231 if (attr == NULL) return(-1);
232 table = (xmlIDTablePtr) doc->ids;
233 if (table == NULL)
234 return(-1);
235
236 if (attr == NULL)
237 return(-1);
238 ID = xmlNodeListGetString(doc, attr->children, 1);
239 if (ID == NULL)
240 return(-1);
241 id = xmlHashLookup(table, ID);
242 xmlFree(ID);
243 if (id == NULL || id->attr != attr) {
244 return(-1);
245 }
246 id->name = attr->name;
247 id->attr = NULL;
248 return(0);
249}
250
251/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000252 * xmlTextReaderFreeProp:
253 * @reader: the xmlTextReaderPtr used
254 * @cur: the node
255 *
256 * Free a node.
257 */
258static void
259xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
260 xmlDictPtr dict;
261
262 dict = reader->ctxt->dict;
263 if (cur == NULL) return;
264
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000265 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
266 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
267
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000268 /* Check for ID removal -> leading to invalid references ! */
269 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
270 ((cur->parent->doc->intSubset != NULL) ||
271 (cur->parent->doc->extSubset != NULL))) {
272 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000273 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000274 }
275 if (cur->children != NULL)
276 xmlTextReaderFreeNodeList(reader, cur->children);
277
278 DICT_FREE(cur->name);
279 if ((reader != NULL) && (reader->ctxt != NULL) &&
280 (reader->ctxt->freeAttrsNr < 100)) {
281 cur->next = reader->ctxt->freeAttrs;
282 reader->ctxt->freeAttrs = cur;
283 reader->ctxt->freeAttrsNr++;
284 } else {
285 xmlFree(cur);
286 }
287}
288
289/**
290 * xmlTextReaderFreePropList:
291 * @reader: the xmlTextReaderPtr used
292 * @cur: the first property in the list
293 *
294 * Free a property and all its siblings, all the children are freed too.
295 */
296static void
297xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
298 xmlAttrPtr next;
299 if (cur == NULL) return;
300 while (cur != NULL) {
301 next = cur->next;
302 xmlTextReaderFreeProp(reader, cur);
303 cur = next;
304 }
305}
306
307/**
308 * xmlTextReaderFreeNodeList:
309 * @reader: the xmlTextReaderPtr used
310 * @cur: the first node in the list
311 *
312 * Free a node and all its siblings, this is a recursive behaviour, all
313 * the children are freed too.
314 */
315static void
316xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
317 xmlNodePtr next;
318 xmlDictPtr dict;
319
320 dict = reader->ctxt->dict;
321 if (cur == NULL) return;
322 if (cur->type == XML_NAMESPACE_DECL) {
323 xmlFreeNsList((xmlNsPtr) cur);
324 return;
325 }
326 if ((cur->type == XML_DOCUMENT_NODE) ||
327 (cur->type == XML_HTML_DOCUMENT_NODE)) {
328 xmlFreeDoc((xmlDocPtr) cur);
329 return;
330 }
331 while (cur != NULL) {
332 next = cur->next;
333 /* unroll to speed up freeing the document */
334 if (cur->type != XML_DTD_NODE) {
335
336 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000337 (cur->type != XML_ENTITY_REF_NODE)) {
338 if (cur->children->parent == cur)
339 xmlTextReaderFreeNodeList(reader, cur->children);
340 cur->children = NULL;
341 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000342
343 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
344 xmlDeregisterNodeDefaultValue(cur);
345
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000346 if (((cur->type == XML_ELEMENT_NODE) ||
347 (cur->type == XML_XINCLUDE_START) ||
348 (cur->type == XML_XINCLUDE_END)) &&
349 (cur->properties != NULL))
350 xmlTextReaderFreePropList(reader, cur->properties);
351 if ((cur->type != XML_ELEMENT_NODE) &&
352 (cur->type != XML_XINCLUDE_START) &&
353 (cur->type != XML_XINCLUDE_END) &&
354 (cur->type != XML_ENTITY_REF_NODE)) {
355 DICT_FREE(cur->content);
356 }
357 if (((cur->type == XML_ELEMENT_NODE) ||
358 (cur->type == XML_XINCLUDE_START) ||
359 (cur->type == XML_XINCLUDE_END)) &&
360 (cur->nsDef != NULL))
361 xmlFreeNsList(cur->nsDef);
362
363 /*
364 * we don't free element names here they are interned now
365 */
366 if ((cur->type != XML_TEXT_NODE) &&
367 (cur->type != XML_COMMENT_NODE))
368 DICT_FREE(cur->name);
369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_TEXT_NODE)) &&
371 (reader != NULL) && (reader->ctxt != NULL) &&
372 (reader->ctxt->freeElemsNr < 100)) {
373 cur->next = reader->ctxt->freeElems;
374 reader->ctxt->freeElems = cur;
375 reader->ctxt->freeElemsNr++;
376 } else {
377 xmlFree(cur);
378 }
379 }
380 cur = next;
381 }
382}
383
384/**
385 * xmlTextReaderFreeNode:
386 * @reader: the xmlTextReaderPtr used
387 * @cur: the node
388 *
389 * Free a node, this is a recursive behaviour, all the children are freed too.
390 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
391 */
392static void
393xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
394 xmlDictPtr dict;
395
396 dict = reader->ctxt->dict;
397 if (cur->type == XML_DTD_NODE) {
398 xmlFreeDtd((xmlDtdPtr) cur);
399 return;
400 }
401 if (cur->type == XML_NAMESPACE_DECL) {
402 xmlFreeNs((xmlNsPtr) cur);
403 return;
404 }
405 if (cur->type == XML_ATTRIBUTE_NODE) {
406 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
407 return;
408 }
409
410 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000411 (cur->type != XML_ENTITY_REF_NODE)) {
412 if (cur->children->parent == cur)
413 xmlTextReaderFreeNodeList(reader, cur->children);
414 cur->children = NULL;
415 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000416
417 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
418 xmlDeregisterNodeDefaultValue(cur);
419
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000420 if (((cur->type == XML_ELEMENT_NODE) ||
421 (cur->type == XML_XINCLUDE_START) ||
422 (cur->type == XML_XINCLUDE_END)) &&
423 (cur->properties != NULL))
424 xmlTextReaderFreePropList(reader, cur->properties);
425 if ((cur->type != XML_ELEMENT_NODE) &&
426 (cur->type != XML_XINCLUDE_START) &&
427 (cur->type != XML_XINCLUDE_END) &&
428 (cur->type != XML_ENTITY_REF_NODE)) {
429 DICT_FREE(cur->content);
430 }
431 if (((cur->type == XML_ELEMENT_NODE) ||
432 (cur->type == XML_XINCLUDE_START) ||
433 (cur->type == XML_XINCLUDE_END)) &&
434 (cur->nsDef != NULL))
435 xmlFreeNsList(cur->nsDef);
436
437 /*
438 * we don't free names here they are interned now
439 */
440 if ((cur->type != XML_TEXT_NODE) &&
441 (cur->type != XML_COMMENT_NODE))
442 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000443
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000444 if (((cur->type == XML_ELEMENT_NODE) ||
445 (cur->type == XML_TEXT_NODE)) &&
446 (reader != NULL) && (reader->ctxt != NULL) &&
447 (reader->ctxt->freeElemsNr < 100)) {
448 cur->next = reader->ctxt->freeElems;
449 reader->ctxt->freeElems = cur;
450 reader->ctxt->freeElemsNr++;
451 } else {
452 xmlFree(cur);
453 }
454}
455
456/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000457 * xmlTextReaderFreeIDTable:
458 * @table: An id table
459 *
460 * Deallocate the memory used by an ID hash table.
461 */
William M. Brack60f394e2003-11-16 06:25:42 +0000462static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000463xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
464 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
465}
466
467/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000468 * xmlTextReaderFreeDoc:
469 * @reader: the xmlTextReaderPtr used
470 * @cur: pointer to the document
471 *
472 * Free up all the structures used by a document, tree included.
473 */
474static void
475xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
476 xmlDtdPtr extSubset, intSubset;
477
478 if (cur == NULL) return;
479
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000480 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
481 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
482
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000483 /*
484 * Do this before freeing the children list to avoid ID lookups
485 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000486 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000487 cur->ids = NULL;
488 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
489 cur->refs = NULL;
490 extSubset = cur->extSubset;
491 intSubset = cur->intSubset;
492 if (intSubset == extSubset)
493 extSubset = NULL;
494 if (extSubset != NULL) {
495 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
496 cur->extSubset = NULL;
497 xmlFreeDtd(extSubset);
498 }
499 if (intSubset != NULL) {
500 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
501 cur->intSubset = NULL;
502 xmlFreeDtd(intSubset);
503 }
504
505 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
506
507 if (cur->version != NULL) xmlFree((char *) cur->version);
508 if (cur->name != NULL) xmlFree((char *) cur->name);
509 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
510 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
511 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000512 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000513
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000514 xmlFree(cur);
515}
516
517/************************************************************************
518 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000519 * The reader core parser *
520 * *
521 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000522#ifdef DEBUG_READER
523static void
524xmlTextReaderDebug(xmlTextReaderPtr reader) {
525 if ((reader == NULL) || (reader->ctxt == NULL)) {
526 fprintf(stderr, "xmlTextReader NULL\n");
527 return;
528 }
529 fprintf(stderr, "xmlTextReader: state %d depth %d ",
530 reader->state, reader->depth);
531 if (reader->node == NULL) {
532 fprintf(stderr, "node = NULL\n");
533 } else {
534 fprintf(stderr, "node %s\n", reader->node->name);
535 }
536 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
537 reader->base, reader->cur, reader->ctxt->nodeNr);
538 if (reader->input->buffer == NULL) {
539 fprintf(stderr, "buffer is NULL\n");
540 } else {
541#ifdef LIBXML_DEBUG_ENABLED
542 xmlDebugDumpString(stderr,
543 &reader->input->buffer->content[reader->cur]);
544#endif
545 fprintf(stderr, "\n");
546 }
547}
548#endif
549
550/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000551 * xmlTextReaderEntPush:
552 * @reader: the xmlTextReaderPtr used
553 * @value: the entity reference node
554 *
555 * Pushes a new entity reference node on top of the entities stack
556 *
557 * Returns 0 in case of error, the index in the stack otherwise
558 */
559static int
560xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
561{
562 if (reader->entMax <= 0) {
563 reader->entMax = 10;
564 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
565 sizeof(reader->entTab[0]));
566 if (reader->entTab == NULL) {
567 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
568 return (0);
569 }
570 }
571 if (reader->entNr >= reader->entMax) {
572 reader->entMax *= 2;
573 reader->entTab =
574 (xmlNodePtr *) xmlRealloc(reader->entTab,
575 reader->entMax *
576 sizeof(reader->entTab[0]));
577 if (reader->entTab == NULL) {
578 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
579 return (0);
580 }
581 }
582 reader->entTab[reader->entNr] = value;
583 reader->ent = value;
584 return (reader->entNr++);
585}
586
587/**
588 * xmlTextReaderEntPop:
589 * @reader: the xmlTextReaderPtr used
590 *
591 * Pops the top element entity from the entities stack
592 *
593 * Returns the entity just removed
594 */
595static xmlNodePtr
596xmlTextReaderEntPop(xmlTextReaderPtr reader)
597{
598 xmlNodePtr ret;
599
600 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000601 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000602 reader->entNr--;
603 if (reader->entNr > 0)
604 reader->ent = reader->entTab[reader->entNr - 1];
605 else
606 reader->ent = NULL;
607 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000608 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000609 return (ret);
610}
611
612/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000613 * xmlTextReaderStartElement:
614 * @ctx: the user data (XML parser context)
615 * @fullname: The element name, including namespace prefix
616 * @atts: An array of name/value attributes pairs, NULL terminated
617 *
618 * called when an opening tag has been processed.
619 */
620static void
621xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
622 const xmlChar **atts) {
623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
624 xmlTextReaderPtr reader = ctxt->_private;
625
626#ifdef DEBUG_CALLBACKS
627 printf("xmlTextReaderStartElement(%s)\n", fullname);
628#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000629 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000630 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000631 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
632 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
633 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000634 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000635 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000636 if (reader != NULL)
637 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000638}
639
640/**
641 * xmlTextReaderEndElement:
642 * @ctx: the user data (XML parser context)
643 * @fullname: The element name, including namespace prefix
644 *
645 * called when an ending tag has been processed.
646 */
647static void
648xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
649 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
650 xmlTextReaderPtr reader = ctxt->_private;
651
652#ifdef DEBUG_CALLBACKS
653 printf("xmlTextReaderEndElement(%s)\n", fullname);
654#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000655 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000656 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000657 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000658}
659
660/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000661 * xmlTextReaderStartElementNs:
662 * @ctx: the user data (XML parser context)
663 * @localname: the local name of the element
664 * @prefix: the element namespace prefix if available
665 * @URI: the element namespace name if available
666 * @nb_namespaces: number of namespace definitions on that node
667 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
668 * @nb_attributes: the number of attributes on that node
669 * nb_defaulted: the number of defaulted attributes.
670 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
671 * attribute values.
672 *
673 * called when an opening tag has been processed.
674 */
675static void
676xmlTextReaderStartElementNs(void *ctx,
677 const xmlChar *localname,
678 const xmlChar *prefix,
679 const xmlChar *URI,
680 int nb_namespaces,
681 const xmlChar **namespaces,
682 int nb_attributes,
683 int nb_defaulted,
684 const xmlChar **attributes)
685{
686 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
687 xmlTextReaderPtr reader = ctxt->_private;
688
689#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000690 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000691#endif
692 if ((reader != NULL) && (reader->startElementNs != NULL)) {
693 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
694 namespaces, nb_attributes, nb_defaulted,
695 attributes);
696 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
697 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
698 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000699 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000700 }
701 if (reader != NULL)
702 reader->state = XML_TEXTREADER_ELEMENT;
703}
704
705/**
706 * xmlTextReaderEndElementNs:
707 * @ctx: the user data (XML parser context)
708 * @localname: the local name of the element
709 * @prefix: the element namespace prefix if available
710 * @URI: the element namespace name if available
711 *
712 * called when an ending tag has been processed.
713 */
714static void
715xmlTextReaderEndElementNs(void *ctx,
716 const xmlChar * localname,
717 const xmlChar * prefix,
718 const xmlChar * URI)
719{
720 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
721 xmlTextReaderPtr reader = ctxt->_private;
722
723#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000724 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000725#endif
726 if ((reader != NULL) && (reader->endElementNs != NULL)) {
727 reader->endElementNs(ctx, localname, prefix, URI);
728 }
729}
730
731
732/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000733 * xmlTextReaderCharacters:
734 * @ctx: the user data (XML parser context)
735 * @ch: a xmlChar string
736 * @len: the number of xmlChar
737 *
738 * receiving some chars from the parser.
739 */
740static void
741xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
742{
743 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
744 xmlTextReaderPtr reader = ctxt->_private;
745
746#ifdef DEBUG_CALLBACKS
747 printf("xmlTextReaderCharacters()\n");
748#endif
749 if ((reader != NULL) && (reader->characters != NULL)) {
750 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000751 }
752}
753
754/**
755 * xmlTextReaderCDataBlock:
756 * @ctx: the user data (XML parser context)
757 * @value: The pcdata content
758 * @len: the block length
759 *
760 * called when a pcdata block has been parsed
761 */
762static void
763xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
764{
765 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
766 xmlTextReaderPtr reader = ctxt->_private;
767
768#ifdef DEBUG_CALLBACKS
769 printf("xmlTextReaderCDataBlock()\n");
770#endif
771 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
772 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000773 }
774}
775
776/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000777 * xmlTextReaderPushData:
778 * @reader: the xmlTextReaderPtr used
779 *
780 * Push data down the progressive parser until a significant callback
781 * got raised.
782 *
783 * Returns -1 in case of failure, 0 otherwise
784 */
785static int
786xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000787 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000788 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000789 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000790
791 if ((reader->input == NULL) || (reader->input->buffer == NULL))
792 return(-1);
793
Daniel Veillardea7751d2002-12-20 00:16:24 +0000794 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000795 reader->state = XML_TEXTREADER_NONE;
796 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000797
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000799 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000800 /*
801 * Refill the buffer unless we are at the end of the stream
802 */
803 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
804 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000805 if ((val == 0) &&
806 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
807 if (inbuf->use == reader->cur) {
808 reader->mode = XML_TEXTREADER_MODE_EOF;
809 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000810 }
811 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000812 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000813 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000814 if ((oldstate != XML_TEXTREADER_START) ||
815 (reader->ctxt->myDoc != NULL))
816 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000817 } else if (val == 0) {
818 /* mark the end of the stream and process the remains */
819 reader->mode = XML_TEXTREADER_MODE_EOF;
820 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000822
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000823 } else
824 break;
825 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000826 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000827 * parse by block of CHUNK_SIZE bytes, various tests show that
828 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000829 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000831 val = xmlParseChunk(reader->ctxt,
832 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000833 CHUNK_SIZE, 0);
834 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000835 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000836 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000837 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000838 s = inbuf->use - reader->cur;
839 val = xmlParseChunk(reader->ctxt,
840 (const char *) &inbuf->content[reader->cur],
841 s, 0);
842 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000843 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000844 return(-1);
845 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000846 }
847 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000848
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000849 /*
850 * Discard the consumed input when needed and possible
851 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000852 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000853 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
854 if ((reader->cur >= 4096) &&
855 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
856 val = xmlBufferShrink(inbuf, reader->cur);
857 if (val >= 0) {
858 reader->cur -= val;
859 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000860 }
861 }
862 }
863
864 /*
865 * At the end of the stream signal that the work is done to the Push
866 * parser.
867 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000868 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000869 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000870 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000871 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000872 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000873 s, 1);
874 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000875 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000876 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000877 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000878 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000879 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000880 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000881 return(0);
882}
883
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000884#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000885/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000886 * xmlTextReaderValidatePush:
887 * @reader: the xmlTextReaderPtr used
888 *
889 * Push the current node for validation
890 */
891static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000892xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000893 xmlNodePtr node = reader->node;
894
Daniel Veillardf54cd532004-02-25 11:52:31 +0000895#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000896 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
897 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
898 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
899 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
900 reader->ctxt->myDoc, node, node->name);
901 } else {
902 /* TODO use the BuildQName interface */
903 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000904
Daniel Veillardf4e55762003-04-15 23:32:22 +0000905 qname = xmlStrdup(node->ns->prefix);
906 qname = xmlStrcat(qname, BAD_CAST ":");
907 qname = xmlStrcat(qname, node->name);
908 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
909 reader->ctxt->myDoc, node, qname);
910 if (qname != NULL)
911 xmlFree(qname);
912 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000913 }
914#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000915#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000916 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000917 (reader->rngValidCtxt != NULL)) {
918 int ret;
919
920 if (reader->rngFullNode != NULL) return;
921 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
922 reader->ctxt->myDoc,
923 node);
924 if (ret == 0) {
925 /*
926 * this element requires a full tree
927 */
928 node = xmlTextReaderExpand(reader);
929 if (node == NULL) {
930printf("Expand failed !\n");
931 ret = -1;
932 } else {
933 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
934 reader->ctxt->myDoc,
935 node);
936 reader->rngFullNode = node;
937 }
938 }
939 if (ret != 1)
940 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000941 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000942#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000943}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000944
945/**
946 * xmlTextReaderValidateCData:
947 * @reader: the xmlTextReaderPtr used
948 * @data: pointer to the CData
949 * @len: lenght of the CData block in bytes.
950 *
951 * Push some CData for validation
952 */
953static void
954xmlTextReaderValidateCData(xmlTextReaderPtr reader,
955 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000956#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000957 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
958 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
959 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
960 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000961 }
962#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000963#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000964 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965 (reader->rngValidCtxt != NULL)) {
966 int ret;
967
968 if (reader->rngFullNode != NULL) return;
969 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
970 if (ret != 1)
971 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000972 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000973#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000974}
975
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000976/**
977 * xmlTextReaderValidatePop:
978 * @reader: the xmlTextReaderPtr used
979 *
980 * Pop the current node from validation
981 */
982static void
983xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
984 xmlNodePtr node = reader->node;
985
Daniel Veillardf54cd532004-02-25 11:52:31 +0000986#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000987 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
988 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
989 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
990 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
991 reader->ctxt->myDoc, node, node->name);
992 } else {
993 /* TODO use the BuildQName interface */
994 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000995
Daniel Veillardf4e55762003-04-15 23:32:22 +0000996 qname = xmlStrdup(node->ns->prefix);
997 qname = xmlStrcat(qname, BAD_CAST ":");
998 qname = xmlStrcat(qname, node->name);
999 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1000 reader->ctxt->myDoc, node, qname);
1001 if (qname != NULL)
1002 xmlFree(qname);
1003 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001004 }
1005#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001006#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001008 (reader->rngValidCtxt != NULL)) {
1009 int ret;
1010
1011 if (reader->rngFullNode != NULL) {
1012 if (node == reader->rngFullNode)
1013 reader->rngFullNode = NULL;
1014 return;
1015 }
1016 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1017 reader->ctxt->myDoc,
1018 node);
1019 if (ret != 1)
1020 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001021 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001022#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001023}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001024
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001025/**
1026 * xmlTextReaderValidateEntity:
1027 * @reader: the xmlTextReaderPtr used
1028 *
1029 * Handle the validation when an entity reference is encountered and
1030 * entity substitution is not activated. As a result the parser interface
1031 * must walk through the entity and do the validation calls
1032 */
1033static void
1034xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1035 xmlNodePtr oldnode = reader->node;
1036 xmlNodePtr node = reader->node;
1037 xmlParserCtxtPtr ctxt = reader->ctxt;
1038
1039 do {
1040 if (node->type == XML_ENTITY_REF_NODE) {
1041 /*
1042 * Case where the underlying tree is not availble, lookup the entity
1043 * and walk it.
1044 */
1045 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1046 (ctxt->sax->getEntity != NULL)) {
1047 node->children = (xmlNodePtr)
1048 ctxt->sax->getEntity(ctxt, node->name);
1049 }
1050
1051 if ((node->children != NULL) &&
1052 (node->children->type == XML_ENTITY_DECL) &&
1053 (node->children->children != NULL)) {
1054 xmlTextReaderEntPush(reader, node);
1055 node = node->children->children;
1056 continue;
1057 } else {
1058 /*
1059 * The error has probably be raised already.
1060 */
1061 if (node == oldnode)
1062 break;
1063 node = node->next;
1064 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001065#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001066 } else if (node->type == XML_ELEMENT_NODE) {
1067 reader->node = node;
1068 xmlTextReaderValidatePush(reader);
1069 } else if ((node->type == XML_TEXT_NODE) ||
1070 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001071 xmlTextReaderValidateCData(reader, node->content,
1072 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001073#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001074 }
1075
1076 /*
1077 * go to next node
1078 */
1079 if (node->children != NULL) {
1080 node = node->children;
1081 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001082 } else if (node->type == XML_ELEMENT_NODE) {
1083 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001084 }
1085 if (node->next != NULL) {
1086 node = node->next;
1087 continue;
1088 }
1089 do {
1090 node = node->parent;
1091 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001092 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001093 if (reader->entNr == 0) {
1094 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001095 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 xmlUnlinkNode(tmp);
1097 xmlTextReaderFreeNode(reader, tmp);
1098 } else
1099 break;
1100 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001101 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001102 reader->node = node;
1103 xmlTextReaderValidatePop(reader);
1104 }
1105 if ((node->type == XML_ENTITY_DECL) &&
1106 (reader->ent != NULL) && (reader->ent->children == node)) {
1107 node = xmlTextReaderEntPop(reader);
1108 }
1109 if (node == oldnode)
1110 break;
1111 if (node->next != NULL) {
1112 node = node->next;
1113 break;
1114 }
1115 } while ((node != NULL) && (node != oldnode));
1116 } while ((node != NULL) && (node != oldnode));
1117 reader->node = oldnode;
1118}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001119#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001120
1121
1122/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001123 * xmlTextReaderGetSuccessor:
1124 * @cur: the current node
1125 *
1126 * Get the successor of a node if available.
1127 *
1128 * Returns the successor node or NULL
1129 */
1130static xmlNodePtr
1131xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1132 if (cur == NULL) return(NULL) ; /* ERROR */
1133 if (cur->next != NULL) return(cur->next) ;
1134 do {
1135 cur = cur->parent;
1136 if (cur == NULL) return(NULL);
1137 if (cur->next != NULL) return(cur->next);
1138 } while (cur != NULL);
1139 return(cur);
1140}
1141
1142/**
1143 * xmlTextReaderDoExpand:
1144 * @reader: the xmlTextReaderPtr used
1145 *
1146 * Makes sure that the current node is fully read as well as all its
1147 * descendant. It means the full DOM subtree must be available at the
1148 * end of the call.
1149 *
1150 * Returns 1 if the node was expanded successfully, 0 if there is no more
1151 * nodes to read, or -1 in case of error
1152 */
1153static int
1154xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1155 int val;
1156
1157 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1158 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001159 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001160 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1161
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001162 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1163 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001164 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001165 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001166 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1167 return(1);
1168 val = xmlTextReaderPushData(reader);
1169 if (val < 0)
1170 return(-1);
1171 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1172 return(1);
1173}
1174
1175/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001176 * xmlTextReaderCollectSiblings:
1177 * @node: the first child
1178 *
1179 * Traverse depth-first through all sibling nodes and their children
1180 * nodes and concatenate their content. This is an auxiliary function
1181 * to xmlTextReaderReadString.
1182 *
1183 * Returns a string containing the content, or NULL in case of error.
1184 */
1185static xmlChar *
1186xmlTextReaderCollectSiblings(xmlNodePtr node)
1187{
1188 xmlBufferPtr buffer;
1189 xmlChar *ret;
1190
1191 buffer = xmlBufferCreate();
1192 if (buffer == NULL)
1193 return NULL;
1194
1195 for ( ; node != NULL; node = node->next) {
1196 switch (node->type) {
1197 case XML_TEXT_NODE:
1198 case XML_CDATA_SECTION_NODE:
1199 xmlBufferCat(buffer, node->content);
1200 break;
1201 case XML_ELEMENT_NODE:
1202 xmlBufferCat(buffer, xmlTextReaderCollectSiblings(node->children));
1203 default:
1204 break;
1205 }
1206 }
1207 ret = buffer->content;
1208 buffer->content = NULL;
1209 xmlBufferFree(buffer);
1210 return(ret);
1211}
1212
1213/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001214 * xmlTextReaderRead:
1215 * @reader: the xmlTextReaderPtr used
1216 *
1217 * Moves the position of the current instance to the next node in
1218 * the stream, exposing its properties.
1219 *
1220 * Returns 1 if the node was read successfully, 0 if there is no more
1221 * nodes to read, or -1 in case of error
1222 */
1223int
1224xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001225 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001226 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001227 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001228
William M. Brack1af55582004-07-22 17:18:00 +00001229
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001230 if (reader == NULL)
1231 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001232 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001233 if (reader->doc != NULL)
1234 return(xmlTextReaderReadTree(reader));
1235 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001236 return(-1);
1237 if (reader->ctxt->wellFormed != 1)
1238 return(-1);
1239
1240#ifdef DEBUG_READER
1241 fprintf(stderr, "\nREAD ");
1242 DUMP_READER
1243#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001244 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1245 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001246 /*
1247 * Initial state
1248 */
1249 do {
1250 val = xmlTextReaderPushData(reader);
1251 if (val < 0)
1252 return(-1);
1253 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001254 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1255 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001256 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001257 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001258 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001259 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001260 if (reader->node == NULL)
1261 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001262 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001264 if (reader->ctxt->myDoc != NULL) {
1265 reader->node = reader->ctxt->myDoc->children;
1266 }
1267 if (reader->node == NULL)
1268 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001269 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001270 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001271 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001272 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001273 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001274 }
1275 oldstate = reader->state;
1276 olddepth = reader->ctxt->nodeNr;
1277 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001278
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001279get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001280 if (reader->node == NULL) {
1281 if (reader->mode == XML_TEXTREADER_DONE)
1282 return(0);
1283 else
1284 return(-1);
1285 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001286
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287 /*
1288 * If we are not backtracking on ancestors or examined nodes,
1289 * that the parser didn't finished or that we arent at the end
1290 * of stream, continue processing.
1291 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001292 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001293 (reader->ctxt->nodeNr == olddepth) &&
1294 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001295 (reader->node->children == NULL) ||
1296 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001297 ((reader->node->children != NULL) &&
1298 (reader->node->children->type == XML_TEXT_NODE) &&
1299 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001300 (reader->node->type == XML_DTD_NODE) ||
1301 (reader->node->type == XML_DOCUMENT_NODE) ||
1302 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001303 ((reader->ctxt->node == NULL) ||
1304 (reader->ctxt->node == reader->node) ||
1305 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001306 (reader->ctxt->instate != XML_PARSER_EOF)) {
1307 val = xmlTextReaderPushData(reader);
1308 if (val < 0)
1309 return(-1);
1310 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001311 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001312 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001313 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001314 if ((reader->node->children != NULL) &&
1315 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001316 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001317 (reader->node->type != XML_DTD_NODE)) {
1318 reader->node = reader->node->children;
1319 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001320 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001321 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 }
1323 }
1324 if (reader->node->next != NULL) {
1325 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001326 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001327 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001328 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1329#ifdef LIBXML_XINCLUDE_ENABLED
1330 && (reader->in_xinclude <= 0)
1331#endif
1332 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001333 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001334 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001336#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001337 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001338 (reader->node->type == XML_ELEMENT_NODE))
1339 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001340#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001341 if ((reader->preserves > 0) &&
1342 (reader->node->extra & NODE_IS_SPRESERVED))
1343 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 reader->node = reader->node->next;
1345 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001346
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001347 /*
1348 * Cleanup of the old node
1349 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001350 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001351#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001352 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001353#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001354 (reader->entNr == 0) &&
1355 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001356 (reader->node->prev->type != XML_DTD_NODE) &&
1357 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001358 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001359 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001360 xmlUnlinkNode(tmp);
1361 xmlTextReaderFreeNode(reader, tmp);
1362 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 }
1364
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001365 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001366 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001367 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001368 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001369 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001370 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001371 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001372 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001373 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001374#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001375 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001376 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001377#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001378 if ((reader->preserves > 0) &&
1379 (reader->node->extra & NODE_IS_SPRESERVED))
1380 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001381 reader->node = reader->node->parent;
1382 if ((reader->node == NULL) ||
1383 (reader->node->type == XML_DOCUMENT_NODE) ||
1384#ifdef LIBXML_DOCB_ENABLED
1385 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1386#endif
1387 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001388 if (reader->mode != XML_TEXTREADER_DONE) {
1389 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1390 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001391 if (val != 0)
1392 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001393 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001394 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001395 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001396
1397 /*
1398 * Cleanup of the old node
1399 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001400 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001401#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001402 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001403#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001404 (reader->entNr == 0) &&
1405 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001406 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001407 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001408 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001409 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001410 }
1411
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001412 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001413 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001414 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001415#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001416 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001417#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001418 (reader->entNr == 0) &&
1419 (reader->node->last != NULL) &&
1420 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1421 xmlNodePtr tmp = reader->node->last;
1422 xmlUnlinkNode(tmp);
1423 xmlTextReaderFreeNode(reader, tmp);
1424 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001425 reader->depth--;
1426 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001427
1428node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001429 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001430
1431 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001432 * If we are in the middle of a piece of CDATA make sure it's finished
1433 */
1434 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001435 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001436 ((reader->node->type == XML_TEXT_NODE) ||
1437 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001438 if (xmlTextReaderExpand(reader) == NULL)
1439 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001440 }
1441
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001442#ifdef LIBXML_XINCLUDE_ENABLED
1443 /*
1444 * Handle XInclude if asked for
1445 */
1446 if ((reader->xinclude) && (reader->node != NULL) &&
1447 (reader->node->type == XML_ELEMENT_NODE) &&
1448 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001449 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1450 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001451 if (reader->xincctxt == NULL) {
1452 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001453 xmlXIncludeSetFlags(reader->xincctxt,
1454 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001455 }
1456 /*
1457 * expand that node and process it
1458 */
William M. Brack42331a92004-07-29 07:07:16 +00001459 if (xmlTextReaderExpand(reader) == NULL)
1460 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001461 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1462 }
1463 if (reader->node->type == XML_XINCLUDE_START) {
1464 reader->in_xinclude++;
1465 goto get_next_node;
1466 }
1467 if (reader->node->type == XML_XINCLUDE_END) {
1468 reader->in_xinclude--;
1469 goto get_next_node;
1470 }
1471#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001472 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001473 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001474 */
1475 if ((reader->node != NULL) &&
1476 (reader->node->type == XML_ENTITY_REF_NODE) &&
1477 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1478 /*
1479 * Case where the underlying tree is not availble, lookup the entity
1480 * and walk it.
1481 */
1482 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1483 (reader->ctxt->sax->getEntity != NULL)) {
1484 reader->node->children = (xmlNodePtr)
1485 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1486 }
1487
1488 if ((reader->node->children != NULL) &&
1489 (reader->node->children->type == XML_ENTITY_DECL) &&
1490 (reader->node->children->children != NULL)) {
1491 xmlTextReaderEntPush(reader, reader->node);
1492 reader->node = reader->node->children->children;
1493 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001494#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001495 } else if ((reader->node != NULL) &&
1496 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001497 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001498 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001499#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001500 }
1501 if ((reader->node != NULL) &&
1502 (reader->node->type == XML_ENTITY_DECL) &&
1503 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1504 reader->node = xmlTextReaderEntPop(reader);
1505 reader->depth++;
1506 goto get_next_node;
1507 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001508#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001509 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001510 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001511
1512 if ((node->type == XML_ELEMENT_NODE) &&
1513 ((reader->state != XML_TEXTREADER_END) &&
1514 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1515 xmlTextReaderValidatePush(reader);
1516 } else if ((node->type == XML_TEXT_NODE) ||
1517 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001518 xmlTextReaderValidateCData(reader, node->content,
1519 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001520 }
1521 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001522#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001523#ifdef LIBXML_PATTERN_ENABLED
1524 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1525 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1526 int i;
1527 for (i = 0;i < reader->patternNr;i++) {
1528 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1529 xmlTextReaderPreserve(reader);
1530 break;
1531 }
1532 }
1533 }
1534#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001535#ifdef LIBXML_SCHEMAS_ENABLED
1536 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1537 (reader->xsdValidErrors == 0) &&
1538 (reader->xsdValidCtxt != NULL)) {
1539 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1540 }
1541#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001542 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001543node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001544 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001545 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001546}
1547
Daniel Veillard67df8092002-12-16 22:04:11 +00001548/**
1549 * xmlTextReaderReadState:
1550 * @reader: the xmlTextReaderPtr used
1551 *
1552 * Gets the read state of the reader.
1553 *
1554 * Returns the state value, or -1 in case of error
1555 */
1556int
1557xmlTextReaderReadState(xmlTextReaderPtr reader) {
1558 if (reader == NULL)
1559 return(-1);
1560 return(reader->mode);
1561}
1562
1563/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001564 * xmlTextReaderExpand:
1565 * @reader: the xmlTextReaderPtr used
1566 *
1567 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001568 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001569 *
1570 * Returns a node pointer valid until the next xmlTextReaderRead() call
1571 * or NULL in case of error.
1572 */
1573xmlNodePtr
1574xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001575 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001576 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001577 if (reader->doc != NULL)
1578 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001579 if (reader->ctxt == NULL)
1580 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001581 if (xmlTextReaderDoExpand(reader) < 0)
1582 return(NULL);
1583 return(reader->node);
1584}
1585
1586/**
1587 * xmlTextReaderNext:
1588 * @reader: the xmlTextReaderPtr used
1589 *
1590 * Skip to the node following the current one in document order while
1591 * avoiding the subtree if any.
1592 *
1593 * Returns 1 if the node was read successfully, 0 if there is no more
1594 * nodes to read, or -1 in case of error
1595 */
1596int
1597xmlTextReaderNext(xmlTextReaderPtr reader) {
1598 int ret;
1599 xmlNodePtr cur;
1600
1601 if (reader == NULL)
1602 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001603 if (reader->doc != NULL)
1604 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001605 cur = reader->node;
1606 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1607 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001608 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001609 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001610 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001611 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001612 do {
1613 ret = xmlTextReaderRead(reader);
1614 if (ret != 1)
1615 return(ret);
1616 } while (reader->node != cur);
1617 return(xmlTextReaderRead(reader));
1618}
1619
1620/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001621 * xmlTextReaderReadInnerXml:
1622 * @reader: the xmlTextReaderPtr used
1623 *
1624 * Reads the contents of the current node, including child nodes and markup.
1625 *
1626 * Returns a string containing the XML content, or NULL if the current node
1627 * is neither an element nor attribute, or has no child nodes. The
1628 * string must be deallocated by the caller.
1629 */
1630xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001631xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1632{
1633 xmlChar *resbuf;
1634 xmlNodePtr node, cur_node;
1635 xmlBufferPtr buff, buff2;
1636 xmlDocPtr doc;
1637
1638 if (xmlTextReaderExpand(reader) == NULL) {
1639 return NULL;
1640 }
1641 doc = reader->doc;
1642 buff = xmlBufferCreate();
1643 for (cur_node = reader->node->children; cur_node != NULL;
1644 cur_node = cur_node->next) {
1645 node = xmlDocCopyNode(cur_node, doc, 1);
1646 buff2 = xmlBufferCreate();
1647 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1648 xmlFreeNode(node);
1649 xmlBufferFree(buff2);
1650 xmlBufferFree(buff);
1651 return NULL;
1652 }
1653 xmlBufferCat(buff, buff2->content);
1654 xmlFreeNode(node);
1655 xmlBufferFree(buff2);
1656 }
1657 resbuf = buff->content;
1658 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001659}
1660
1661/**
1662 * xmlTextReaderReadOuterXml:
1663 * @reader: the xmlTextReaderPtr used
1664 *
1665 * Reads the contents of the current node, including child nodes and markup.
1666 *
1667 * Returns a string containing the XML content, or NULL if the current node
1668 * is neither an element nor attribute, or has no child nodes. The
1669 * string must be deallocated by the caller.
1670 */
1671xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001672xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1673{
1674 xmlChar *resbuf;
1675 xmlNodePtr node;
1676 xmlBufferPtr buff;
1677 xmlDocPtr doc;
1678
1679 node = reader->node;
1680 doc = reader->doc;
1681 if (xmlTextReaderExpand(reader) == NULL) {
1682 return NULL;
1683 }
1684 node = xmlDocCopyNode(node, doc, 1);
1685 buff = xmlBufferCreate();
1686 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1687 xmlFreeNode(node);
1688 xmlBufferFree(buff);
1689 return NULL;
1690 }
1691
1692 resbuf = buff->content;
1693 buff->content = NULL;
1694
1695 xmlFreeNode(node);
1696 xmlBufferFree(buff);
1697 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001698}
1699
1700/**
1701 * xmlTextReaderReadString:
1702 * @reader: the xmlTextReaderPtr used
1703 *
1704 * Reads the contents of an element or a text node as a string.
1705 *
1706 * Returns a string containing the contents of the Element or Text node,
1707 * or NULL if the reader is positioned on any other type of node.
1708 * The string must be deallocated by the caller.
1709 */
1710xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001711xmlTextReaderReadString(xmlTextReaderPtr reader)
1712{
1713 xmlNodePtr node;
1714
1715 if ((reader == NULL) || (reader->node == NULL))
1716 return(NULL);
1717
1718 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1719 switch (node->type) {
1720 case XML_TEXT_NODE:
1721 if (node->content != NULL)
1722 return(xmlStrdup(node->content));
1723 break;
1724 case XML_ELEMENT_NODE:
1725 if (xmlTextReaderDoExpand(reader) != -1) {
1726 return xmlTextReaderCollectSiblings(node->children);
1727 }
1728 case XML_ATTRIBUTE_NODE:
1729 TODO
1730 break;
1731 default:
1732 break;
1733 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001734 return(NULL);
1735}
1736
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001737#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001738/**
1739 * xmlTextReaderReadBase64:
1740 * @reader: the xmlTextReaderPtr used
1741 * @array: a byte array to store the content.
1742 * @offset: the zero-based index into array where the method should
1743 * begin to write.
1744 * @len: the number of bytes to write.
1745 *
1746 * Reads and decodes the Base64 encoded contents of an element and
1747 * stores the result in a byte buffer.
1748 *
1749 * Returns the number of bytes written to array, or zero if the current
1750 * instance is not positioned on an element or -1 in case of error.
1751 */
1752int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001753xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1754 unsigned char *array ATTRIBUTE_UNUSED,
1755 int offset ATTRIBUTE_UNUSED,
1756 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001757 if ((reader == NULL) || (reader->ctxt == NULL))
1758 return(-1);
1759 if (reader->ctxt->wellFormed != 1)
1760 return(-1);
1761
1762 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1763 return(0);
1764 TODO
1765 return(0);
1766}
1767
1768/**
1769 * xmlTextReaderReadBinHex:
1770 * @reader: the xmlTextReaderPtr used
1771 * @array: a byte array to store the content.
1772 * @offset: the zero-based index into array where the method should
1773 * begin to write.
1774 * @len: the number of bytes to write.
1775 *
1776 * Reads and decodes the BinHex encoded contents of an element and
1777 * stores the result in a byte buffer.
1778 *
1779 * Returns the number of bytes written to array, or zero if the current
1780 * instance is not positioned on an element or -1 in case of error.
1781 */
1782int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001783xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1784 unsigned char *array ATTRIBUTE_UNUSED,
1785 int offset ATTRIBUTE_UNUSED,
1786 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001787 if ((reader == NULL) || (reader->ctxt == NULL))
1788 return(-1);
1789 if (reader->ctxt->wellFormed != 1)
1790 return(-1);
1791
1792 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1793 return(0);
1794 TODO
1795 return(0);
1796}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001797#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001798
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001799/************************************************************************
1800 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 * Operating on a preparsed tree *
1802 * *
1803 ************************************************************************/
1804static int
1805xmlTextReaderNextTree(xmlTextReaderPtr reader)
1806{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001807 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001808 return(-1);
1809
1810 if (reader->state == XML_TEXTREADER_END)
1811 return(0);
1812
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001813 if (reader->node == NULL) {
1814 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001815 reader->state = XML_TEXTREADER_END;
1816 return(0);
1817 }
1818
1819 reader->node = reader->doc->children;
1820 reader->state = XML_TEXTREADER_START;
1821 return(1);
1822 }
1823
1824 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1825 if (reader->node->children != 0) {
1826 reader->node = reader->node->children;
1827 reader->depth++;
1828 reader->state = XML_TEXTREADER_START;
1829 return(1);
1830 }
1831
1832 if ((reader->node->type == XML_ELEMENT_NODE) ||
1833 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1834 reader->state = XML_TEXTREADER_BACKTRACK;
1835 return(1);
1836 }
1837 }
1838
1839 if (reader->node->next != 0) {
1840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1843 }
1844
1845 if (reader->node->parent != 0) {
1846 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1847 reader->state = XML_TEXTREADER_END;
1848 return(0);
1849 }
1850
1851 reader->node = reader->node->parent;
1852 reader->depth--;
1853 reader->state = XML_TEXTREADER_BACKTRACK;
1854 return(1);
1855 }
1856
1857 reader->state = XML_TEXTREADER_END;
1858
1859 return(1);
1860}
1861
1862/**
1863 * xmlTextReaderReadTree:
1864 * @reader: the xmlTextReaderPtr used
1865 *
1866 * Moves the position of the current instance to the next node in
1867 * the stream, exposing its properties.
1868 *
1869 * Returns 1 if the node was read successfully, 0 if there is no more
1870 * nodes to read, or -1 in case of error
1871 */
1872static int
1873xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1874 if (reader->state == XML_TEXTREADER_END)
1875 return(0);
1876
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001877next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001878 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;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001886 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001887 }
1888
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001889 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1890 (reader->node->type != XML_DTD_NODE) &&
1891 (reader->node->type != XML_XINCLUDE_START) &&
1892 (reader->node->type != XML_ENTITY_REF_NODE)) {
1893 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001894 reader->node = reader->node->children;
1895 reader->depth++;
1896 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001897 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001898 }
1899
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001900 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001901 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001902 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 }
1904 }
1905
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001906 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001907 reader->node = reader->node->next;
1908 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001909 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 }
1911
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001912 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001913 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1914 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1915 reader->state = XML_TEXTREADER_END;
1916 return(0);
1917 }
1918
1919 reader->node = reader->node->parent;
1920 reader->depth--;
1921 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001922 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 }
1924
1925 reader->state = XML_TEXTREADER_END;
1926
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001927found_node:
1928 if ((reader->node->type == XML_XINCLUDE_START) ||
1929 (reader->node->type == XML_XINCLUDE_END))
1930 goto next_node;
1931
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 return(1);
1933}
1934
1935/**
William M. Brackb1d53162003-11-18 06:54:40 +00001936 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001937 * @reader: the xmlTextReaderPtr used
1938 *
1939 * Skip to the node following the current one in document order while
1940 * avoiding the subtree if any.
1941 * Currently implemented only for Readers built on a document
1942 *
1943 * Returns 1 if the node was read successfully, 0 if there is no more
1944 * nodes to read, or -1 in case of error
1945 */
1946int
1947xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1948 if (reader == NULL)
1949 return(-1);
1950 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001951 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001952 return(-1);
1953 }
1954
1955 if (reader->state == XML_TEXTREADER_END)
1956 return(0);
1957
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001958 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001959 return(xmlTextReaderNextTree(reader));
1960
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001961 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001962 reader->node = reader->node->next;
1963 reader->state = XML_TEXTREADER_START;
1964 return(1);
1965 }
1966
1967 return(0);
1968}
1969
1970/************************************************************************
1971 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001972 * Constructor and destructors *
1973 * *
1974 ************************************************************************/
1975/**
1976 * xmlNewTextReader:
1977 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001978 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001979 *
1980 * Create an xmlTextReader structure fed with @input
1981 *
1982 * Returns the new xmlTextReaderPtr or NULL in case of error
1983 */
1984xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001985xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001986 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001987
1988 if (input == NULL)
1989 return(NULL);
1990 ret = xmlMalloc(sizeof(xmlTextReader));
1991 if (ret == NULL) {
1992 xmlGenericError(xmlGenericErrorContext,
1993 "xmlNewTextReader : malloc failed\n");
1994 return(NULL);
1995 }
1996 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001997 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001998 ret->entTab = NULL;
1999 ret->entMax = 0;
2000 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002001 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002002 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002003 if (ret->buffer == NULL) {
2004 xmlFree(ret);
2005 xmlGenericError(xmlGenericErrorContext,
2006 "xmlNewTextReader : malloc failed\n");
2007 return(NULL);
2008 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002009 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2010 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002011 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002012 xmlFree(ret);
2013 xmlGenericError(xmlGenericErrorContext,
2014 "xmlNewTextReader : malloc failed\n");
2015 return(NULL);
2016 }
Daniel Veillard81273902003-09-30 00:43:48 +00002017 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018 ret->startElement = ret->sax->startElement;
2019 ret->sax->startElement = xmlTextReaderStartElement;
2020 ret->endElement = ret->sax->endElement;
2021 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002022#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002023 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002024#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002025 ret->startElementNs = ret->sax->startElementNs;
2026 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2027 ret->endElementNs = ret->sax->endElementNs;
2028 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002029#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002030 } else {
2031 ret->startElementNs = NULL;
2032 ret->endElementNs = NULL;
2033 }
Daniel Veillard81273902003-09-30 00:43:48 +00002034#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002035 ret->characters = ret->sax->characters;
2036 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002037 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002038 ret->cdataBlock = ret->sax->cdataBlock;
2039 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002040
Daniel Veillard67df8092002-12-16 22:04:11 +00002041 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002042 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002043 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002044 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002045 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002046 }
2047 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002049 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002050 ret->base = 0;
2051 ret->cur = 4;
2052 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002053 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002054 ret->base = 0;
2055 ret->cur = 0;
2056 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002057
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002058 if (ret->ctxt == NULL) {
2059 xmlGenericError(xmlGenericErrorContext,
2060 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002061 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002062 xmlFree(ret->sax);
2063 xmlFree(ret);
2064 return(NULL);
2065 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002066 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002067 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002068 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002069 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002070 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002071 /*
2072 * use the parser dictionnary to allocate all elements and attributes names
2073 */
2074 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002075 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002076#ifdef LIBXML_XINCLUDE_ENABLED
2077 ret->xinclude = 0;
2078#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002079#ifdef LIBXML_PATTERN_ENABLED
2080 ret->patternMax = 0;
2081 ret->patternTab = NULL;
2082#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002083 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002084}
2085
2086/**
2087 * xmlNewTextReaderFilename:
2088 * @URI: the URI of the resource to process
2089 *
2090 * Create an xmlTextReader structure fed with the resource at @URI
2091 *
2092 * Returns the new xmlTextReaderPtr or NULL in case of error
2093 */
2094xmlTextReaderPtr
2095xmlNewTextReaderFilename(const char *URI) {
2096 xmlParserInputBufferPtr input;
2097 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002098 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002099
2100 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2101 if (input == NULL)
2102 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002103 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002104 if (ret == NULL) {
2105 xmlFreeParserInputBuffer(input);
2106 return(NULL);
2107 }
2108 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002109 if (ret->ctxt->directory == NULL)
2110 directory = xmlParserGetDirectory(URI);
2111 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2112 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2113 if (directory != NULL)
2114 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115 return(ret);
2116}
2117
2118/**
2119 * xmlFreeTextReader:
2120 * @reader: the xmlTextReaderPtr
2121 *
2122 * Deallocate all the resources associated to the reader
2123 */
2124void
2125xmlFreeTextReader(xmlTextReaderPtr reader) {
2126 if (reader == NULL)
2127 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002128#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002129 if (reader->rngSchemas != NULL) {
2130 xmlRelaxNGFree(reader->rngSchemas);
2131 reader->rngSchemas = NULL;
2132 }
2133 if (reader->rngValidCtxt != NULL) {
2134 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2135 reader->rngValidCtxt = NULL;
2136 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002137 if (reader->xsdPlug != NULL) {
2138 xmlSchemaSAXUnplug(reader->xsdPlug);
2139 reader->xsdPlug = NULL;
2140 }
2141 if (reader->xsdValidCtxt != NULL) {
2142 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2143 reader->xsdValidCtxt = NULL;
2144 }
2145 if (reader->xsdSchemas != NULL) {
2146 xmlSchemaFree(reader->xsdSchemas);
2147 reader->xsdSchemas = NULL;
2148 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002149#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002150#ifdef LIBXML_XINCLUDE_ENABLED
2151 if (reader->xincctxt != NULL)
2152 xmlXIncludeFreeContext(reader->xincctxt);
2153#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002154#ifdef LIBXML_PATTERN_ENABLED
2155 if (reader->patternTab != NULL) {
2156 int i;
2157 for (i = 0;i < reader->patternNr;i++) {
2158 if (reader->patternTab[i] != NULL)
2159 xmlFreePattern(reader->patternTab[i]);
2160 }
2161 xmlFree(reader->patternTab);
2162 }
2163#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002164 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002165 if (reader->dict == reader->ctxt->dict)
2166 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002167 if (reader->ctxt->myDoc != NULL) {
2168 if (reader->preserve == 0)
2169 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2170 reader->ctxt->myDoc = NULL;
2171 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002172 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2173 (reader->ctxt->vctxt.vstateMax > 0)){
2174 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002175 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002176 reader->ctxt->vctxt.vstateMax = 0;
2177 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002178 if (reader->allocs & XML_TEXTREADER_CTXT)
2179 xmlFreeParserCtxt(reader->ctxt);
2180 }
2181 if (reader->sax != NULL)
2182 xmlFree(reader->sax);
2183 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2184 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002185 if (reader->faketext != NULL) {
2186 xmlFreeNode(reader->faketext);
2187 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002188 if (reader->buffer != NULL)
2189 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002190 if (reader->entTab != NULL)
2191 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002192 if (reader->dict != NULL)
2193 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002194 xmlFree(reader);
2195}
2196
2197/************************************************************************
2198 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002199 * Methods for XmlTextReader *
2200 * *
2201 ************************************************************************/
2202/**
2203 * xmlTextReaderClose:
2204 * @reader: the xmlTextReaderPtr used
2205 *
2206 * This method releases any resources allocated by the current instance
2207 * changes the state to Closed and close any underlying input.
2208 *
2209 * Returns 0 or -1 in case of error
2210 */
2211int
2212xmlTextReaderClose(xmlTextReaderPtr reader) {
2213 if (reader == NULL)
2214 return(-1);
2215 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002216 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002217 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2218 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002219 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002220 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002221 if (reader->preserve == 0)
2222 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002223 reader->ctxt->myDoc = NULL;
2224 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002225 }
2226 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2227 xmlFreeParserInputBuffer(reader->input);
2228 reader->allocs -= XML_TEXTREADER_INPUT;
2229 }
2230 return(0);
2231}
2232
2233/**
2234 * xmlTextReaderGetAttributeNo:
2235 * @reader: the xmlTextReaderPtr used
2236 * @no: the zero-based index of the attribute relative to the containing element
2237 *
2238 * Provides the value of the attribute with the specified index relative
2239 * to the containing element.
2240 *
2241 * Returns a string containing the value of the specified attribute, or NULL
2242 * in case of error. The string must be deallocated by the caller.
2243 */
2244xmlChar *
2245xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2246 xmlChar *ret;
2247 int i;
2248 xmlAttrPtr cur;
2249 xmlNsPtr ns;
2250
2251 if (reader == NULL)
2252 return(NULL);
2253 if (reader->node == NULL)
2254 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002255 if (reader->curnode != NULL)
2256 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002257 /* TODO: handle the xmlDecl */
2258 if (reader->node->type != XML_ELEMENT_NODE)
2259 return(NULL);
2260
2261 ns = reader->node->nsDef;
2262 for (i = 0;(i < no) && (ns != NULL);i++) {
2263 ns = ns->next;
2264 }
2265 if (ns != NULL)
2266 return(xmlStrdup(ns->href));
2267
2268 cur = reader->node->properties;
2269 if (cur == NULL)
2270 return(NULL);
2271 for (;i < no;i++) {
2272 cur = cur->next;
2273 if (cur == NULL)
2274 return(NULL);
2275 }
2276 /* TODO walk the DTD if present */
2277
2278 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2279 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2280 return(ret);
2281}
2282
2283/**
2284 * xmlTextReaderGetAttribute:
2285 * @reader: the xmlTextReaderPtr used
2286 * @name: the qualified name of the attribute.
2287 *
2288 * Provides the value of the attribute with the specified qualified name.
2289 *
2290 * Returns a string containing the value of the specified attribute, or NULL
2291 * in case of error. The string must be deallocated by the caller.
2292 */
2293xmlChar *
2294xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2295 xmlChar *prefix = NULL;
2296 xmlChar *localname;
2297 xmlNsPtr ns;
2298 xmlChar *ret = NULL;
2299
2300 if ((reader == NULL) || (name == NULL))
2301 return(NULL);
2302 if (reader->node == NULL)
2303 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002304 if (reader->curnode != NULL)
2305 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002306
2307 /* TODO: handle the xmlDecl */
2308 if (reader->node->type != XML_ELEMENT_NODE)
2309 return(NULL);
2310
2311 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002312 if (localname == NULL) {
2313 /*
2314 * Namespace default decl
2315 */
2316 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2317 ns = reader->node->nsDef;
2318 while (ns != NULL) {
2319 if (ns->prefix == NULL) {
2320 return(xmlStrdup(ns->href));
2321 }
2322 ns = ns->next;
2323 }
2324 return NULL;
2325 }
2326 return(xmlGetNoNsProp(reader->node, name));
2327 }
2328
2329 /*
2330 * Namespace default decl
2331 */
2332 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2333 ns = reader->node->nsDef;
2334 while (ns != NULL) {
2335 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2336 ret = xmlStrdup(ns->href);
2337 break;
2338 }
2339 ns = ns->next;
2340 }
2341 } else {
2342 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2343 if (ns != NULL)
2344 ret = xmlGetNsProp(reader->node, localname, ns->href);
2345 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002346
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002347 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002348 if (prefix != NULL)
2349 xmlFree(prefix);
2350 return(ret);
2351}
2352
2353
2354/**
2355 * xmlTextReaderGetAttributeNs:
2356 * @reader: the xmlTextReaderPtr used
2357 * @localName: the local name of the attribute.
2358 * @namespaceURI: the namespace URI of the attribute.
2359 *
2360 * Provides the value of the specified attribute
2361 *
2362 * Returns a string containing the value of the specified attribute, or NULL
2363 * in case of error. The string must be deallocated by the caller.
2364 */
2365xmlChar *
2366xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2367 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002368 xmlChar *prefix = NULL;
2369 xmlNsPtr ns;
2370
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002371 if ((reader == NULL) || (localName == NULL))
2372 return(NULL);
2373 if (reader->node == NULL)
2374 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002375 if (reader->curnode != NULL)
2376 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002377
2378 /* TODO: handle the xmlDecl */
2379 if (reader->node->type != XML_ELEMENT_NODE)
2380 return(NULL);
2381
Daniel Veillard45b97e72005-08-20 21:14:28 +00002382 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2383 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2384 prefix = BAD_CAST localName;
2385 }
2386 ns = reader->node->nsDef;
2387 while (ns != NULL) {
2388 if ((prefix == NULL && ns->prefix == NULL) ||
2389 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2390 return xmlStrdup(ns->href);
2391 }
2392 ns = ns->next;
2393 }
2394 return NULL;
2395 }
2396
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002397 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2398}
2399
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002400/**
2401 * xmlTextReaderGetRemainder:
2402 * @reader: the xmlTextReaderPtr used
2403 *
2404 * Method to get the remainder of the buffered XML. this method stops the
2405 * parser, set its state to End Of File and return the input stream with
2406 * what is left that the parser did not use.
2407 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002408 * The implementation is not good, the parser certainly procgressed past
2409 * what's left in reader->input, and there is an allocation problem. Best
2410 * would be to rewrite it differently.
2411 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002412 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2413 * in case of error.
2414 */
2415xmlParserInputBufferPtr
2416xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2417 xmlParserInputBufferPtr ret = NULL;
2418
2419 if (reader == NULL)
2420 return(NULL);
2421 if (reader->node == NULL)
2422 return(NULL);
2423
2424 reader->node = NULL;
2425 reader->curnode = NULL;
2426 reader->mode = XML_TEXTREADER_MODE_EOF;
2427 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002428 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002429 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002430 if (reader->preserve == 0)
2431 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002432 reader->ctxt->myDoc = NULL;
2433 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002434 }
2435 if (reader->allocs & XML_TEXTREADER_INPUT) {
2436 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002437 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002438 reader->allocs -= XML_TEXTREADER_INPUT;
2439 } else {
2440 /*
2441 * Hum, one may need to duplicate the data structure because
2442 * without reference counting the input may be freed twice:
2443 * - by the layer which allocated it.
2444 * - by the layer to which would have been returned to.
2445 */
2446 TODO
2447 return(NULL);
2448 }
2449 return(ret);
2450}
2451
2452/**
2453 * xmlTextReaderLookupNamespace:
2454 * @reader: the xmlTextReaderPtr used
2455 * @prefix: the prefix whose namespace URI is to be resolved. To return
2456 * the default namespace, specify NULL
2457 *
2458 * Resolves a namespace prefix in the scope of the current element.
2459 *
2460 * Returns a string containing the namespace URI to which the prefix maps
2461 * or NULL in case of error. The string must be deallocated by the caller.
2462 */
2463xmlChar *
2464xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2465 xmlNsPtr ns;
2466
2467 if (reader == NULL)
2468 return(NULL);
2469 if (reader->node == NULL)
2470 return(NULL);
2471
2472 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2473 if (ns == NULL)
2474 return(NULL);
2475 return(xmlStrdup(ns->href));
2476}
2477
2478/**
2479 * xmlTextReaderMoveToAttributeNo:
2480 * @reader: the xmlTextReaderPtr used
2481 * @no: the zero-based index of the attribute relative to the containing
2482 * element.
2483 *
2484 * Moves the position of the current instance to the attribute with
2485 * the specified index relative to the containing element.
2486 *
2487 * Returns 1 in case of success, -1 in case of error, 0 if not found
2488 */
2489int
2490xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2491 int i;
2492 xmlAttrPtr cur;
2493 xmlNsPtr ns;
2494
2495 if (reader == NULL)
2496 return(-1);
2497 if (reader->node == NULL)
2498 return(-1);
2499 /* TODO: handle the xmlDecl */
2500 if (reader->node->type != XML_ELEMENT_NODE)
2501 return(-1);
2502
2503 reader->curnode = NULL;
2504
2505 ns = reader->node->nsDef;
2506 for (i = 0;(i < no) && (ns != NULL);i++) {
2507 ns = ns->next;
2508 }
2509 if (ns != NULL) {
2510 reader->curnode = (xmlNodePtr) ns;
2511 return(1);
2512 }
2513
2514 cur = reader->node->properties;
2515 if (cur == NULL)
2516 return(0);
2517 for (;i < no;i++) {
2518 cur = cur->next;
2519 if (cur == NULL)
2520 return(0);
2521 }
2522 /* TODO walk the DTD if present */
2523
2524 reader->curnode = (xmlNodePtr) cur;
2525 return(1);
2526}
2527
2528/**
2529 * xmlTextReaderMoveToAttribute:
2530 * @reader: the xmlTextReaderPtr used
2531 * @name: the qualified name of the attribute.
2532 *
2533 * Moves the position of the current instance to the attribute with
2534 * the specified qualified name.
2535 *
2536 * Returns 1 in case of success, -1 in case of error, 0 if not found
2537 */
2538int
2539xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2540 xmlChar *prefix = NULL;
2541 xmlChar *localname;
2542 xmlNsPtr ns;
2543 xmlAttrPtr prop;
2544
2545 if ((reader == NULL) || (name == NULL))
2546 return(-1);
2547 if (reader->node == NULL)
2548 return(-1);
2549
2550 /* TODO: handle the xmlDecl */
2551 if (reader->node->type != XML_ELEMENT_NODE)
2552 return(0);
2553
2554 localname = xmlSplitQName2(name, &prefix);
2555 if (localname == NULL) {
2556 /*
2557 * Namespace default decl
2558 */
2559 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2560 ns = reader->node->nsDef;
2561 while (ns != NULL) {
2562 if (ns->prefix == NULL) {
2563 reader->curnode = (xmlNodePtr) ns;
2564 return(1);
2565 }
2566 ns = ns->next;
2567 }
2568 return(0);
2569 }
2570
2571 prop = reader->node->properties;
2572 while (prop != NULL) {
2573 /*
2574 * One need to have
2575 * - same attribute names
2576 * - and the attribute carrying that namespace
2577 */
2578 if ((xmlStrEqual(prop->name, name)) &&
2579 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2580 reader->curnode = (xmlNodePtr) prop;
2581 return(1);
2582 }
2583 prop = prop->next;
2584 }
2585 return(0);
2586 }
2587
2588 /*
2589 * Namespace default decl
2590 */
2591 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2592 ns = reader->node->nsDef;
2593 while (ns != NULL) {
2594 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2595 reader->curnode = (xmlNodePtr) ns;
2596 goto found;
2597 }
2598 ns = ns->next;
2599 }
2600 goto not_found;
2601 }
2602 prop = reader->node->properties;
2603 while (prop != NULL) {
2604 /*
2605 * One need to have
2606 * - same attribute names
2607 * - and the attribute carrying that namespace
2608 */
2609 if ((xmlStrEqual(prop->name, localname)) &&
2610 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2611 reader->curnode = (xmlNodePtr) prop;
2612 goto found;
2613 }
2614 prop = prop->next;
2615 }
2616not_found:
2617 if (localname != NULL)
2618 xmlFree(localname);
2619 if (prefix != NULL)
2620 xmlFree(prefix);
2621 return(0);
2622
2623found:
2624 if (localname != NULL)
2625 xmlFree(localname);
2626 if (prefix != NULL)
2627 xmlFree(prefix);
2628 return(1);
2629}
2630
2631/**
2632 * xmlTextReaderMoveToAttributeNs:
2633 * @reader: the xmlTextReaderPtr used
2634 * @localName: the local name of the attribute.
2635 * @namespaceURI: the namespace URI of the attribute.
2636 *
2637 * Moves the position of the current instance to the attribute with the
2638 * specified local name and namespace URI.
2639 *
2640 * Returns 1 in case of success, -1 in case of error, 0 if not found
2641 */
2642int
2643xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2644 const xmlChar *localName, const xmlChar *namespaceURI) {
2645 xmlAttrPtr prop;
2646 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002647 xmlNsPtr ns;
2648 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002649
2650 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2651 return(-1);
2652 if (reader->node == NULL)
2653 return(-1);
2654 if (reader->node->type != XML_ELEMENT_NODE)
2655 return(0);
2656 node = reader->node;
2657
Daniel Veillard45b97e72005-08-20 21:14:28 +00002658 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2659 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2660 prefix = BAD_CAST localName;
2661 }
2662 ns = reader->node->nsDef;
2663 while (ns != NULL) {
2664 if ((prefix == NULL && ns->prefix == NULL) ||
2665 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2666 reader->curnode = (xmlNodePtr) ns;
2667 return(1);
2668 }
2669 ns = ns->next;
2670 }
2671 return(0);
2672 }
2673
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002674 prop = node->properties;
2675 while (prop != NULL) {
2676 /*
2677 * One need to have
2678 * - same attribute names
2679 * - and the attribute carrying that namespace
2680 */
2681 if (xmlStrEqual(prop->name, localName) &&
2682 ((prop->ns != NULL) &&
2683 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2684 reader->curnode = (xmlNodePtr) prop;
2685 return(1);
2686 }
2687 prop = prop->next;
2688 }
2689 return(0);
2690}
2691
2692/**
2693 * xmlTextReaderMoveToFirstAttribute:
2694 * @reader: the xmlTextReaderPtr used
2695 *
2696 * Moves the position of the current instance to the first attribute
2697 * associated with the current node.
2698 *
2699 * Returns 1 in case of success, -1 in case of error, 0 if not found
2700 */
2701int
2702xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2703 if (reader == NULL)
2704 return(-1);
2705 if (reader->node == NULL)
2706 return(-1);
2707 if (reader->node->type != XML_ELEMENT_NODE)
2708 return(0);
2709
2710 if (reader->node->nsDef != NULL) {
2711 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2712 return(1);
2713 }
2714 if (reader->node->properties != NULL) {
2715 reader->curnode = (xmlNodePtr) reader->node->properties;
2716 return(1);
2717 }
2718 return(0);
2719}
2720
2721/**
2722 * xmlTextReaderMoveToNextAttribute:
2723 * @reader: the xmlTextReaderPtr used
2724 *
2725 * Moves the position of the current instance to the next attribute
2726 * associated with the current node.
2727 *
2728 * Returns 1 in case of success, -1 in case of error, 0 if not found
2729 */
2730int
2731xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2732 if (reader == NULL)
2733 return(-1);
2734 if (reader->node == NULL)
2735 return(-1);
2736 if (reader->node->type != XML_ELEMENT_NODE)
2737 return(0);
2738 if (reader->curnode == NULL)
2739 return(xmlTextReaderMoveToFirstAttribute(reader));
2740
2741 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2742 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2743 if (ns->next != NULL) {
2744 reader->curnode = (xmlNodePtr) ns->next;
2745 return(1);
2746 }
2747 if (reader->node->properties != NULL) {
2748 reader->curnode = (xmlNodePtr) reader->node->properties;
2749 return(1);
2750 }
2751 return(0);
2752 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2753 (reader->curnode->next != NULL)) {
2754 reader->curnode = reader->curnode->next;
2755 return(1);
2756 }
2757 return(0);
2758}
2759
2760/**
2761 * xmlTextReaderMoveToElement:
2762 * @reader: the xmlTextReaderPtr used
2763 *
2764 * Moves the position of the current instance to the node that
2765 * contains the current Attribute node.
2766 *
2767 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2768 */
2769int
2770xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2771 if (reader == NULL)
2772 return(-1);
2773 if (reader->node == NULL)
2774 return(-1);
2775 if (reader->node->type != XML_ELEMENT_NODE)
2776 return(0);
2777 if (reader->curnode != NULL) {
2778 reader->curnode = NULL;
2779 return(1);
2780 }
2781 return(0);
2782}
2783
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002784/**
2785 * xmlTextReaderReadAttributeValue:
2786 * @reader: the xmlTextReaderPtr used
2787 *
2788 * Parses an attribute value into one or more Text and EntityReference nodes.
2789 *
2790 * Returns 1 in case of success, 0 if the reader was not positionned on an
2791 * ttribute node or all the attribute values have been read, or -1
2792 * in case of error.
2793 */
2794int
2795xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2796 if (reader == NULL)
2797 return(-1);
2798 if (reader->node == NULL)
2799 return(-1);
2800 if (reader->curnode == NULL)
2801 return(0);
2802 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2803 if (reader->curnode->children == NULL)
2804 return(0);
2805 reader->curnode = reader->curnode->children;
2806 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2807 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2808
2809 if (reader->faketext == NULL) {
2810 reader->faketext = xmlNewDocText(reader->node->doc,
2811 ns->href);
2812 } else {
2813 if (reader->faketext->content != NULL)
2814 xmlFree(reader->faketext->content);
2815 reader->faketext->content = xmlStrdup(ns->href);
2816 }
2817 reader->curnode = reader->faketext;
2818 } else {
2819 if (reader->curnode->next == NULL)
2820 return(0);
2821 reader->curnode = reader->curnode->next;
2822 }
2823 return(1);
2824}
2825
Daniel Veillarde2811272004-10-19 09:04:23 +00002826/**
2827 * xmlTextReaderConstEncoding:
2828 * @reader: the xmlTextReaderPtr used
2829 *
2830 * Determine the encoding of the document being read.
2831 *
2832 * Returns a string containing the encoding of the document or NULL in
2833 * case of error. The string is deallocated with the reader.
2834 */
2835const xmlChar *
2836xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2837 xmlDocPtr doc = NULL;
2838 if (reader == NULL)
2839 return(NULL);
2840 if (reader->doc != NULL)
2841 doc = reader->doc;
2842 else if (reader->ctxt != NULL)
2843 doc = reader->ctxt->myDoc;
2844 if (doc == NULL)
2845 return(NULL);
2846
2847 if (doc->encoding == NULL)
2848 return(NULL);
2849 else
2850 return(CONSTSTR(doc->encoding));
2851}
2852
2853
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002854/************************************************************************
2855 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002856 * Acces API to the current node *
2857 * *
2858 ************************************************************************/
2859/**
2860 * xmlTextReaderAttributeCount:
2861 * @reader: the xmlTextReaderPtr used
2862 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002863 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002864 *
2865 * Returns 0 i no attributes, -1 in case of error or the attribute count
2866 */
2867int
2868xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2869 int ret;
2870 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002871 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002872 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002873
2874 if (reader == NULL)
2875 return(-1);
2876 if (reader->node == NULL)
2877 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002878
2879 if (reader->curnode != NULL)
2880 node = reader->curnode;
2881 else
2882 node = reader->node;
2883
2884 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002885 return(0);
2886 if ((reader->state == XML_TEXTREADER_END) ||
2887 (reader->state == XML_TEXTREADER_BACKTRACK))
2888 return(0);
2889 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002890 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002891 while (attr != NULL) {
2892 ret++;
2893 attr = attr->next;
2894 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002895 ns = node->nsDef;
2896 while (ns != NULL) {
2897 ret++;
2898 ns = ns->next;
2899 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002900 return(ret);
2901}
2902
2903/**
2904 * xmlTextReaderNodeType:
2905 * @reader: the xmlTextReaderPtr used
2906 *
2907 * Get the node type of the current node
2908 * Reference:
2909 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2910 *
2911 * Returns the xmlNodeType of the current node or -1 in case of error
2912 */
2913int
2914xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002915 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002916
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002917 if (reader == NULL)
2918 return(-1);
2919 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002920 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002921 if (reader->curnode != NULL)
2922 node = reader->curnode;
2923 else
2924 node = reader->node;
2925 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002926 case XML_ELEMENT_NODE:
2927 if ((reader->state == XML_TEXTREADER_END) ||
2928 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002929 return(XML_READER_TYPE_END_ELEMENT);
2930 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002931 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002932 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002933 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002934 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002935 if (xmlIsBlankNode(reader->node)) {
2936 if (xmlNodeGetSpacePreserve(reader->node))
2937 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2938 else
2939 return(XML_READER_TYPE_WHITESPACE);
2940 } else {
2941 return(XML_READER_TYPE_TEXT);
2942 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002943 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002944 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002945 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002946 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002947 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002948 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002949 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002950 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002951 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002952 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002953 case XML_DOCUMENT_NODE:
2954 case XML_HTML_DOCUMENT_NODE:
2955#ifdef LIBXML_DOCB_ENABLED
2956 case XML_DOCB_DOCUMENT_NODE:
2957#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002958 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002959 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002960 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002962 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002963 case XML_DOCUMENT_TYPE_NODE:
2964 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002965 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002966
2967 case XML_ELEMENT_DECL:
2968 case XML_ATTRIBUTE_DECL:
2969 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002970 case XML_XINCLUDE_START:
2971 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002972 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002973 }
2974 return(-1);
2975}
2976
2977/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002978 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002979 * @reader: the xmlTextReaderPtr used
2980 *
2981 * Check if the current node is empty
2982 *
2983 * Returns 1 if empty, 0 if not and -1 in case of error
2984 */
2985int
2986xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2987 if ((reader == NULL) || (reader->node == NULL))
2988 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002989 if (reader->node->type != XML_ELEMENT_NODE)
2990 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002991 if (reader->curnode != NULL)
2992 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002993 if (reader->node->children != NULL)
2994 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002995 if (reader->state == XML_TEXTREADER_END)
2996 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002997 if (reader->doc != NULL)
2998 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002999#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003000 if (reader->in_xinclude > 0)
3001 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003002#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003003 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003004}
3005
3006/**
3007 * xmlTextReaderLocalName:
3008 * @reader: the xmlTextReaderPtr used
3009 *
3010 * The local name of the node.
3011 *
3012 * Returns the local name or NULL if not available
3013 */
3014xmlChar *
3015xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003016 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003017 if ((reader == NULL) || (reader->node == NULL))
3018 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003019 if (reader->curnode != NULL)
3020 node = reader->curnode;
3021 else
3022 node = reader->node;
3023 if (node->type == XML_NAMESPACE_DECL) {
3024 xmlNsPtr ns = (xmlNsPtr) node;
3025 if (ns->prefix == NULL)
3026 return(xmlStrdup(BAD_CAST "xmlns"));
3027 else
3028 return(xmlStrdup(ns->prefix));
3029 }
3030 if ((node->type != XML_ELEMENT_NODE) &&
3031 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003032 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003033 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003034}
3035
3036/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003037 * xmlTextReaderConstLocalName:
3038 * @reader: the xmlTextReaderPtr used
3039 *
3040 * The local name of the node.
3041 *
3042 * Returns the local name or NULL if not available, the
3043 * string will be deallocated with the reader.
3044 */
3045const xmlChar *
3046xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3047 xmlNodePtr node;
3048 if ((reader == NULL) || (reader->node == NULL))
3049 return(NULL);
3050 if (reader->curnode != NULL)
3051 node = reader->curnode;
3052 else
3053 node = reader->node;
3054 if (node->type == XML_NAMESPACE_DECL) {
3055 xmlNsPtr ns = (xmlNsPtr) node;
3056 if (ns->prefix == NULL)
3057 return(CONSTSTR(BAD_CAST "xmlns"));
3058 else
3059 return(ns->prefix);
3060 }
3061 if ((node->type != XML_ELEMENT_NODE) &&
3062 (node->type != XML_ATTRIBUTE_NODE))
3063 return(xmlTextReaderConstName(reader));
3064 return(node->name);
3065}
3066
3067/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003068 * xmlTextReaderName:
3069 * @reader: the xmlTextReaderPtr used
3070 *
3071 * The qualified name of the node, equal to Prefix :LocalName.
3072 *
3073 * Returns the local name or NULL if not available
3074 */
3075xmlChar *
3076xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003077 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003078 xmlChar *ret;
3079
3080 if ((reader == NULL) || (reader->node == NULL))
3081 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003082 if (reader->curnode != NULL)
3083 node = reader->curnode;
3084 else
3085 node = reader->node;
3086 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003087 case XML_ELEMENT_NODE:
3088 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003089 if ((node->ns == NULL) ||
3090 (node->ns->prefix == NULL))
3091 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003092
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003093 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003094 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003095 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003096 return(ret);
3097 case XML_TEXT_NODE:
3098 return(xmlStrdup(BAD_CAST "#text"));
3099 case XML_CDATA_SECTION_NODE:
3100 return(xmlStrdup(BAD_CAST "#cdata-section"));
3101 case XML_ENTITY_NODE:
3102 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003103 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003104 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003105 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003106 case XML_COMMENT_NODE:
3107 return(xmlStrdup(BAD_CAST "#comment"));
3108 case XML_DOCUMENT_NODE:
3109 case XML_HTML_DOCUMENT_NODE:
3110#ifdef LIBXML_DOCB_ENABLED
3111 case XML_DOCB_DOCUMENT_NODE:
3112#endif
3113 return(xmlStrdup(BAD_CAST "#document"));
3114 case XML_DOCUMENT_FRAG_NODE:
3115 return(xmlStrdup(BAD_CAST "#document-fragment"));
3116 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003117 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003118 case XML_DOCUMENT_TYPE_NODE:
3119 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003120 return(xmlStrdup(node->name));
3121 case XML_NAMESPACE_DECL: {
3122 xmlNsPtr ns = (xmlNsPtr) node;
3123
3124 ret = xmlStrdup(BAD_CAST "xmlns");
3125 if (ns->prefix == NULL)
3126 return(ret);
3127 ret = xmlStrcat(ret, BAD_CAST ":");
3128 ret = xmlStrcat(ret, ns->prefix);
3129 return(ret);
3130 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003131
3132 case XML_ELEMENT_DECL:
3133 case XML_ATTRIBUTE_DECL:
3134 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003135 case XML_XINCLUDE_START:
3136 case XML_XINCLUDE_END:
3137 return(NULL);
3138 }
3139 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003140}
3141
3142/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003143 * xmlTextReaderConstName:
3144 * @reader: the xmlTextReaderPtr used
3145 *
3146 * The qualified name of the node, equal to Prefix :LocalName.
3147 *
3148 * Returns the local name or NULL if not available, the string is
3149 * deallocated with the reader.
3150 */
3151const xmlChar *
3152xmlTextReaderConstName(xmlTextReaderPtr reader) {
3153 xmlNodePtr node;
3154
3155 if ((reader == NULL) || (reader->node == NULL))
3156 return(NULL);
3157 if (reader->curnode != NULL)
3158 node = reader->curnode;
3159 else
3160 node = reader->node;
3161 switch (node->type) {
3162 case XML_ELEMENT_NODE:
3163 case XML_ATTRIBUTE_NODE:
3164 if ((node->ns == NULL) ||
3165 (node->ns->prefix == NULL))
3166 return(node->name);
3167 return(CONSTQSTR(node->ns->prefix, node->name));
3168 case XML_TEXT_NODE:
3169 return(CONSTSTR(BAD_CAST "#text"));
3170 case XML_CDATA_SECTION_NODE:
3171 return(CONSTSTR(BAD_CAST "#cdata-section"));
3172 case XML_ENTITY_NODE:
3173 case XML_ENTITY_REF_NODE:
3174 return(CONSTSTR(node->name));
3175 case XML_PI_NODE:
3176 return(CONSTSTR(node->name));
3177 case XML_COMMENT_NODE:
3178 return(CONSTSTR(BAD_CAST "#comment"));
3179 case XML_DOCUMENT_NODE:
3180 case XML_HTML_DOCUMENT_NODE:
3181#ifdef LIBXML_DOCB_ENABLED
3182 case XML_DOCB_DOCUMENT_NODE:
3183#endif
3184 return(CONSTSTR(BAD_CAST "#document"));
3185 case XML_DOCUMENT_FRAG_NODE:
3186 return(CONSTSTR(BAD_CAST "#document-fragment"));
3187 case XML_NOTATION_NODE:
3188 return(CONSTSTR(node->name));
3189 case XML_DOCUMENT_TYPE_NODE:
3190 case XML_DTD_NODE:
3191 return(CONSTSTR(node->name));
3192 case XML_NAMESPACE_DECL: {
3193 xmlNsPtr ns = (xmlNsPtr) node;
3194
3195 if (ns->prefix == NULL)
3196 return(CONSTSTR(BAD_CAST "xmlns"));
3197 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3198 }
3199
3200 case XML_ELEMENT_DECL:
3201 case XML_ATTRIBUTE_DECL:
3202 case XML_ENTITY_DECL:
3203 case XML_XINCLUDE_START:
3204 case XML_XINCLUDE_END:
3205 return(NULL);
3206 }
3207 return(NULL);
3208}
3209
3210/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003211 * xmlTextReaderPrefix:
3212 * @reader: the xmlTextReaderPtr used
3213 *
3214 * A shorthand reference to the namespace associated with the node.
3215 *
3216 * Returns the prefix or NULL if not available
3217 */
3218xmlChar *
3219xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003220 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003221 if ((reader == NULL) || (reader->node == NULL))
3222 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003223 if (reader->curnode != NULL)
3224 node = reader->curnode;
3225 else
3226 node = reader->node;
3227 if (node->type == XML_NAMESPACE_DECL) {
3228 xmlNsPtr ns = (xmlNsPtr) node;
3229 if (ns->prefix == NULL)
3230 return(NULL);
3231 return(xmlStrdup(BAD_CAST "xmlns"));
3232 }
3233 if ((node->type != XML_ELEMENT_NODE) &&
3234 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003235 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003236 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003237 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003238 return(NULL);
3239}
3240
3241/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003242 * xmlTextReaderConstPrefix:
3243 * @reader: the xmlTextReaderPtr used
3244 *
3245 * A shorthand reference to the namespace associated with the node.
3246 *
3247 * Returns the prefix or NULL if not available, the string is deallocated
3248 * with the reader.
3249 */
3250const xmlChar *
3251xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3252 xmlNodePtr node;
3253 if ((reader == NULL) || (reader->node == NULL))
3254 return(NULL);
3255 if (reader->curnode != NULL)
3256 node = reader->curnode;
3257 else
3258 node = reader->node;
3259 if (node->type == XML_NAMESPACE_DECL) {
3260 xmlNsPtr ns = (xmlNsPtr) node;
3261 if (ns->prefix == NULL)
3262 return(NULL);
3263 return(CONSTSTR(BAD_CAST "xmlns"));
3264 }
3265 if ((node->type != XML_ELEMENT_NODE) &&
3266 (node->type != XML_ATTRIBUTE_NODE))
3267 return(NULL);
3268 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3269 return(CONSTSTR(node->ns->prefix));
3270 return(NULL);
3271}
3272
3273/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003274 * xmlTextReaderNamespaceUri:
3275 * @reader: the xmlTextReaderPtr used
3276 *
3277 * The URI defining the namespace associated with the node.
3278 *
3279 * Returns the namespace URI or NULL if not available
3280 */
3281xmlChar *
3282xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003283 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003284 if ((reader == NULL) || (reader->node == NULL))
3285 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003286 if (reader->curnode != NULL)
3287 node = reader->curnode;
3288 else
3289 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003290 if (node->type == XML_NAMESPACE_DECL)
3291 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003292 if ((node->type != XML_ELEMENT_NODE) &&
3293 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003294 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003295 if (node->ns != NULL)
3296 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003297 return(NULL);
3298}
3299
3300/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003301 * xmlTextReaderConstNamespaceUri:
3302 * @reader: the xmlTextReaderPtr used
3303 *
3304 * The URI defining the namespace associated with the node.
3305 *
3306 * Returns the namespace URI or NULL if not available, the string
3307 * will be deallocated with the reader
3308 */
3309const xmlChar *
3310xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3311 xmlNodePtr node;
3312 if ((reader == NULL) || (reader->node == NULL))
3313 return(NULL);
3314 if (reader->curnode != NULL)
3315 node = reader->curnode;
3316 else
3317 node = reader->node;
3318 if (node->type == XML_NAMESPACE_DECL)
3319 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3320 if ((node->type != XML_ELEMENT_NODE) &&
3321 (node->type != XML_ATTRIBUTE_NODE))
3322 return(NULL);
3323 if (node->ns != NULL)
3324 return(CONSTSTR(node->ns->href));
3325 return(NULL);
3326}
3327
3328/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003329 * xmlTextReaderBaseUri:
3330 * @reader: the xmlTextReaderPtr used
3331 *
3332 * The base URI of the node.
3333 *
3334 * Returns the base URI or NULL if not available
3335 */
3336xmlChar *
3337xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3338 if ((reader == NULL) || (reader->node == NULL))
3339 return(NULL);
3340 return(xmlNodeGetBase(NULL, reader->node));
3341}
3342
3343/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003344 * xmlTextReaderConstBaseUri:
3345 * @reader: the xmlTextReaderPtr used
3346 *
3347 * The base URI of the node.
3348 *
3349 * Returns the base URI or NULL if not available, the string
3350 * will be deallocated with the reader
3351 */
3352const xmlChar *
3353xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3354 xmlChar *tmp;
3355 const xmlChar *ret;
3356
3357 if ((reader == NULL) || (reader->node == NULL))
3358 return(NULL);
3359 tmp = xmlNodeGetBase(NULL, reader->node);
3360 if (tmp == NULL)
3361 return(NULL);
3362 ret = CONSTSTR(tmp);
3363 xmlFree(tmp);
3364 return(ret);
3365}
3366
3367/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003368 * xmlTextReaderDepth:
3369 * @reader: the xmlTextReaderPtr used
3370 *
3371 * The depth of the node in the tree.
3372 *
3373 * Returns the depth or -1 in case of error
3374 */
3375int
3376xmlTextReaderDepth(xmlTextReaderPtr reader) {
3377 if (reader == NULL)
3378 return(-1);
3379 if (reader->node == NULL)
3380 return(0);
3381
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003382 if (reader->curnode != NULL) {
3383 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3384 (reader->curnode->type == XML_NAMESPACE_DECL))
3385 return(reader->depth + 1);
3386 return(reader->depth + 2);
3387 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003388 return(reader->depth);
3389}
3390
3391/**
3392 * xmlTextReaderHasAttributes:
3393 * @reader: the xmlTextReaderPtr used
3394 *
3395 * Whether the node has attributes.
3396 *
3397 * Returns 1 if true, 0 if false, and -1 in case or error
3398 */
3399int
3400xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003401 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003402 if (reader == NULL)
3403 return(-1);
3404 if (reader->node == NULL)
3405 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003406 if (reader->curnode != NULL)
3407 node = reader->curnode;
3408 else
3409 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003410
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003411 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003412 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003413 return(1);
3414 /* TODO: handle the xmlDecl */
3415 return(0);
3416}
3417
3418/**
3419 * xmlTextReaderHasValue:
3420 * @reader: the xmlTextReaderPtr used
3421 *
3422 * Whether the node can have a text value.
3423 *
3424 * Returns 1 if true, 0 if false, and -1 in case or error
3425 */
3426int
3427xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003428 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003429 if (reader == NULL)
3430 return(-1);
3431 if (reader->node == NULL)
3432 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003433 if (reader->curnode != NULL)
3434 node = reader->curnode;
3435 else
3436 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003437
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003438 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003439 case XML_ATTRIBUTE_NODE:
3440 case XML_TEXT_NODE:
3441 case XML_CDATA_SECTION_NODE:
3442 case XML_PI_NODE:
3443 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003444 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003445 return(1);
3446 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003447 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003448 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003449 return(0);
3450}
3451
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003452/**
3453 * xmlTextReaderValue:
3454 * @reader: the xmlTextReaderPtr used
3455 *
3456 * Provides the text value of the node if present
3457 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003458 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003459 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003460 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003461xmlChar *
3462xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003463 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003464 if (reader == NULL)
3465 return(NULL);
3466 if (reader->node == NULL)
3467 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003468 if (reader->curnode != NULL)
3469 node = reader->curnode;
3470 else
3471 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003472
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003473 switch (node->type) {
3474 case XML_NAMESPACE_DECL:
3475 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003476 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003477 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003478
3479 if (attr->parent != NULL)
3480 return (xmlNodeListGetString
3481 (attr->parent->doc, attr->children, 1));
3482 else
3483 return (xmlNodeListGetString(NULL, attr->children, 1));
3484 break;
3485 }
3486 case XML_TEXT_NODE:
3487 case XML_CDATA_SECTION_NODE:
3488 case XML_PI_NODE:
3489 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003490 if (node->content != NULL)
3491 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003492 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003493 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003494 }
3495 return(NULL);
3496}
3497
3498/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003499 * xmlTextReaderConstValue:
3500 * @reader: the xmlTextReaderPtr used
3501 *
3502 * Provides the text value of the node if present
3503 *
3504 * Returns the string or NULL if not available. The result will be
3505 * deallocated on the next Read() operation.
3506 */
3507const xmlChar *
3508xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3509 xmlNodePtr node;
3510 if (reader == NULL)
3511 return(NULL);
3512 if (reader->node == NULL)
3513 return(NULL);
3514 if (reader->curnode != NULL)
3515 node = reader->curnode;
3516 else
3517 node = reader->node;
3518
3519 switch (node->type) {
3520 case XML_NAMESPACE_DECL:
3521 return(((xmlNsPtr) node)->href);
3522 case XML_ATTRIBUTE_NODE:{
3523 xmlAttrPtr attr = (xmlAttrPtr) node;
3524
3525 if ((attr->children != NULL) &&
3526 (attr->children->type == XML_TEXT_NODE) &&
3527 (attr->children->next == NULL))
3528 return(attr->children->content);
3529 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003530 if (reader->buffer == NULL)
3531 reader->buffer = xmlBufferCreateSize(100);
3532 if (reader->buffer == NULL) {
3533 xmlGenericError(xmlGenericErrorContext,
3534 "xmlTextReaderSetup : malloc failed\n");
3535 return (NULL);
3536 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003537 reader->buffer->use = 0;
3538 xmlNodeBufGetContent(reader->buffer, node);
3539 return(reader->buffer->content);
3540 }
3541 break;
3542 }
3543 case XML_TEXT_NODE:
3544 case XML_CDATA_SECTION_NODE:
3545 case XML_PI_NODE:
3546 case XML_COMMENT_NODE:
3547 return(node->content);
3548 default:
3549 break;
3550 }
3551 return(NULL);
3552}
3553
3554/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003555 * xmlTextReaderIsDefault:
3556 * @reader: the xmlTextReaderPtr used
3557 *
3558 * Whether an Attribute node was generated from the default value
3559 * defined in the DTD or schema.
3560 *
3561 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3562 */
3563int
3564xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3565 if (reader == NULL)
3566 return(-1);
3567 return(0);
3568}
3569
3570/**
3571 * xmlTextReaderQuoteChar:
3572 * @reader: the xmlTextReaderPtr used
3573 *
3574 * The quotation mark character used to enclose the value of an attribute.
3575 *
3576 * Returns " or ' and -1 in case of error
3577 */
3578int
3579xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3580 if (reader == NULL)
3581 return(-1);
3582 /* TODO maybe lookup the attribute value for " first */
3583 return((int) '"');
3584}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003585
3586/**
3587 * xmlTextReaderXmlLang:
3588 * @reader: the xmlTextReaderPtr used
3589 *
3590 * The xml:lang scope within which the node resides.
3591 *
3592 * Returns the xml:lang value or NULL if none exists.
3593 */
3594xmlChar *
3595xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3596 if (reader == NULL)
3597 return(NULL);
3598 if (reader->node == NULL)
3599 return(NULL);
3600 return(xmlNodeGetLang(reader->node));
3601}
3602
Daniel Veillard67df8092002-12-16 22:04:11 +00003603/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003604 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003605 * @reader: the xmlTextReaderPtr used
3606 *
3607 * The xml:lang scope within which the node resides.
3608 *
3609 * Returns the xml:lang value or NULL if none exists.
3610 */
3611const xmlChar *
3612xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3613 xmlChar *tmp;
3614 const xmlChar *ret;
3615
3616 if (reader == NULL)
3617 return(NULL);
3618 if (reader->node == NULL)
3619 return(NULL);
3620 tmp = xmlNodeGetLang(reader->node);
3621 if (tmp == NULL)
3622 return(NULL);
3623 ret = CONSTSTR(tmp);
3624 xmlFree(tmp);
3625 return(ret);
3626}
3627
3628/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003629 * xmlTextReaderConstString:
3630 * @reader: the xmlTextReaderPtr used
3631 * @str: the string to intern.
3632 *
3633 * Get an interned string from the reader, allows for example to
3634 * speedup string name comparisons
3635 *
3636 * Returns an interned copy of the string or NULL in case of error. The
3637 * string will be deallocated with the reader.
3638 */
3639const xmlChar *
3640xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3641 if (reader == NULL)
3642 return(NULL);
3643 return(CONSTSTR(str));
3644}
3645
3646/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003647 * xmlTextReaderNormalization:
3648 * @reader: the xmlTextReaderPtr used
3649 *
3650 * The value indicating whether to normalize white space and attribute values.
3651 * Since attribute value and end of line normalizations are a MUST in the XML
3652 * specification only the value true is accepted. The broken bahaviour of
3653 * accepting out of range character entities like &#0; is of course not
3654 * supported either.
3655 *
3656 * Returns 1 or -1 in case of error.
3657 */
3658int
3659xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3660 if (reader == NULL)
3661 return(-1);
3662 return(1);
3663}
3664
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003665/************************************************************************
3666 * *
3667 * Extensions to the base APIs *
3668 * *
3669 ************************************************************************/
3670
3671/**
3672 * xmlTextReaderSetParserProp:
3673 * @reader: the xmlTextReaderPtr used
3674 * @prop: the xmlParserProperties to set
3675 * @value: usually 0 or 1 to (de)activate it
3676 *
3677 * Change the parser processing behaviour by changing some of its internal
3678 * properties. Note that some properties can only be changed before any
3679 * read has been done.
3680 *
3681 * Returns 0 if the call was successful, or -1 in case of error
3682 */
3683int
3684xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3685 xmlParserProperties p = (xmlParserProperties) prop;
3686 xmlParserCtxtPtr ctxt;
3687
3688 if ((reader == NULL) || (reader->ctxt == NULL))
3689 return(-1);
3690 ctxt = reader->ctxt;
3691
3692 switch (p) {
3693 case XML_PARSER_LOADDTD:
3694 if (value != 0) {
3695 if (ctxt->loadsubset == 0) {
3696 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3697 return(-1);
3698 ctxt->loadsubset = XML_DETECT_IDS;
3699 }
3700 } else {
3701 ctxt->loadsubset = 0;
3702 }
3703 return(0);
3704 case XML_PARSER_DEFAULTATTRS:
3705 if (value != 0) {
3706 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3707 } else {
3708 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3709 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3710 }
3711 return(0);
3712 case XML_PARSER_VALIDATE:
3713 if (value != 0) {
3714 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003715 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003716 } else {
3717 ctxt->validate = 0;
3718 }
3719 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003720 case XML_PARSER_SUBST_ENTITIES:
3721 if (value != 0) {
3722 ctxt->replaceEntities = 1;
3723 } else {
3724 ctxt->replaceEntities = 0;
3725 }
3726 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003727 }
3728 return(-1);
3729}
3730
3731/**
3732 * xmlTextReaderGetParserProp:
3733 * @reader: the xmlTextReaderPtr used
3734 * @prop: the xmlParserProperties to get
3735 *
3736 * Read the parser internal property.
3737 *
3738 * Returns the value, usually 0 or 1, or -1 in case of error.
3739 */
3740int
3741xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3742 xmlParserProperties p = (xmlParserProperties) prop;
3743 xmlParserCtxtPtr ctxt;
3744
3745 if ((reader == NULL) || (reader->ctxt == NULL))
3746 return(-1);
3747 ctxt = reader->ctxt;
3748
3749 switch (p) {
3750 case XML_PARSER_LOADDTD:
3751 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3752 return(1);
3753 return(0);
3754 case XML_PARSER_DEFAULTATTRS:
3755 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3756 return(1);
3757 return(0);
3758 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003759 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003760 case XML_PARSER_SUBST_ENTITIES:
3761 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003762 }
3763 return(-1);
3764}
3765
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003766
Daniel Veillarde18fc182002-12-28 22:56:33 +00003767/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003768 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003769 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003770 *
3771 * Provide the line number of the current parsing point.
3772 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003773 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003774 */
3775int
3776xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3777{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003778 if ((reader == NULL) || (reader->ctxt == NULL) ||
3779 (reader->ctxt->input == NULL)) {
3780 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003781 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003782 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003783}
3784
3785/**
3786 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003787 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003788 *
3789 * Provide the column number of the current parsing point.
3790 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003791 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003792 */
3793int
3794xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3795{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003796 if ((reader == NULL) || (reader->ctxt == NULL) ||
3797 (reader->ctxt->input == NULL)) {
3798 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003799 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003800 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003801}
3802
3803/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003804 * xmlTextReaderCurrentNode:
3805 * @reader: the xmlTextReaderPtr used
3806 *
3807 * Hacking interface allowing to get the xmlNodePtr correponding to the
3808 * current node being accessed by the xmlTextReader. This is dangerous
3809 * because the underlying node may be destroyed on the next Reads.
3810 *
3811 * Returns the xmlNodePtr or NULL in case of error.
3812 */
3813xmlNodePtr
3814xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3815 if (reader == NULL)
3816 return(NULL);
3817
3818 if (reader->curnode != NULL)
3819 return(reader->curnode);
3820 return(reader->node);
3821}
3822
3823/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003824 * xmlTextReaderPreserve:
3825 * @reader: the xmlTextReaderPtr used
3826 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003827 * This tells the XML Reader to preserve the current node.
3828 * The caller must also use xmlTextReaderCurrentDoc() to
3829 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003830 *
3831 * Returns the xmlNodePtr or NULL in case of error.
3832 */
3833xmlNodePtr
3834xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3835 xmlNodePtr cur, parent;
3836
3837 if (reader == NULL)
3838 return(NULL);
3839
3840 if (reader->curnode != NULL)
3841 cur = reader->curnode;
3842 else
3843 cur = reader->node;
3844 if (cur == NULL)
3845 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003846
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003847 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003848 cur->extra |= NODE_IS_PRESERVED;
3849 cur->extra |= NODE_IS_SPRESERVED;
3850 }
3851 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003852
3853 parent = cur->parent;;
3854 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003855 if (parent->type == XML_ELEMENT_NODE)
3856 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003857 parent = parent->parent;
3858 }
3859 return(cur);
3860}
3861
Daniel Veillard1e906612003-12-05 14:57:46 +00003862#ifdef LIBXML_PATTERN_ENABLED
3863/**
3864 * xmlTextReaderPreservePattern:
3865 * @reader: the xmlTextReaderPtr used
3866 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003867 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003868 *
3869 * This tells the XML Reader to preserve all nodes matched by the
3870 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3871 * keep an handle on the resulting document once parsing has finished
3872 *
3873 * Returns a positive number in case of success and -1 in case of error
3874 */
3875int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003876xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3877 const xmlChar **namespaces)
3878{
Daniel Veillard1e906612003-12-05 14:57:46 +00003879 xmlPatternPtr comp;
3880
3881 if ((reader == NULL) || (pattern == NULL))
3882 return(-1);
3883
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003884 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003885 if (comp == NULL)
3886 return(-1);
3887
3888 if (reader->patternMax <= 0) {
3889 reader->patternMax = 4;
3890 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3891 sizeof(reader->patternTab[0]));
3892 if (reader->patternTab == NULL) {
3893 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3894 return (-1);
3895 }
3896 }
3897 if (reader->patternNr >= reader->patternMax) {
3898 xmlPatternPtr *tmp;
3899 reader->patternMax *= 2;
3900 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3901 reader->patternMax *
3902 sizeof(reader->patternTab[0]));
3903 if (tmp == NULL) {
3904 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3905 reader->patternMax /= 2;
3906 return (-1);
3907 }
3908 reader->patternTab = tmp;
3909 }
3910 reader->patternTab[reader->patternNr] = comp;
3911 return(reader->patternNr++);
3912}
3913#endif
3914
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003915/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003916 * xmlTextReaderCurrentDoc:
3917 * @reader: the xmlTextReaderPtr used
3918 *
3919 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003920 * current document being accessed by the xmlTextReader.
3921 * NOTE: as a result of this call, the reader will not destroy the
3922 * associated XML document and calling xmlFreeDoc() on the result
3923 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003924 *
3925 * Returns the xmlDocPtr or NULL in case of error.
3926 */
3927xmlDocPtr
3928xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003929 if (reader == NULL)
3930 return(NULL);
3931 if (reader->doc != NULL)
3932 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003933 if ((reader == NULL) || (reader->ctxt == NULL) ||
3934 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003935 return(NULL);
3936
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003937 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003938 return(reader->ctxt->myDoc);
3939}
3940
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003941#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003942
3943static char *
3944xmlTextReaderBuildMessage(const char *msg, va_list ap);
3945
Daniel Veillardffa3c742005-07-21 13:24:09 +00003946static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003947xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3948
Daniel Veillardffa3c742005-07-21 13:24:09 +00003949static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003950xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3951
Daniel Veillardffa3c742005-07-21 13:24:09 +00003952static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003953{
3954 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3955 char * str;
3956 va_list ap;
3957
3958 va_start(ap,msg);
3959 str = xmlTextReaderBuildMessage(msg,ap);
3960 if (!reader->errorFunc) {
3961 xmlTextReaderValidityError(ctx, "%s", str);
3962 } else {
3963 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3964 }
3965 if (str != NULL)
3966 xmlFree(str);
3967 va_end(ap);
3968}
3969
Daniel Veillardffa3c742005-07-21 13:24:09 +00003970static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003971{
3972 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3973 char * str;
3974 va_list ap;
3975
3976 va_start(ap,msg);
3977 str = xmlTextReaderBuildMessage(msg,ap);
3978 if (!reader->errorFunc) {
3979 xmlTextReaderValidityWarning(ctx, "%s", str);
3980 } else {
3981 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3982 }
3983 if (str != NULL)
3984 xmlFree(str);
3985 va_end(ap);
3986}
3987
3988static void
3989xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
3990
3991static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
3992{
3993 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
3994
3995 if (reader->sErrorFunc) {
3996 reader->sErrorFunc(reader->errorFuncArg, error);
3997 } else {
3998 xmlTextReaderStructuredError(reader, error);
3999 }
4000}
4001
Daniel Veillardf4e55762003-04-15 23:32:22 +00004002/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004003 * xmlTextReaderRelaxNGSetSchema:
4004 * @reader: the xmlTextReaderPtr used
4005 * @schema: a precompiled RelaxNG schema
4006 *
4007 * Use RelaxNG to validate the document as it is processed.
4008 * Activation is only possible before the first Read().
4009 * if @schema is NULL, then RelaxNG validation is desactivated.
4010 @ The @schema should not be freed until the reader is deallocated
4011 * or its use has been deactivated.
4012 *
4013 * Returns 0 in case the RelaxNG validation could be (des)activated and
4014 * -1 in case of error.
4015 */
4016int
4017xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004018 if (reader == NULL)
4019 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004020 if (schema == NULL) {
4021 if (reader->rngSchemas != NULL) {
4022 xmlRelaxNGFree(reader->rngSchemas);
4023 reader->rngSchemas = NULL;
4024 }
4025 if (reader->rngValidCtxt != NULL) {
4026 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4027 reader->rngValidCtxt = NULL;
4028 }
4029 return(0);
4030 }
4031 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4032 return(-1);
4033 if (reader->rngSchemas != NULL) {
4034 xmlRelaxNGFree(reader->rngSchemas);
4035 reader->rngSchemas = NULL;
4036 }
4037 if (reader->rngValidCtxt != NULL) {
4038 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4039 reader->rngValidCtxt = NULL;
4040 }
4041 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4042 if (reader->rngValidCtxt == NULL)
4043 return(-1);
4044 if (reader->errorFunc != NULL) {
4045 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004046 xmlTextReaderValidityErrorRelay,
4047 xmlTextReaderValidityWarningRelay,
4048 reader);
4049 }
4050 if (reader->sErrorFunc != NULL) {
4051 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4052 xmlTextReaderValidityStructuredRelay,
4053 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004054 }
4055 reader->rngValidErrors = 0;
4056 reader->rngFullNode = NULL;
4057 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4058 return(0);
4059}
4060
4061/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004062 * xmlTextReaderSetSchema:
4063 * @reader: the xmlTextReaderPtr used
4064 * @schema: a precompiled Schema schema
4065 *
4066 * Use XSD Schema to validate the document as it is processed.
4067 * Activation is only possible before the first Read().
4068 * if @schema is NULL, then Schema validation is desactivated.
4069 @ The @schema should not be freed until the reader is deallocated
4070 * or its use has been deactivated.
4071 *
4072 * Returns 0 in case the Schema validation could be (des)activated and
4073 * -1 in case of error.
4074 */
4075int
4076xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4077 if (reader == NULL)
4078 return(-1);
4079 if (schema == NULL) {
4080 if (reader->xsdPlug != NULL) {
4081 xmlSchemaSAXUnplug(reader->xsdPlug);
4082 reader->xsdPlug = NULL;
4083 }
4084 if (reader->xsdValidCtxt != NULL) {
4085 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4086 reader->xsdValidCtxt = NULL;
4087 }
4088 if (reader->xsdSchemas != NULL) {
4089 xmlSchemaFree(reader->xsdSchemas);
4090 reader->xsdSchemas = NULL;
4091 }
4092 return(0);
4093 }
4094 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4095 return(-1);
4096 if (reader->xsdPlug != NULL) {
4097 xmlSchemaSAXUnplug(reader->xsdPlug);
4098 reader->xsdPlug = NULL;
4099 }
4100 if (reader->xsdValidCtxt != NULL) {
4101 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4102 reader->xsdValidCtxt = NULL;
4103 }
4104 if (reader->xsdSchemas != NULL) {
4105 xmlSchemaFree(reader->xsdSchemas);
4106 reader->xsdSchemas = NULL;
4107 }
4108 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4109 if (reader->xsdValidCtxt == NULL) {
4110 xmlSchemaFree(reader->xsdSchemas);
4111 reader->xsdSchemas = NULL;
4112 return(-1);
4113 }
4114 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4115 &(reader->ctxt->sax),
4116 &(reader->ctxt->userData));
4117 if (reader->xsdPlug == NULL) {
4118 xmlSchemaFree(reader->xsdSchemas);
4119 reader->xsdSchemas = NULL;
4120 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4121 reader->xsdValidCtxt = NULL;
4122 return(-1);
4123 }
4124 if (reader->errorFunc != NULL) {
4125 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004126 xmlTextReaderValidityErrorRelay,
4127 xmlTextReaderValidityWarningRelay,
4128 reader);
4129 }
4130 if (reader->sErrorFunc != NULL) {
4131 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4132 xmlTextReaderValidityStructuredRelay,
4133 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004134 }
4135 reader->xsdValidErrors = 0;
4136 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4137 return(0);
4138}
4139
4140/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004141 * xmlTextReaderRelaxNGValidate:
4142 * @reader: the xmlTextReaderPtr used
4143 * @rng: the path to a RelaxNG schema or NULL
4144 *
4145 * Use RelaxNG to validate the document as it is processed.
4146 * Activation is only possible before the first Read().
4147 * if @rng is NULL, then RelaxNG validation is desactivated.
4148 *
4149 * Returns 0 in case the RelaxNG validation could be (des)activated and
4150 * -1 in case of error.
4151 */
4152int
4153xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4154 xmlRelaxNGParserCtxtPtr ctxt;
4155
4156 if (reader == NULL)
4157 return(-1);
4158
4159 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004160 if (reader->rngValidCtxt != NULL) {
4161 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4162 reader->rngValidCtxt = NULL;
4163 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004164 if (reader->rngSchemas != NULL) {
4165 xmlRelaxNGFree(reader->rngSchemas);
4166 reader->rngSchemas = NULL;
4167 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004168 return(0);
4169 }
4170 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4171 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004172 if (reader->rngSchemas != NULL) {
4173 xmlRelaxNGFree(reader->rngSchemas);
4174 reader->rngSchemas = NULL;
4175 }
4176 if (reader->rngValidCtxt != NULL) {
4177 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4178 reader->rngValidCtxt = NULL;
4179 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004180 ctxt = xmlRelaxNGNewParserCtxt(rng);
4181 if (reader->errorFunc != NULL) {
4182 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004183 xmlTextReaderValidityErrorRelay,
4184 xmlTextReaderValidityWarningRelay,
4185 reader);
4186 }
4187 if (reader->sErrorFunc != NULL) {
4188 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4189 xmlTextReaderValidityStructuredRelay,
4190 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004191 }
4192 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4193 xmlRelaxNGFreeParserCtxt(ctxt);
4194 if (reader->rngSchemas == NULL)
4195 return(-1);
4196 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004197 if (reader->rngValidCtxt == NULL) {
4198 xmlRelaxNGFree(reader->rngSchemas);
4199 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004200 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004201 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004202 if (reader->errorFunc != NULL) {
4203 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004204 xmlTextReaderValidityErrorRelay,
4205 xmlTextReaderValidityWarningRelay,
4206 reader);
4207 }
4208 if (reader->sErrorFunc != NULL) {
4209 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4210 xmlTextReaderValidityStructuredRelay,
4211 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004212 }
4213 reader->rngValidErrors = 0;
4214 reader->rngFullNode = NULL;
4215 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4216 return(0);
4217}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004218
4219/**
4220 * xmlTextReaderSchemaValidate:
4221 * @reader: the xmlTextReaderPtr used
4222 * @xsd: the path to a W3C XSD schema or NULL
4223 *
4224 * Use W3C XSD schema to validate the document as it is processed.
4225 * Activation is only possible before the first Read().
4226 * if @xsd is NULL, then RelaxNG validation is desactivated.
4227 *
4228 * Returns 0 in case the schemas validation could be (des)activated and
4229 * -1 in case of error.
4230 */
4231int
4232xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4233 xmlSchemaParserCtxtPtr ctxt;
4234
4235 if (reader == NULL)
4236 return(-1);
4237
4238 if (xsd == NULL) {
4239 if (reader->xsdPlug != NULL) {
4240 xmlSchemaSAXUnplug(reader->xsdPlug);
4241 reader->xsdPlug = NULL;
4242 }
4243 if (reader->xsdSchemas != NULL) {
4244 xmlSchemaFree(reader->xsdSchemas);
4245 reader->xsdSchemas = NULL;
4246 }
4247 if (reader->xsdValidCtxt != NULL) {
4248 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4249 reader->xsdValidCtxt = NULL;
4250 }
4251 return(0);
4252 }
4253 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4254 (reader->ctxt == NULL))
4255 return(-1);
4256 if (reader->xsdPlug != NULL) {
4257 xmlSchemaSAXUnplug(reader->xsdPlug);
4258 reader->xsdPlug = NULL;
4259 }
4260 if (reader->xsdValidCtxt != NULL) {
4261 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4262 reader->xsdValidCtxt = NULL;
4263 }
4264 if (reader->xsdSchemas != NULL) {
4265 xmlSchemaFree(reader->xsdSchemas);
4266 reader->xsdSchemas = NULL;
4267 }
4268 ctxt = xmlSchemaNewParserCtxt(xsd);
4269 if (reader->errorFunc != NULL) {
4270 xmlSchemaSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004271 xmlTextReaderValidityErrorRelay,
4272 xmlTextReaderValidityWarningRelay,
4273 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004274 }
4275 reader->xsdSchemas = xmlSchemaParse(ctxt);
4276 xmlSchemaFreeParserCtxt(ctxt);
4277 if (reader->xsdSchemas == NULL)
4278 return(-1);
4279 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4280 if (reader->xsdValidCtxt == NULL) {
4281 xmlSchemaFree(reader->xsdSchemas);
4282 reader->xsdSchemas = NULL;
4283 return(-1);
4284 }
4285 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4286 &(reader->ctxt->sax),
4287 &(reader->ctxt->userData));
4288 if (reader->xsdPlug == NULL) {
4289 xmlSchemaFree(reader->xsdSchemas);
4290 reader->xsdSchemas = NULL;
4291 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4292 reader->xsdValidCtxt = NULL;
4293 return(-1);
4294 }
4295 if (reader->errorFunc != NULL) {
4296 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004297 xmlTextReaderValidityErrorRelay,
4298 xmlTextReaderValidityWarningRelay,
4299 reader);
4300 }
4301 if (reader->sErrorFunc != NULL) {
4302 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4303 xmlTextReaderValidityStructuredRelay,
4304 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004305 }
4306 reader->xsdValidErrors = 0;
4307 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4308 return(0);
4309}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004310#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004311
Daniel Veillarde2811272004-10-19 09:04:23 +00004312/**
4313 * xmlTextReaderIsNamespaceDecl:
4314 * @reader: the xmlTextReaderPtr used
4315 *
4316 * Determine whether the current node is a namespace declaration
4317 * rather than a regular attribute.
4318 *
4319 * Returns 1 if the current node is a namespace declaration, 0 if it
4320 * is a regular attribute or other type of node, or -1 in case of
4321 * error.
4322 */
4323int
4324xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4325 xmlNodePtr node;
4326 if (reader == NULL)
4327 return(-1);
4328 if (reader->node == NULL)
4329 return(-1);
4330 if (reader->curnode != NULL)
4331 node = reader->curnode;
4332 else
4333 node = reader->node;
4334
4335 if (XML_NAMESPACE_DECL == node->type)
4336 return(1);
4337 else
4338 return(0);
4339}
4340
4341/**
4342 * xmlTextReaderConstXmlVersion:
4343 * @reader: the xmlTextReaderPtr used
4344 *
4345 * Determine the XML version of the document being read.
4346 *
4347 * Returns a string containing the XML version of the document or NULL
4348 * in case of error. The string is deallocated with the reader.
4349 */
4350const xmlChar *
4351xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4352 xmlDocPtr doc = NULL;
4353 if (reader == NULL)
4354 return(NULL);
4355 if (reader->doc != NULL)
4356 doc = reader->doc;
4357 else if (reader->ctxt != NULL)
4358 doc = reader->ctxt->myDoc;
4359 if (doc == NULL)
4360 return(NULL);
4361
4362 if (doc->version == NULL)
4363 return(NULL);
4364 else
4365 return(CONSTSTR(doc->version));
4366}
4367
4368/**
4369 * xmlTextReaderStandalone:
4370 * @reader: the xmlTextReaderPtr used
4371 *
4372 * Determine the standalone status of the document being read.
4373 *
4374 * Returns 1 if the document was declared to be standalone, 0 if it
4375 * was declared to be not standalone, or -1 if the document did not
4376 * specify its standalone status or in case of error.
4377 */
4378int
4379xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4380 xmlDocPtr doc = NULL;
4381 if (reader == NULL)
4382 return(-1);
4383 if (reader->doc != NULL)
4384 doc = reader->doc;
4385 else if (reader->ctxt != NULL)
4386 doc = reader->ctxt->myDoc;
4387 if (doc == NULL)
4388 return(-1);
4389
4390 return(doc->standalone);
4391}
4392
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004393/************************************************************************
4394 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004395 * Error Handling Extensions *
4396 * *
4397 ************************************************************************/
4398
4399/* helper to build a xmlMalloc'ed string from a format and va_list */
4400static char *
4401xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4402 int size;
4403 int chars;
4404 char *larger;
4405 char *str;
4406
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004407 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004408 if (str == NULL) {
4409 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4410 return NULL;
4411 }
4412
4413 size = 150;
4414
4415 while (1) {
4416 chars = vsnprintf(str, size, msg, ap);
4417 if ((chars > -1) && (chars < size))
4418 break;
4419 if (chars > -1)
4420 size += chars + 1;
4421 else
4422 size += 100;
4423 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4424 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4425 xmlFree(str);
4426 return NULL;
4427 }
4428 str = larger;
4429 }
4430
4431 return str;
4432}
4433
Daniel Veillard417be3a2003-01-20 21:26:34 +00004434/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004435 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004436 * @locator: the xmlTextReaderLocatorPtr used
4437 *
4438 * Obtain the line number for the given locator.
4439 *
4440 * Returns the line number or -1 in case of error.
4441 */
4442int
4443xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4444 /* we know that locator is a xmlParserCtxtPtr */
4445 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4446 int ret = -1;
4447
Daniel Veillardce682bc2004-11-05 17:22:25 +00004448 if (locator == NULL)
4449 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004450 if (ctx->node != NULL) {
4451 ret = xmlGetLineNo(ctx->node);
4452 }
4453 else {
4454 /* inspired from error.c */
4455 xmlParserInputPtr input;
4456 input = ctx->input;
4457 if ((input->filename == NULL) && (ctx->inputNr > 1))
4458 input = ctx->inputTab[ctx->inputNr - 2];
4459 if (input != NULL) {
4460 ret = input->line;
4461 }
4462 else {
4463 ret = -1;
4464 }
4465 }
4466
4467 return ret;
4468}
4469
4470/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004471 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004472 * @locator: the xmlTextReaderLocatorPtr used
4473 *
4474 * Obtain the base URI for the given locator.
4475 *
4476 * Returns the base URI or NULL in case of error.
4477 */
4478xmlChar *
4479xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4480 /* we know that locator is a xmlParserCtxtPtr */
4481 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4482 xmlChar *ret = NULL;
4483
Daniel Veillardce682bc2004-11-05 17:22:25 +00004484 if (locator == NULL)
4485 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004486 if (ctx->node != NULL) {
4487 ret = xmlNodeGetBase(NULL,ctx->node);
4488 }
4489 else {
4490 /* inspired from error.c */
4491 xmlParserInputPtr input;
4492 input = ctx->input;
4493 if ((input->filename == NULL) && (ctx->inputNr > 1))
4494 input = ctx->inputTab[ctx->inputNr - 2];
4495 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004496 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004497 }
4498 else {
4499 ret = NULL;
4500 }
4501 }
4502
4503 return ret;
4504}
4505
Daniel Veillard26f70262003-01-16 22:45:08 +00004506static void
William M. Brack899e64a2003-09-26 18:03:42 +00004507xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004508 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4509 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4510
William M. Bracka3215c72004-07-31 16:24:01 +00004511 if (str != NULL) {
4512 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004513 reader->errorFunc(reader->errorFuncArg,
4514 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004515 severity,
4516 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004517 xmlFree(str);
4518 }
4519}
4520
4521static void
William M. Brack93d004f2004-02-03 00:14:10 +00004522xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4523 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4524 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4525
4526 if (error && reader->sErrorFunc) {
4527 reader->sErrorFunc(reader->errorFuncArg,
4528 (xmlErrorPtr) error);
4529 }
4530}
4531
Daniel Veillardffa3c742005-07-21 13:24:09 +00004532static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004533xmlTextReaderError(void *ctxt, const char *msg, ...) {
4534 va_list ap;
4535
4536 va_start(ap,msg);
4537 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004538 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004539 xmlTextReaderBuildMessage(msg,ap));
4540 va_end(ap);
4541
4542}
4543
Daniel Veillardffa3c742005-07-21 13:24:09 +00004544static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004545xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4546 va_list ap;
4547
4548 va_start(ap,msg);
4549 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004550 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004551 xmlTextReaderBuildMessage(msg,ap));
4552 va_end(ap);
4553}
4554
Daniel Veillardffa3c742005-07-21 13:24:09 +00004555static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004556xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4557 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004558 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004559
Daniel Veillard417be3a2003-01-20 21:26:34 +00004560 if ((len > 1) && (msg[len - 2] != ':')) {
4561 /*
4562 * some callbacks only report locator information:
4563 * skip them (mimicking behaviour in error.c)
4564 */
4565 va_start(ap,msg);
4566 xmlTextReaderGenericError(ctxt,
4567 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4568 xmlTextReaderBuildMessage(msg,ap));
4569 va_end(ap);
4570 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004571}
4572
Daniel Veillardffa3c742005-07-21 13:24:09 +00004573static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004574xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4575 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004576 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004577
Daniel Veillard417be3a2003-01-20 21:26:34 +00004578 if ((len != 0) && (msg[len - 1] != ':')) {
4579 /*
4580 * some callbacks only report locator information:
4581 * skip them (mimicking behaviour in error.c)
4582 */
4583 va_start(ap,msg);
4584 xmlTextReaderGenericError(ctxt,
4585 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4586 xmlTextReaderBuildMessage(msg,ap));
4587 va_end(ap);
4588 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004589}
4590
4591/**
4592 * xmlTextReaderSetErrorHandler:
4593 * @reader: the xmlTextReaderPtr used
4594 * @f: the callback function to call on error and warnings
4595 * @arg: a user argument to pass to the callback function
4596 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004597 * Register a callback function that will be called on error and warnings.
4598 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004599 * If @f is NULL, the default error and warning handlers are restored.
4600 */
4601void
4602xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4603 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004604 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004605 if (f != NULL) {
4606 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004607 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004608 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4609 reader->ctxt->sax->warning = xmlTextReaderWarning;
4610 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4611 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004612 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004613 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004614#ifdef LIBXML_SCHEMAS_ENABLED
4615 if (reader->rngValidCtxt) {
4616 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4617 xmlTextReaderValidityErrorRelay,
4618 xmlTextReaderValidityWarningRelay,
4619 reader);
4620 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4621 }
4622 if (reader->xsdValidCtxt) {
4623 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4624 xmlTextReaderValidityErrorRelay,
4625 xmlTextReaderValidityWarningRelay,
4626 reader);
4627 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4628 }
4629#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004630 }
4631 else {
4632 /* restore defaults */
4633 reader->ctxt->sax->error = xmlParserError;
4634 reader->ctxt->vctxt.error = xmlParserValidityError;
4635 reader->ctxt->sax->warning = xmlParserWarning;
4636 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4637 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004638 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004639 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004640#ifdef LIBXML_SCHEMAS_ENABLED
4641 if (reader->rngValidCtxt) {
4642 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4643 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4644 }
4645 if (reader->xsdValidCtxt) {
4646 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4647 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4648 }
4649#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004650 }
4651}
4652
Daniel Veillard417be3a2003-01-20 21:26:34 +00004653/**
William M. Brack93d004f2004-02-03 00:14:10 +00004654* xmlTextReaderSetStructuredErrorHandler:
4655 * @reader: the xmlTextReaderPtr used
4656 * @f: the callback function to call on error and warnings
4657 * @arg: a user argument to pass to the callback function
4658 *
4659 * Register a callback function that will be called on error and warnings.
4660 *
4661 * If @f is NULL, the default error and warning handlers are restored.
4662 */
4663void
4664xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4665 xmlStructuredErrorFunc f,
4666 void *arg) {
4667 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004668 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004669 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4670 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4671 reader->ctxt->sax->warning = xmlTextReaderWarning;
4672 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4673 reader->sErrorFunc = f;
4674 reader->errorFunc = NULL;
4675 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004676#ifdef LIBXML_SCHEMAS_ENABLED
4677 if (reader->rngValidCtxt) {
4678 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4679 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4680 xmlTextReaderValidityStructuredRelay,
4681 reader);
4682 }
4683 if (reader->xsdValidCtxt) {
4684 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4685 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4686 xmlTextReaderValidityStructuredRelay,
4687 reader);
4688 }
4689#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004690 }
4691 else {
4692 /* restore defaults */
4693 reader->ctxt->sax->error = xmlParserError;
4694 reader->ctxt->sax->serror = NULL;
4695 reader->ctxt->vctxt.error = xmlParserValidityError;
4696 reader->ctxt->sax->warning = xmlParserWarning;
4697 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4698 reader->errorFunc = NULL;
4699 reader->sErrorFunc = NULL;
4700 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004701#ifdef LIBXML_SCHEMAS_ENABLED
4702 if (reader->rngValidCtxt) {
4703 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4704 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4705 }
4706 if (reader->xsdValidCtxt) {
4707 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4708 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4709 }
4710#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004711 }
4712}
4713
4714/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004715 * xmlTextReaderIsValid:
4716 * @reader: the xmlTextReaderPtr used
4717 *
4718 * Retrieve the validity status from the parser context
4719 *
4720 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4721 */
4722int
4723xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004724 if (reader == NULL) return(-1);
4725#ifdef LIBXML_SCHEMAS_ENABLED
4726 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4727 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004728 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4729 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004730#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004731 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004732 return(reader->ctxt->valid);
4733 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004734}
4735
4736/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004737 * xmlTextReaderGetErrorHandler:
4738 * @reader: the xmlTextReaderPtr used
4739 * @f: the callback function or NULL is no callback has been registered
4740 * @arg: a user argument
4741 *
4742 * Retrieve the error callback function and user argument.
4743 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004744void
4745xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4746 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004747 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004748 if (f != NULL) *f = reader->errorFunc;
4749 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004750}
4751
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004752
4753/************************************************************************
4754 * *
4755 * New set (2.6.0) of simpler and more flexible APIs *
4756 * *
4757 ************************************************************************/
4758
4759/**
4760 * xmlTextReaderSetup:
4761 * @reader: an XML reader
4762 * @URL: the base URL to use for the document
4763 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004764 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004765 * @reuse: keep the context for reuse
4766 *
4767 * Setup an XML reader with new options
4768 *
4769 * Returns 0 in case of success and -1 in case of error.
4770 */
4771static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004772xmlTextReaderSetup(xmlTextReaderPtr reader,
4773 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004774 const char *encoding, int options)
4775{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004776 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004777 return (-1);
4778
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004779 reader->doc = NULL;
4780 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004781 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004782 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004783 if ((input != NULL) && (reader->input != NULL) &&
4784 (reader->allocs & XML_TEXTREADER_INPUT)) {
4785 xmlFreeParserInputBuffer(reader->input);
4786 reader->input = NULL;
4787 reader->allocs -= XML_TEXTREADER_INPUT;
4788 }
4789 if (input != NULL) {
4790 reader->input = input;
4791 reader->allocs |= XML_TEXTREADER_INPUT;
4792 }
4793 if (reader->buffer == NULL)
4794 reader->buffer = xmlBufferCreateSize(100);
4795 if (reader->buffer == NULL) {
4796 xmlGenericError(xmlGenericErrorContext,
4797 "xmlTextReaderSetup : malloc failed\n");
4798 return (-1);
4799 }
4800 if (reader->sax == NULL)
4801 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4802 if (reader->sax == NULL) {
4803 xmlGenericError(xmlGenericErrorContext,
4804 "xmlTextReaderSetup : malloc failed\n");
4805 return (-1);
4806 }
4807 xmlSAXVersion(reader->sax, 2);
4808 reader->startElement = reader->sax->startElement;
4809 reader->sax->startElement = xmlTextReaderStartElement;
4810 reader->endElement = reader->sax->endElement;
4811 reader->sax->endElement = xmlTextReaderEndElement;
4812#ifdef LIBXML_SAX1_ENABLED
4813 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4814#endif /* LIBXML_SAX1_ENABLED */
4815 reader->startElementNs = reader->sax->startElementNs;
4816 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4817 reader->endElementNs = reader->sax->endElementNs;
4818 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4819#ifdef LIBXML_SAX1_ENABLED
4820 } else {
4821 reader->startElementNs = NULL;
4822 reader->endElementNs = NULL;
4823 }
4824#endif /* LIBXML_SAX1_ENABLED */
4825 reader->characters = reader->sax->characters;
4826 reader->sax->characters = xmlTextReaderCharacters;
4827 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4828 reader->cdataBlock = reader->sax->cdataBlock;
4829 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4830
4831 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4832 reader->node = NULL;
4833 reader->curnode = NULL;
4834 if (input != NULL) {
4835 if (reader->input->buffer->use < 4) {
4836 xmlParserInputBufferRead(input, 4);
4837 }
4838 if (reader->ctxt == NULL) {
4839 if (reader->input->buffer->use >= 4) {
4840 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4841 (const char *) reader->input->buffer->content, 4, URL);
4842 reader->base = 0;
4843 reader->cur = 4;
4844 } else {
4845 reader->ctxt =
4846 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4847 reader->base = 0;
4848 reader->cur = 0;
4849 }
4850 } else {
4851 xmlParserInputPtr inputStream;
4852 xmlParserInputBufferPtr buf;
4853 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4854
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004855 xmlCtxtReset(reader->ctxt);
4856 buf = xmlAllocParserInputBuffer(enc);
4857 if (buf == NULL) return(-1);
4858 inputStream = xmlNewInputStream(reader->ctxt);
4859 if (inputStream == NULL) {
4860 xmlFreeParserInputBuffer(buf);
4861 return(-1);
4862 }
4863
4864 if (URL == NULL)
4865 inputStream->filename = NULL;
4866 else
4867 inputStream->filename = (char *)
4868 xmlCanonicPath((const xmlChar *) URL);
4869 inputStream->buf = buf;
4870 inputStream->base = inputStream->buf->buffer->content;
4871 inputStream->cur = inputStream->buf->buffer->content;
4872 inputStream->end =
4873 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4874
4875 inputPush(reader->ctxt, inputStream);
4876 reader->cur = 0;
4877 }
4878 if (reader->ctxt == NULL) {
4879 xmlGenericError(xmlGenericErrorContext,
4880 "xmlTextReaderSetup : malloc failed\n");
4881 return (-1);
4882 }
4883 }
4884 if (reader->dict != NULL) {
4885 if (reader->ctxt->dict != NULL) {
4886 if (reader->dict != reader->ctxt->dict) {
4887 xmlDictFree(reader->dict);
4888 reader->dict = reader->ctxt->dict;
4889 }
4890 } else {
4891 reader->ctxt->dict = reader->dict;
4892 }
4893 } else {
4894 if (reader->ctxt->dict == NULL)
4895 reader->ctxt->dict = xmlDictCreate();
4896 reader->dict = reader->ctxt->dict;
4897 }
4898 reader->ctxt->_private = reader;
4899 reader->ctxt->linenumbers = 1;
4900 reader->ctxt->dictNames = 1;
4901 /*
4902 * use the parser dictionnary to allocate all elements and attributes names
4903 */
4904 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004905 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004906
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004907#ifdef LIBXML_XINCLUDE_ENABLED
4908 if (reader->xincctxt != NULL) {
4909 xmlXIncludeFreeContext(reader->xincctxt);
4910 reader->xincctxt = NULL;
4911 }
4912 if (options & XML_PARSE_XINCLUDE) {
4913 reader->xinclude = 1;
4914 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4915 options -= XML_PARSE_XINCLUDE;
4916 } else
4917 reader->xinclude = 0;
4918 reader->in_xinclude = 0;
4919#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004920#ifdef LIBXML_PATTERN_ENABLED
4921 if (reader->patternTab == NULL) {
4922 reader->patternNr = 0;
4923 reader->patternMax = 0;
4924 }
4925 while (reader->patternNr > 0) {
4926 reader->patternNr--;
4927 if (reader->patternTab[reader->patternNr] != NULL) {
4928 xmlFreePattern(reader->patternTab[reader->patternNr]);
4929 reader->patternTab[reader->patternNr] = NULL;
4930 }
4931 }
4932#endif
4933
Daniel Veillardc36965d2003-12-02 10:28:48 +00004934 if (options & XML_PARSE_DTDVALID)
4935 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4936
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004937 xmlCtxtUseOptions(reader->ctxt, options);
4938 if (encoding != NULL) {
4939 xmlCharEncodingHandlerPtr hdlr;
4940
4941 hdlr = xmlFindCharEncodingHandler(encoding);
4942 if (hdlr != NULL)
4943 xmlSwitchToEncoding(reader->ctxt, hdlr);
4944 }
4945 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4946 (reader->ctxt->input->filename == NULL))
4947 reader->ctxt->input->filename = (char *)
4948 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004949
4950 reader->doc = NULL;
4951
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004952 return (0);
4953}
4954
4955/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004956 * xmlTextReaderByteConsumed:
4957 * @reader: an XML reader
4958 *
4959 * This function provides the current index of the parser used
4960 * by the reader, relative to the start of the current entity.
4961 * This function actually just wraps a call to xmlBytesConsumed()
4962 * for the parser context associated with the reader.
4963 * See xmlBytesConsumed() for more information.
4964 *
4965 * Returns the index in bytes from the beginning of the entity or -1
4966 * in case the index could not be computed.
4967 */
4968long
4969xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4970 if ((reader == NULL) || (reader->ctxt == NULL))
4971 return(-1);
4972 return(xmlByteConsumed(reader->ctxt));
4973}
4974
4975
4976/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004977 * xmlReaderWalker:
4978 * @doc: a preparsed document
4979 *
4980 * Create an xmltextReader for a preparsed document.
4981 *
4982 * Returns the new reader or NULL in case of error.
4983 */
4984xmlTextReaderPtr
4985xmlReaderWalker(xmlDocPtr doc)
4986{
4987 xmlTextReaderPtr ret;
4988
4989 if (doc == NULL)
4990 return(NULL);
4991
4992 ret = xmlMalloc(sizeof(xmlTextReader));
4993 if (ret == NULL) {
4994 xmlGenericError(xmlGenericErrorContext,
4995 "xmlNewTextReader : malloc failed\n");
4996 return(NULL);
4997 }
4998 memset(ret, 0, sizeof(xmlTextReader));
4999 ret->entNr = 0;
5000 ret->input = NULL;
5001 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5002 ret->node = NULL;
5003 ret->curnode = NULL;
5004 ret->base = 0;
5005 ret->cur = 0;
5006 ret->allocs = XML_TEXTREADER_CTXT;
5007 ret->doc = doc;
5008 ret->state = XML_TEXTREADER_START;
5009 ret->dict = xmlDictCreate();
5010 return(ret);
5011}
5012
5013/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005014 * xmlReaderForDoc:
5015 * @cur: a pointer to a zero terminated string
5016 * @URL: the base URL to use for the document
5017 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005018 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005019 *
5020 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005021 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005022 *
5023 * Returns the new reader or NULL in case of error.
5024 */
5025xmlTextReaderPtr
5026xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5027 int options)
5028{
5029 int len;
5030
5031 if (cur == NULL)
5032 return (NULL);
5033 len = xmlStrlen(cur);
5034
5035 return (xmlReaderForMemory
5036 ((const char *) cur, len, URL, encoding, options));
5037}
5038
5039/**
5040 * xmlReaderForFile:
5041 * @filename: a file or URL
5042 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005043 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005044 *
5045 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005046 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005047 *
5048 * Returns the new reader or NULL in case of error.
5049 */
5050xmlTextReaderPtr
5051xmlReaderForFile(const char *filename, const char *encoding, int options)
5052{
5053 xmlTextReaderPtr reader;
5054
5055 reader = xmlNewTextReaderFilename(filename);
5056 if (reader == NULL)
5057 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005058 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005059 return (reader);
5060}
5061
5062/**
5063 * xmlReaderForMemory:
5064 * @buffer: a pointer to a char array
5065 * @size: the size of the array
5066 * @URL: the base URL to use for the document
5067 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005068 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005069 *
5070 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005071 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005072 *
5073 * Returns the new reader or NULL in case of error.
5074 */
5075xmlTextReaderPtr
5076xmlReaderForMemory(const char *buffer, int size, const char *URL,
5077 const char *encoding, int options)
5078{
5079 xmlTextReaderPtr reader;
5080 xmlParserInputBufferPtr buf;
5081
Daniel Veillard21924522004-02-19 16:37:07 +00005082 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005083 XML_CHAR_ENCODING_NONE);
5084 if (buf == NULL) {
5085 return (NULL);
5086 }
5087 reader = xmlNewTextReader(buf, URL);
5088 if (reader == NULL) {
5089 xmlFreeParserInputBuffer(buf);
5090 return (NULL);
5091 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005092 reader->allocs |= XML_TEXTREADER_INPUT;
5093 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005094 return (reader);
5095}
5096
5097/**
5098 * xmlReaderForFd:
5099 * @fd: an open file descriptor
5100 * @URL: the base URL to use for the document
5101 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005102 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005103 *
5104 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005105 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005106 * NOTE that the file descriptor will not be closed when the
5107 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005108 *
5109 * Returns the new reader or NULL in case of error.
5110 */
5111xmlTextReaderPtr
5112xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5113{
5114 xmlTextReaderPtr reader;
5115 xmlParserInputBufferPtr input;
5116
5117 if (fd < 0)
5118 return (NULL);
5119
5120 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5121 if (input == NULL)
5122 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005123 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005124 reader = xmlNewTextReader(input, URL);
5125 if (reader == NULL) {
5126 xmlFreeParserInputBuffer(input);
5127 return (NULL);
5128 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005129 reader->allocs |= XML_TEXTREADER_INPUT;
5130 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005131 return (reader);
5132}
5133
5134/**
5135 * xmlReaderForIO:
5136 * @ioread: an I/O read function
5137 * @ioclose: an I/O close function
5138 * @ioctx: an I/O handler
5139 * @URL: the base URL to use for the document
5140 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005141 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005142 *
5143 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005144 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005145 *
5146 * Returns the new reader or NULL in case of error.
5147 */
5148xmlTextReaderPtr
5149xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5150 void *ioctx, const char *URL, const char *encoding,
5151 int options)
5152{
5153 xmlTextReaderPtr reader;
5154 xmlParserInputBufferPtr input;
5155
5156 if (ioread == NULL)
5157 return (NULL);
5158
5159 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5160 XML_CHAR_ENCODING_NONE);
5161 if (input == NULL)
5162 return (NULL);
5163 reader = xmlNewTextReader(input, URL);
5164 if (reader == NULL) {
5165 xmlFreeParserInputBuffer(input);
5166 return (NULL);
5167 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005168 reader->allocs |= XML_TEXTREADER_INPUT;
5169 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005170 return (reader);
5171}
5172
5173/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005174 * xmlReaderNewWalker:
5175 * @reader: an XML reader
5176 * @doc: a preparsed document
5177 *
5178 * Setup an xmltextReader to parse a preparsed XML document.
5179 * This reuses the existing @reader xmlTextReader.
5180 *
5181 * Returns 0 in case of success and -1 in case of error
5182 */
5183int
5184xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5185{
5186 if (doc == NULL)
5187 return (-1);
5188 if (reader == NULL)
5189 return (-1);
5190
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005191 if (reader->input != NULL) {
5192 xmlFreeParserInputBuffer(reader->input);
5193 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005194 if (reader->ctxt != NULL) {
5195 xmlCtxtReset(reader->ctxt);
5196 }
5197
5198 reader->entNr = 0;
5199 reader->input = NULL;
5200 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5201 reader->node = NULL;
5202 reader->curnode = NULL;
5203 reader->base = 0;
5204 reader->cur = 0;
5205 reader->allocs = XML_TEXTREADER_CTXT;
5206 reader->doc = doc;
5207 reader->state = XML_TEXTREADER_START;
5208 if (reader->dict == NULL) {
5209 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5210 reader->dict = reader->ctxt->dict;
5211 else
5212 reader->dict = xmlDictCreate();
5213 }
5214 return(0);
5215}
5216
5217/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005218 * xmlReaderNewDoc:
5219 * @reader: an XML reader
5220 * @cur: a pointer to a zero terminated string
5221 * @URL: the base URL to use for the document
5222 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005223 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005224 *
5225 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005226 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005227 * This reuses the existing @reader xmlTextReader.
5228 *
5229 * Returns 0 in case of success and -1 in case of error
5230 */
5231int
5232xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5233 const char *URL, const char *encoding, int options)
5234{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005235
5236 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005237
5238 if (cur == NULL)
5239 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005240 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005241 return (-1);
5242
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005243 len = xmlStrlen(cur);
5244 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5245 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005246}
5247
5248/**
5249 * xmlReaderNewFile:
5250 * @reader: an XML reader
5251 * @filename: a file or URL
5252 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005253 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005254 *
5255 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005256 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005257 * This reuses the existing @reader xmlTextReader.
5258 *
5259 * Returns 0 in case of success and -1 in case of error
5260 */
5261int
5262xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5263 const char *encoding, int options)
5264{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005265 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005266
5267 if (filename == NULL)
5268 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005269 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005270 return (-1);
5271
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005272 input =
5273 xmlParserInputBufferCreateFilename(filename,
5274 XML_CHAR_ENCODING_NONE);
5275 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005276 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005277 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005278}
5279
5280/**
5281 * xmlReaderNewMemory:
5282 * @reader: an XML reader
5283 * @buffer: a pointer to a char array
5284 * @size: the size of the array
5285 * @URL: the base URL to use for the document
5286 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005287 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005288 *
5289 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005290 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005291 * This reuses the existing @reader xmlTextReader.
5292 *
5293 * Returns 0 in case of success and -1 in case of error
5294 */
5295int
5296xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5297 const char *URL, const char *encoding, int options)
5298{
5299 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005300
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005301 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005302 return (-1);
5303 if (buffer == NULL)
5304 return (-1);
5305
Daniel Veillard21924522004-02-19 16:37:07 +00005306 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005307 XML_CHAR_ENCODING_NONE);
5308 if (input == NULL) {
5309 return (-1);
5310 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005311 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005312}
5313
5314/**
5315 * xmlReaderNewFd:
5316 * @reader: an XML reader
5317 * @fd: an open file descriptor
5318 * @URL: the base URL to use for the document
5319 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005320 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005321 *
5322 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005323 * NOTE that the file descriptor will not be closed when the
5324 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005325 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005326 * This reuses the existing @reader xmlTextReader.
5327 *
5328 * Returns 0 in case of success and -1 in case of error
5329 */
5330int
5331xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5332 const char *URL, const char *encoding, int options)
5333{
5334 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005335
5336 if (fd < 0)
5337 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005338 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005339 return (-1);
5340
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005341 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5342 if (input == NULL)
5343 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005344 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005345 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005346}
5347
5348/**
5349 * xmlReaderNewIO:
5350 * @reader: an XML reader
5351 * @ioread: an I/O read function
5352 * @ioclose: an I/O close function
5353 * @ioctx: an I/O handler
5354 * @URL: the base URL to use for the document
5355 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005356 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005357 *
5358 * Setup an xmltextReader to parse an XML document from I/O functions
5359 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005360 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005361 * This reuses the existing @reader xmlTextReader.
5362 *
5363 * Returns 0 in case of success and -1 in case of error
5364 */
5365int
5366xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5367 xmlInputCloseCallback ioclose, void *ioctx,
5368 const char *URL, const char *encoding, int options)
5369{
5370 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005371
5372 if (ioread == NULL)
5373 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005374 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005375 return (-1);
5376
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5378 XML_CHAR_ENCODING_NONE);
5379 if (input == NULL)
5380 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005381 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005382}
Daniel Veillard26f70262003-01-16 22:45:08 +00005383/************************************************************************
5384 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005385 * Utilities *
5386 * *
5387 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005388#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005389/**
5390 * xmlBase64Decode:
5391 * @in: the input buffer
5392 * @inlen: the size of the input (in), the size read from it (out)
5393 * @to: the output buffer
5394 * @tolen: the size of the output (in), the size written to (out)
5395 *
5396 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005397 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005398 *
5399 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5400 * 2 if there wasn't enough space on the output or -1 in case of error.
5401 */
5402static int
5403xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5404 unsigned char *to, unsigned long *tolen) {
5405 unsigned long incur; /* current index in in[] */
5406 unsigned long inblk; /* last block index in in[] */
5407 unsigned long outcur; /* current index in out[] */
5408 unsigned long inmax; /* size of in[] */
5409 unsigned long outmax; /* size of out[] */
5410 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005411 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005412 int nbintmp; /* number of byte in intmp[] */
5413 int is_ignore; /* cur should be ignored */
5414 int is_end = 0; /* the end of the base64 was found */
5415 int retval = 1;
5416 int i;
5417
5418 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5419 return(-1);
5420
5421 incur = 0;
5422 inblk = 0;
5423 outcur = 0;
5424 inmax = *inlen;
5425 outmax = *tolen;
5426 nbintmp = 0;
5427
5428 while (1) {
5429 if (incur >= inmax)
5430 break;
5431 cur = in[incur++];
5432 is_ignore = 0;
5433 if ((cur >= 'A') && (cur <= 'Z'))
5434 cur = cur - 'A';
5435 else if ((cur >= 'a') && (cur <= 'z'))
5436 cur = cur - 'a' + 26;
5437 else if ((cur >= '0') && (cur <= '9'))
5438 cur = cur - '0' + 52;
5439 else if (cur == '+')
5440 cur = 62;
5441 else if (cur == '/')
5442 cur = 63;
5443 else if (cur == '.')
5444 cur = 0;
5445 else if (cur == '=') /*no op , end of the base64 stream */
5446 is_end = 1;
5447 else {
5448 is_ignore = 1;
5449 if (nbintmp == 0)
5450 inblk = incur;
5451 }
5452
5453 if (!is_ignore) {
5454 int nbouttmp = 3;
5455 int is_break = 0;
5456
5457 if (is_end) {
5458 if (nbintmp == 0)
5459 break;
5460 if ((nbintmp == 1) || (nbintmp == 2))
5461 nbouttmp = 1;
5462 else
5463 nbouttmp = 2;
5464 nbintmp = 3;
5465 is_break = 1;
5466 }
5467 intmp[nbintmp++] = cur;
5468 /*
5469 * if intmp is full, push the 4byte sequence as a 3 byte
5470 * sequence out
5471 */
5472 if (nbintmp == 4) {
5473 nbintmp = 0;
5474 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5475 outtmp[1] =
5476 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5477 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5478 if (outcur + 3 >= outmax) {
5479 retval = 2;
5480 break;
5481 }
5482
5483 for (i = 0; i < nbouttmp; i++)
5484 to[outcur++] = outtmp[i];
5485 inblk = incur;
5486 }
5487
5488 if (is_break) {
5489 retval = 0;
5490 break;
5491 }
5492 }
5493 }
5494
5495 *tolen = outcur;
5496 *inlen = inblk;
5497 return (retval);
5498}
5499
5500/*
5501 * Test routine for the xmlBase64Decode function
5502 */
5503#if 0
5504int main(int argc, char **argv) {
5505 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5506 char output[100];
5507 char output2[100];
5508 char output3[100];
5509 unsigned long inlen = strlen(input);
5510 unsigned long outlen = 100;
5511 int ret;
5512 unsigned long cons, tmp, tmp2, prod;
5513
5514 /*
5515 * Direct
5516 */
5517 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5518
5519 output[outlen] = 0;
5520 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5521
5522 /*
5523 * output chunking
5524 */
5525 cons = 0;
5526 prod = 0;
5527 while (cons < inlen) {
5528 tmp = 5;
5529 tmp2 = inlen - cons;
5530
5531 printf("%ld %ld\n", cons, prod);
5532 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5533 cons += tmp2;
5534 prod += tmp;
5535 printf("%ld %ld\n", cons, prod);
5536 }
5537 output2[outlen] = 0;
5538 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5539
5540 /*
5541 * input chunking
5542 */
5543 cons = 0;
5544 prod = 0;
5545 while (cons < inlen) {
5546 tmp = 100 - prod;
5547 tmp2 = inlen - cons;
5548 if (tmp2 > 5)
5549 tmp2 = 5;
5550
5551 printf("%ld %ld\n", cons, prod);
5552 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5553 cons += tmp2;
5554 prod += tmp;
5555 printf("%ld %ld\n", cons, prod);
5556 }
5557 output3[outlen] = 0;
5558 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5559 return(0);
5560
5561}
5562#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005563#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005564#define bottom_xmlreader
5565#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005566#endif /* LIBXML_READER_ENABLED */