blob: a74c7a61e66c4717be91eb545e477092e25a463a [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);
Daniel Veillard8874b942005-08-25 13:19:21 +0000351 if ((cur->content != (xmlChar *) &(cur->properties)) &&
352 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000353 (cur->type != XML_XINCLUDE_START) &&
354 (cur->type != XML_XINCLUDE_END) &&
355 (cur->type != XML_ENTITY_REF_NODE)) {
356 DICT_FREE(cur->content);
357 }
358 if (((cur->type == XML_ELEMENT_NODE) ||
359 (cur->type == XML_XINCLUDE_START) ||
360 (cur->type == XML_XINCLUDE_END)) &&
361 (cur->nsDef != NULL))
362 xmlFreeNsList(cur->nsDef);
363
364 /*
365 * we don't free element names here they are interned now
366 */
367 if ((cur->type != XML_TEXT_NODE) &&
368 (cur->type != XML_COMMENT_NODE))
369 DICT_FREE(cur->name);
370 if (((cur->type == XML_ELEMENT_NODE) ||
371 (cur->type == XML_TEXT_NODE)) &&
372 (reader != NULL) && (reader->ctxt != NULL) &&
373 (reader->ctxt->freeElemsNr < 100)) {
374 cur->next = reader->ctxt->freeElems;
375 reader->ctxt->freeElems = cur;
376 reader->ctxt->freeElemsNr++;
377 } else {
378 xmlFree(cur);
379 }
380 }
381 cur = next;
382 }
383}
384
385/**
386 * xmlTextReaderFreeNode:
387 * @reader: the xmlTextReaderPtr used
388 * @cur: the node
389 *
390 * Free a node, this is a recursive behaviour, all the children are freed too.
391 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
392 */
393static void
394xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
395 xmlDictPtr dict;
396
397 dict = reader->ctxt->dict;
398 if (cur->type == XML_DTD_NODE) {
399 xmlFreeDtd((xmlDtdPtr) cur);
400 return;
401 }
402 if (cur->type == XML_NAMESPACE_DECL) {
403 xmlFreeNs((xmlNsPtr) cur);
404 return;
405 }
406 if (cur->type == XML_ATTRIBUTE_NODE) {
407 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
408 return;
409 }
410
411 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000412 (cur->type != XML_ENTITY_REF_NODE)) {
413 if (cur->children->parent == cur)
414 xmlTextReaderFreeNodeList(reader, cur->children);
415 cur->children = NULL;
416 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000417
418 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
419 xmlDeregisterNodeDefaultValue(cur);
420
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000421 if (((cur->type == XML_ELEMENT_NODE) ||
422 (cur->type == XML_XINCLUDE_START) ||
423 (cur->type == XML_XINCLUDE_END)) &&
424 (cur->properties != NULL))
425 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000426 if ((cur->content != (xmlChar *) &(cur->properties)) &&
427 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000428 (cur->type != XML_XINCLUDE_START) &&
429 (cur->type != XML_XINCLUDE_END) &&
430 (cur->type != XML_ENTITY_REF_NODE)) {
431 DICT_FREE(cur->content);
432 }
433 if (((cur->type == XML_ELEMENT_NODE) ||
434 (cur->type == XML_XINCLUDE_START) ||
435 (cur->type == XML_XINCLUDE_END)) &&
436 (cur->nsDef != NULL))
437 xmlFreeNsList(cur->nsDef);
438
439 /*
440 * we don't free names here they are interned now
441 */
442 if ((cur->type != XML_TEXT_NODE) &&
443 (cur->type != XML_COMMENT_NODE))
444 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000445
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000446 if (((cur->type == XML_ELEMENT_NODE) ||
447 (cur->type == XML_TEXT_NODE)) &&
448 (reader != NULL) && (reader->ctxt != NULL) &&
449 (reader->ctxt->freeElemsNr < 100)) {
450 cur->next = reader->ctxt->freeElems;
451 reader->ctxt->freeElems = cur;
452 reader->ctxt->freeElemsNr++;
453 } else {
454 xmlFree(cur);
455 }
456}
457
458/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000459 * xmlTextReaderFreeIDTable:
460 * @table: An id table
461 *
462 * Deallocate the memory used by an ID hash table.
463 */
William M. Brack60f394e2003-11-16 06:25:42 +0000464static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000465xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
466 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
467}
468
469/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000470 * xmlTextReaderFreeDoc:
471 * @reader: the xmlTextReaderPtr used
472 * @cur: pointer to the document
473 *
474 * Free up all the structures used by a document, tree included.
475 */
476static void
477xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
478 xmlDtdPtr extSubset, intSubset;
479
480 if (cur == NULL) return;
481
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000482 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
483 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
484
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000485 /*
486 * Do this before freeing the children list to avoid ID lookups
487 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000488 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000489 cur->ids = NULL;
490 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
491 cur->refs = NULL;
492 extSubset = cur->extSubset;
493 intSubset = cur->intSubset;
494 if (intSubset == extSubset)
495 extSubset = NULL;
496 if (extSubset != NULL) {
497 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
498 cur->extSubset = NULL;
499 xmlFreeDtd(extSubset);
500 }
501 if (intSubset != NULL) {
502 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
503 cur->intSubset = NULL;
504 xmlFreeDtd(intSubset);
505 }
506
507 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
508
509 if (cur->version != NULL) xmlFree((char *) cur->version);
510 if (cur->name != NULL) xmlFree((char *) cur->name);
511 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
512 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
513 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000514 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000515
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000516 xmlFree(cur);
517}
518
519/************************************************************************
520 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000521 * The reader core parser *
522 * *
523 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000524#ifdef DEBUG_READER
525static void
526xmlTextReaderDebug(xmlTextReaderPtr reader) {
527 if ((reader == NULL) || (reader->ctxt == NULL)) {
528 fprintf(stderr, "xmlTextReader NULL\n");
529 return;
530 }
531 fprintf(stderr, "xmlTextReader: state %d depth %d ",
532 reader->state, reader->depth);
533 if (reader->node == NULL) {
534 fprintf(stderr, "node = NULL\n");
535 } else {
536 fprintf(stderr, "node %s\n", reader->node->name);
537 }
538 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
539 reader->base, reader->cur, reader->ctxt->nodeNr);
540 if (reader->input->buffer == NULL) {
541 fprintf(stderr, "buffer is NULL\n");
542 } else {
543#ifdef LIBXML_DEBUG_ENABLED
544 xmlDebugDumpString(stderr,
545 &reader->input->buffer->content[reader->cur]);
546#endif
547 fprintf(stderr, "\n");
548 }
549}
550#endif
551
552/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000553 * xmlTextReaderEntPush:
554 * @reader: the xmlTextReaderPtr used
555 * @value: the entity reference node
556 *
557 * Pushes a new entity reference node on top of the entities stack
558 *
559 * Returns 0 in case of error, the index in the stack otherwise
560 */
561static int
562xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
563{
564 if (reader->entMax <= 0) {
565 reader->entMax = 10;
566 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
567 sizeof(reader->entTab[0]));
568 if (reader->entTab == NULL) {
569 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
570 return (0);
571 }
572 }
573 if (reader->entNr >= reader->entMax) {
574 reader->entMax *= 2;
575 reader->entTab =
576 (xmlNodePtr *) xmlRealloc(reader->entTab,
577 reader->entMax *
578 sizeof(reader->entTab[0]));
579 if (reader->entTab == NULL) {
580 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
581 return (0);
582 }
583 }
584 reader->entTab[reader->entNr] = value;
585 reader->ent = value;
586 return (reader->entNr++);
587}
588
589/**
590 * xmlTextReaderEntPop:
591 * @reader: the xmlTextReaderPtr used
592 *
593 * Pops the top element entity from the entities stack
594 *
595 * Returns the entity just removed
596 */
597static xmlNodePtr
598xmlTextReaderEntPop(xmlTextReaderPtr reader)
599{
600 xmlNodePtr ret;
601
602 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000603 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000604 reader->entNr--;
605 if (reader->entNr > 0)
606 reader->ent = reader->entTab[reader->entNr - 1];
607 else
608 reader->ent = NULL;
609 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000610 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000611 return (ret);
612}
613
614/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000615 * xmlTextReaderStartElement:
616 * @ctx: the user data (XML parser context)
617 * @fullname: The element name, including namespace prefix
618 * @atts: An array of name/value attributes pairs, NULL terminated
619 *
620 * called when an opening tag has been processed.
621 */
622static void
623xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
624 const xmlChar **atts) {
625 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
626 xmlTextReaderPtr reader = ctxt->_private;
627
628#ifdef DEBUG_CALLBACKS
629 printf("xmlTextReaderStartElement(%s)\n", fullname);
630#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000631 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000632 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000633 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
634 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
635 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000636 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000637 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000638 if (reader != NULL)
639 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000640}
641
642/**
643 * xmlTextReaderEndElement:
644 * @ctx: the user data (XML parser context)
645 * @fullname: The element name, including namespace prefix
646 *
647 * called when an ending tag has been processed.
648 */
649static void
650xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
651 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
652 xmlTextReaderPtr reader = ctxt->_private;
653
654#ifdef DEBUG_CALLBACKS
655 printf("xmlTextReaderEndElement(%s)\n", fullname);
656#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000657 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000658 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000659 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000660}
661
662/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000663 * xmlTextReaderStartElementNs:
664 * @ctx: the user data (XML parser context)
665 * @localname: the local name of the element
666 * @prefix: the element namespace prefix if available
667 * @URI: the element namespace name if available
668 * @nb_namespaces: number of namespace definitions on that node
669 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
670 * @nb_attributes: the number of attributes on that node
671 * nb_defaulted: the number of defaulted attributes.
672 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
673 * attribute values.
674 *
675 * called when an opening tag has been processed.
676 */
677static void
678xmlTextReaderStartElementNs(void *ctx,
679 const xmlChar *localname,
680 const xmlChar *prefix,
681 const xmlChar *URI,
682 int nb_namespaces,
683 const xmlChar **namespaces,
684 int nb_attributes,
685 int nb_defaulted,
686 const xmlChar **attributes)
687{
688 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
689 xmlTextReaderPtr reader = ctxt->_private;
690
691#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000692 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000693#endif
694 if ((reader != NULL) && (reader->startElementNs != NULL)) {
695 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
696 namespaces, nb_attributes, nb_defaulted,
697 attributes);
698 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
699 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
700 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000701 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000702 }
703 if (reader != NULL)
704 reader->state = XML_TEXTREADER_ELEMENT;
705}
706
707/**
708 * xmlTextReaderEndElementNs:
709 * @ctx: the user data (XML parser context)
710 * @localname: the local name of the element
711 * @prefix: the element namespace prefix if available
712 * @URI: the element namespace name if available
713 *
714 * called when an ending tag has been processed.
715 */
716static void
717xmlTextReaderEndElementNs(void *ctx,
718 const xmlChar * localname,
719 const xmlChar * prefix,
720 const xmlChar * URI)
721{
722 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
723 xmlTextReaderPtr reader = ctxt->_private;
724
725#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000726 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000727#endif
728 if ((reader != NULL) && (reader->endElementNs != NULL)) {
729 reader->endElementNs(ctx, localname, prefix, URI);
730 }
731}
732
733
734/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000735 * xmlTextReaderCharacters:
736 * @ctx: the user data (XML parser context)
737 * @ch: a xmlChar string
738 * @len: the number of xmlChar
739 *
740 * receiving some chars from the parser.
741 */
742static void
743xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
744{
745 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
746 xmlTextReaderPtr reader = ctxt->_private;
747
748#ifdef DEBUG_CALLBACKS
749 printf("xmlTextReaderCharacters()\n");
750#endif
751 if ((reader != NULL) && (reader->characters != NULL)) {
752 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000753 }
754}
755
756/**
757 * xmlTextReaderCDataBlock:
758 * @ctx: the user data (XML parser context)
759 * @value: The pcdata content
760 * @len: the block length
761 *
762 * called when a pcdata block has been parsed
763 */
764static void
765xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
766{
767 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
768 xmlTextReaderPtr reader = ctxt->_private;
769
770#ifdef DEBUG_CALLBACKS
771 printf("xmlTextReaderCDataBlock()\n");
772#endif
773 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
774 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000775 }
776}
777
778/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000779 * xmlTextReaderPushData:
780 * @reader: the xmlTextReaderPtr used
781 *
782 * Push data down the progressive parser until a significant callback
783 * got raised.
784 *
785 * Returns -1 in case of failure, 0 otherwise
786 */
787static int
788xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000789 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000790 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000791 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000792
793 if ((reader->input == NULL) || (reader->input->buffer == NULL))
794 return(-1);
795
Daniel Veillardea7751d2002-12-20 00:16:24 +0000796 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000797 reader->state = XML_TEXTREADER_NONE;
798 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000799
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000800 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000801 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000802 /*
803 * Refill the buffer unless we are at the end of the stream
804 */
805 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
806 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000807 if ((val == 0) &&
808 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
809 if (inbuf->use == reader->cur) {
810 reader->mode = XML_TEXTREADER_MODE_EOF;
811 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000812 }
813 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000814 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000815 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000816 if ((oldstate != XML_TEXTREADER_START) ||
817 (reader->ctxt->myDoc != NULL))
818 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000819 } else if (val == 0) {
820 /* mark the end of the stream and process the remains */
821 reader->mode = XML_TEXTREADER_MODE_EOF;
822 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000823 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000824
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000825 } else
826 break;
827 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000828 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000829 * parse by block of CHUNK_SIZE bytes, various tests show that
830 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000831 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000832 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000833 val = xmlParseChunk(reader->ctxt,
834 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000835 CHUNK_SIZE, 0);
836 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000837 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000838 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000840 s = inbuf->use - reader->cur;
841 val = xmlParseChunk(reader->ctxt,
842 (const char *) &inbuf->content[reader->cur],
843 s, 0);
844 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000845 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000846 return(-1);
847 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000848 }
849 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000850
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000851 /*
852 * Discard the consumed input when needed and possible
853 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000854 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000855 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
856 if ((reader->cur >= 4096) &&
857 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
858 val = xmlBufferShrink(inbuf, reader->cur);
859 if (val >= 0) {
860 reader->cur -= val;
861 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000862 }
863 }
864 }
865
866 /*
867 * At the end of the stream signal that the work is done to the Push
868 * parser.
869 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000870 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000871 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000872 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000873 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000874 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000875 s, 1);
876 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000877 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000878 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000879 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000880 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000881 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000882 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000883 return(0);
884}
885
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000886#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000887/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000888 * xmlTextReaderValidatePush:
889 * @reader: the xmlTextReaderPtr used
890 *
891 * Push the current node for validation
892 */
893static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000894xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000895 xmlNodePtr node = reader->node;
896
Daniel Veillardf54cd532004-02-25 11:52:31 +0000897#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000898 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
899 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
900 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
901 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
902 reader->ctxt->myDoc, node, node->name);
903 } else {
904 /* TODO use the BuildQName interface */
905 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000906
Daniel Veillardf4e55762003-04-15 23:32:22 +0000907 qname = xmlStrdup(node->ns->prefix);
908 qname = xmlStrcat(qname, BAD_CAST ":");
909 qname = xmlStrcat(qname, node->name);
910 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
911 reader->ctxt->myDoc, node, qname);
912 if (qname != NULL)
913 xmlFree(qname);
914 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000915 }
916#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000917#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000918 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000919 (reader->rngValidCtxt != NULL)) {
920 int ret;
921
922 if (reader->rngFullNode != NULL) return;
923 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
924 reader->ctxt->myDoc,
925 node);
926 if (ret == 0) {
927 /*
928 * this element requires a full tree
929 */
930 node = xmlTextReaderExpand(reader);
931 if (node == NULL) {
932printf("Expand failed !\n");
933 ret = -1;
934 } else {
935 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
936 reader->ctxt->myDoc,
937 node);
938 reader->rngFullNode = node;
939 }
940 }
941 if (ret != 1)
942 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000943 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000944#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000945}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000946
947/**
948 * xmlTextReaderValidateCData:
949 * @reader: the xmlTextReaderPtr used
950 * @data: pointer to the CData
951 * @len: lenght of the CData block in bytes.
952 *
953 * Push some CData for validation
954 */
955static void
956xmlTextReaderValidateCData(xmlTextReaderPtr reader,
957 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000958#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000959 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
960 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
961 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
962 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000963 }
964#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000966 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000967 (reader->rngValidCtxt != NULL)) {
968 int ret;
969
970 if (reader->rngFullNode != NULL) return;
971 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
972 if (ret != 1)
973 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000974 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000975#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000976}
977
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000978/**
979 * xmlTextReaderValidatePop:
980 * @reader: the xmlTextReaderPtr used
981 *
982 * Pop the current node from validation
983 */
984static void
985xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
986 xmlNodePtr node = reader->node;
987
Daniel Veillardf54cd532004-02-25 11:52:31 +0000988#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000989 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
990 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
991 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
992 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
993 reader->ctxt->myDoc, node, node->name);
994 } else {
995 /* TODO use the BuildQName interface */
996 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000997
Daniel Veillardf4e55762003-04-15 23:32:22 +0000998 qname = xmlStrdup(node->ns->prefix);
999 qname = xmlStrcat(qname, BAD_CAST ":");
1000 qname = xmlStrcat(qname, node->name);
1001 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1002 reader->ctxt->myDoc, node, qname);
1003 if (qname != NULL)
1004 xmlFree(qname);
1005 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001006 }
1007#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001008#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001009 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001010 (reader->rngValidCtxt != NULL)) {
1011 int ret;
1012
1013 if (reader->rngFullNode != NULL) {
1014 if (node == reader->rngFullNode)
1015 reader->rngFullNode = NULL;
1016 return;
1017 }
1018 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1019 reader->ctxt->myDoc,
1020 node);
1021 if (ret != 1)
1022 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001023 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001024#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001025}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001026
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001027/**
1028 * xmlTextReaderValidateEntity:
1029 * @reader: the xmlTextReaderPtr used
1030 *
1031 * Handle the validation when an entity reference is encountered and
1032 * entity substitution is not activated. As a result the parser interface
1033 * must walk through the entity and do the validation calls
1034 */
1035static void
1036xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1037 xmlNodePtr oldnode = reader->node;
1038 xmlNodePtr node = reader->node;
1039 xmlParserCtxtPtr ctxt = reader->ctxt;
1040
1041 do {
1042 if (node->type == XML_ENTITY_REF_NODE) {
1043 /*
1044 * Case where the underlying tree is not availble, lookup the entity
1045 * and walk it.
1046 */
1047 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1048 (ctxt->sax->getEntity != NULL)) {
1049 node->children = (xmlNodePtr)
1050 ctxt->sax->getEntity(ctxt, node->name);
1051 }
1052
1053 if ((node->children != NULL) &&
1054 (node->children->type == XML_ENTITY_DECL) &&
1055 (node->children->children != NULL)) {
1056 xmlTextReaderEntPush(reader, node);
1057 node = node->children->children;
1058 continue;
1059 } else {
1060 /*
1061 * The error has probably be raised already.
1062 */
1063 if (node == oldnode)
1064 break;
1065 node = node->next;
1066 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001067#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001068 } else if (node->type == XML_ELEMENT_NODE) {
1069 reader->node = node;
1070 xmlTextReaderValidatePush(reader);
1071 } else if ((node->type == XML_TEXT_NODE) ||
1072 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001073 xmlTextReaderValidateCData(reader, node->content,
1074 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001075#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001076 }
1077
1078 /*
1079 * go to next node
1080 */
1081 if (node->children != NULL) {
1082 node = node->children;
1083 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001084 } else if (node->type == XML_ELEMENT_NODE) {
1085 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001086 }
1087 if (node->next != NULL) {
1088 node = node->next;
1089 continue;
1090 }
1091 do {
1092 node = node->parent;
1093 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001094 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001095 if (reader->entNr == 0) {
1096 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001097 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001098 xmlUnlinkNode(tmp);
1099 xmlTextReaderFreeNode(reader, tmp);
1100 } else
1101 break;
1102 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001103 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001104 reader->node = node;
1105 xmlTextReaderValidatePop(reader);
1106 }
1107 if ((node->type == XML_ENTITY_DECL) &&
1108 (reader->ent != NULL) && (reader->ent->children == node)) {
1109 node = xmlTextReaderEntPop(reader);
1110 }
1111 if (node == oldnode)
1112 break;
1113 if (node->next != NULL) {
1114 node = node->next;
1115 break;
1116 }
1117 } while ((node != NULL) && (node != oldnode));
1118 } while ((node != NULL) && (node != oldnode));
1119 reader->node = oldnode;
1120}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001121#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001122
1123
1124/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001125 * xmlTextReaderGetSuccessor:
1126 * @cur: the current node
1127 *
1128 * Get the successor of a node if available.
1129 *
1130 * Returns the successor node or NULL
1131 */
1132static xmlNodePtr
1133xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1134 if (cur == NULL) return(NULL) ; /* ERROR */
1135 if (cur->next != NULL) return(cur->next) ;
1136 do {
1137 cur = cur->parent;
1138 if (cur == NULL) return(NULL);
1139 if (cur->next != NULL) return(cur->next);
1140 } while (cur != NULL);
1141 return(cur);
1142}
1143
1144/**
1145 * xmlTextReaderDoExpand:
1146 * @reader: the xmlTextReaderPtr used
1147 *
1148 * Makes sure that the current node is fully read as well as all its
1149 * descendant. It means the full DOM subtree must be available at the
1150 * end of the call.
1151 *
1152 * Returns 1 if the node was expanded successfully, 0 if there is no more
1153 * nodes to read, or -1 in case of error
1154 */
1155static int
1156xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1157 int val;
1158
1159 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1160 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001161 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001162 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1163
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001164 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1165 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001166 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001167 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001168 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1169 return(1);
1170 val = xmlTextReaderPushData(reader);
1171 if (val < 0)
1172 return(-1);
1173 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1174 return(1);
1175}
1176
1177/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001178 * xmlTextReaderCollectSiblings:
1179 * @node: the first child
1180 *
1181 * Traverse depth-first through all sibling nodes and their children
1182 * nodes and concatenate their content. This is an auxiliary function
1183 * to xmlTextReaderReadString.
1184 *
1185 * Returns a string containing the content, or NULL in case of error.
1186 */
1187static xmlChar *
1188xmlTextReaderCollectSiblings(xmlNodePtr node)
1189{
1190 xmlBufferPtr buffer;
1191 xmlChar *ret;
1192
1193 buffer = xmlBufferCreate();
1194 if (buffer == NULL)
1195 return NULL;
1196
1197 for ( ; node != NULL; node = node->next) {
1198 switch (node->type) {
1199 case XML_TEXT_NODE:
1200 case XML_CDATA_SECTION_NODE:
1201 xmlBufferCat(buffer, node->content);
1202 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001203 case XML_ELEMENT_NODE: {
1204 xmlChar *tmp;
1205
1206 tmp = xmlTextReaderCollectSiblings(node->children);
1207 xmlBufferCat(buffer, tmp);
1208 xmlFree(tmp);
1209 break;
1210 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001211 default:
1212 break;
1213 }
1214 }
1215 ret = buffer->content;
1216 buffer->content = NULL;
1217 xmlBufferFree(buffer);
1218 return(ret);
1219}
1220
1221/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001222 * xmlTextReaderRead:
1223 * @reader: the xmlTextReaderPtr used
1224 *
1225 * Moves the position of the current instance to the next node in
1226 * the stream, exposing its properties.
1227 *
1228 * Returns 1 if the node was read successfully, 0 if there is no more
1229 * nodes to read, or -1 in case of error
1230 */
1231int
1232xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001233 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001234 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001235 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001236
William M. Brack1af55582004-07-22 17:18:00 +00001237
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001238 if (reader == NULL)
1239 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001240 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001241 if (reader->doc != NULL)
1242 return(xmlTextReaderReadTree(reader));
1243 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001244 return(-1);
1245 if (reader->ctxt->wellFormed != 1)
1246 return(-1);
1247
1248#ifdef DEBUG_READER
1249 fprintf(stderr, "\nREAD ");
1250 DUMP_READER
1251#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001252 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1253 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001254 /*
1255 * Initial state
1256 */
1257 do {
1258 val = xmlTextReaderPushData(reader);
1259 if (val < 0)
1260 return(-1);
1261 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001262 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1263 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001264 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001265 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001266 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001267 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 if (reader->node == NULL)
1269 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001270 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001271 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001272 if (reader->ctxt->myDoc != NULL) {
1273 reader->node = reader->ctxt->myDoc->children;
1274 }
1275 if (reader->node == NULL)
1276 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001277 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001278 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001279 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001280 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001281 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001282 }
1283 oldstate = reader->state;
1284 olddepth = reader->ctxt->nodeNr;
1285 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001286
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001287get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001288 if (reader->node == NULL) {
1289 if (reader->mode == XML_TEXTREADER_DONE)
1290 return(0);
1291 else
1292 return(-1);
1293 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001294
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001295 /*
1296 * If we are not backtracking on ancestors or examined nodes,
1297 * that the parser didn't finished or that we arent at the end
1298 * of stream, continue processing.
1299 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001300 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001301 (reader->ctxt->nodeNr == olddepth) &&
1302 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001303 (reader->node->children == NULL) ||
1304 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001305 ((reader->node->children != NULL) &&
1306 (reader->node->children->type == XML_TEXT_NODE) &&
1307 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001308 (reader->node->type == XML_DTD_NODE) ||
1309 (reader->node->type == XML_DOCUMENT_NODE) ||
1310 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001311 ((reader->ctxt->node == NULL) ||
1312 (reader->ctxt->node == reader->node) ||
1313 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001314 (reader->ctxt->instate != XML_PARSER_EOF)) {
1315 val = xmlTextReaderPushData(reader);
1316 if (val < 0)
1317 return(-1);
1318 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001319 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001320 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001321 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 if ((reader->node->children != NULL) &&
1323 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001324 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001325 (reader->node->type != XML_DTD_NODE)) {
1326 reader->node = reader->node->children;
1327 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001328 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001329 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001330 }
1331 }
1332 if (reader->node->next != NULL) {
1333 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001334 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001335 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001336 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1337#ifdef LIBXML_XINCLUDE_ENABLED
1338 && (reader->in_xinclude <= 0)
1339#endif
1340 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001341 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001342 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001343 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001344#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001345 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001346 (reader->node->type == XML_ELEMENT_NODE))
1347 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001348#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001349 if ((reader->preserves > 0) &&
1350 (reader->node->extra & NODE_IS_SPRESERVED))
1351 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001352 reader->node = reader->node->next;
1353 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001354
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001355 /*
1356 * Cleanup of the old node
1357 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001358 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001359#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001360 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001361#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001362 (reader->entNr == 0) &&
1363 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001364 (reader->node->prev->type != XML_DTD_NODE) &&
1365 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001366 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001367 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001368 xmlUnlinkNode(tmp);
1369 xmlTextReaderFreeNode(reader, tmp);
1370 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001371 }
1372
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001373 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001374 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001375 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001376 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001377 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001378 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001379 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001380 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001381 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001382#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001383 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001384 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001385#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001386 if ((reader->preserves > 0) &&
1387 (reader->node->extra & NODE_IS_SPRESERVED))
1388 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001389 reader->node = reader->node->parent;
1390 if ((reader->node == NULL) ||
1391 (reader->node->type == XML_DOCUMENT_NODE) ||
1392#ifdef LIBXML_DOCB_ENABLED
1393 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1394#endif
1395 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001396 if (reader->mode != XML_TEXTREADER_DONE) {
1397 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1398 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001399 if (val != 0)
1400 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001401 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001402 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001403 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001404
1405 /*
1406 * Cleanup of the old node
1407 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001408 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001409#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001410 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001411#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001412 (reader->entNr == 0) &&
1413 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001414 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001415 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001416 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001417 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001418 }
1419
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001420 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001421 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001422 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001423#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001424 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001425#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001426 (reader->entNr == 0) &&
1427 (reader->node->last != NULL) &&
1428 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1429 xmlNodePtr tmp = reader->node->last;
1430 xmlUnlinkNode(tmp);
1431 xmlTextReaderFreeNode(reader, tmp);
1432 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001433 reader->depth--;
1434 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001435
1436node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001437 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001438
1439 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001440 * If we are in the middle of a piece of CDATA make sure it's finished
1441 */
1442 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001443 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001444 ((reader->node->type == XML_TEXT_NODE) ||
1445 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001446 if (xmlTextReaderExpand(reader) == NULL)
1447 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001448 }
1449
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001450#ifdef LIBXML_XINCLUDE_ENABLED
1451 /*
1452 * Handle XInclude if asked for
1453 */
1454 if ((reader->xinclude) && (reader->node != NULL) &&
1455 (reader->node->type == XML_ELEMENT_NODE) &&
1456 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001457 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1458 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001459 if (reader->xincctxt == NULL) {
1460 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001461 xmlXIncludeSetFlags(reader->xincctxt,
1462 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001463 }
1464 /*
1465 * expand that node and process it
1466 */
William M. Brack42331a92004-07-29 07:07:16 +00001467 if (xmlTextReaderExpand(reader) == NULL)
1468 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001469 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1470 }
1471 if (reader->node->type == XML_XINCLUDE_START) {
1472 reader->in_xinclude++;
1473 goto get_next_node;
1474 }
1475 if (reader->node->type == XML_XINCLUDE_END) {
1476 reader->in_xinclude--;
1477 goto get_next_node;
1478 }
1479#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001480 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001481 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001482 */
1483 if ((reader->node != NULL) &&
1484 (reader->node->type == XML_ENTITY_REF_NODE) &&
1485 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1486 /*
1487 * Case where the underlying tree is not availble, lookup the entity
1488 * and walk it.
1489 */
1490 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1491 (reader->ctxt->sax->getEntity != NULL)) {
1492 reader->node->children = (xmlNodePtr)
1493 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1494 }
1495
1496 if ((reader->node->children != NULL) &&
1497 (reader->node->children->type == XML_ENTITY_DECL) &&
1498 (reader->node->children->children != NULL)) {
1499 xmlTextReaderEntPush(reader, reader->node);
1500 reader->node = reader->node->children->children;
1501 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001502#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001503 } else if ((reader->node != NULL) &&
1504 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001505 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001506 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001507#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001508 }
1509 if ((reader->node != NULL) &&
1510 (reader->node->type == XML_ENTITY_DECL) &&
1511 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1512 reader->node = xmlTextReaderEntPop(reader);
1513 reader->depth++;
1514 goto get_next_node;
1515 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001516#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001517 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001518 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001519
1520 if ((node->type == XML_ELEMENT_NODE) &&
1521 ((reader->state != XML_TEXTREADER_END) &&
1522 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1523 xmlTextReaderValidatePush(reader);
1524 } else if ((node->type == XML_TEXT_NODE) ||
1525 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001526 xmlTextReaderValidateCData(reader, node->content,
1527 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001528 }
1529 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001530#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001531#ifdef LIBXML_PATTERN_ENABLED
1532 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1533 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1534 int i;
1535 for (i = 0;i < reader->patternNr;i++) {
1536 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1537 xmlTextReaderPreserve(reader);
1538 break;
1539 }
1540 }
1541 }
1542#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001543#ifdef LIBXML_SCHEMAS_ENABLED
1544 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1545 (reader->xsdValidErrors == 0) &&
1546 (reader->xsdValidCtxt != NULL)) {
1547 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1548 }
1549#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001550 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001551node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001552 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001553 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001554}
1555
Daniel Veillard67df8092002-12-16 22:04:11 +00001556/**
1557 * xmlTextReaderReadState:
1558 * @reader: the xmlTextReaderPtr used
1559 *
1560 * Gets the read state of the reader.
1561 *
1562 * Returns the state value, or -1 in case of error
1563 */
1564int
1565xmlTextReaderReadState(xmlTextReaderPtr reader) {
1566 if (reader == NULL)
1567 return(-1);
1568 return(reader->mode);
1569}
1570
1571/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001572 * xmlTextReaderExpand:
1573 * @reader: the xmlTextReaderPtr used
1574 *
1575 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001576 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001577 *
1578 * Returns a node pointer valid until the next xmlTextReaderRead() call
1579 * or NULL in case of error.
1580 */
1581xmlNodePtr
1582xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001583 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001584 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001585 if (reader->doc != NULL)
1586 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001587 if (reader->ctxt == NULL)
1588 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001589 if (xmlTextReaderDoExpand(reader) < 0)
1590 return(NULL);
1591 return(reader->node);
1592}
1593
1594/**
1595 * xmlTextReaderNext:
1596 * @reader: the xmlTextReaderPtr used
1597 *
1598 * Skip to the node following the current one in document order while
1599 * avoiding the subtree if any.
1600 *
1601 * Returns 1 if the node was read successfully, 0 if there is no more
1602 * nodes to read, or -1 in case of error
1603 */
1604int
1605xmlTextReaderNext(xmlTextReaderPtr reader) {
1606 int ret;
1607 xmlNodePtr cur;
1608
1609 if (reader == NULL)
1610 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001611 if (reader->doc != NULL)
1612 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001613 cur = reader->node;
1614 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1615 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001616 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001617 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001618 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001619 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001620 do {
1621 ret = xmlTextReaderRead(reader);
1622 if (ret != 1)
1623 return(ret);
1624 } while (reader->node != cur);
1625 return(xmlTextReaderRead(reader));
1626}
1627
1628/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001629 * xmlTextReaderReadInnerXml:
1630 * @reader: the xmlTextReaderPtr used
1631 *
1632 * Reads the contents of the current node, including child nodes and markup.
1633 *
1634 * Returns a string containing the XML content, or NULL if the current node
1635 * is neither an element nor attribute, or has no child nodes. The
1636 * string must be deallocated by the caller.
1637 */
1638xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001639xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1640{
1641 xmlChar *resbuf;
1642 xmlNodePtr node, cur_node;
1643 xmlBufferPtr buff, buff2;
1644 xmlDocPtr doc;
1645
1646 if (xmlTextReaderExpand(reader) == NULL) {
1647 return NULL;
1648 }
1649 doc = reader->doc;
1650 buff = xmlBufferCreate();
1651 for (cur_node = reader->node->children; cur_node != NULL;
1652 cur_node = cur_node->next) {
1653 node = xmlDocCopyNode(cur_node, doc, 1);
1654 buff2 = xmlBufferCreate();
1655 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1656 xmlFreeNode(node);
1657 xmlBufferFree(buff2);
1658 xmlBufferFree(buff);
1659 return NULL;
1660 }
1661 xmlBufferCat(buff, buff2->content);
1662 xmlFreeNode(node);
1663 xmlBufferFree(buff2);
1664 }
1665 resbuf = buff->content;
1666 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001667}
1668
1669/**
1670 * xmlTextReaderReadOuterXml:
1671 * @reader: the xmlTextReaderPtr used
1672 *
1673 * Reads the contents of the current node, including child nodes and markup.
1674 *
1675 * Returns a string containing the XML content, or NULL if the current node
1676 * is neither an element nor attribute, or has no child nodes. The
1677 * string must be deallocated by the caller.
1678 */
1679xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001680xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1681{
1682 xmlChar *resbuf;
1683 xmlNodePtr node;
1684 xmlBufferPtr buff;
1685 xmlDocPtr doc;
1686
1687 node = reader->node;
1688 doc = reader->doc;
1689 if (xmlTextReaderExpand(reader) == NULL) {
1690 return NULL;
1691 }
1692 node = xmlDocCopyNode(node, doc, 1);
1693 buff = xmlBufferCreate();
1694 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1695 xmlFreeNode(node);
1696 xmlBufferFree(buff);
1697 return NULL;
1698 }
1699
1700 resbuf = buff->content;
1701 buff->content = NULL;
1702
1703 xmlFreeNode(node);
1704 xmlBufferFree(buff);
1705 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001706}
1707
1708/**
1709 * xmlTextReaderReadString:
1710 * @reader: the xmlTextReaderPtr used
1711 *
1712 * Reads the contents of an element or a text node as a string.
1713 *
1714 * Returns a string containing the contents of the Element or Text node,
1715 * or NULL if the reader is positioned on any other type of node.
1716 * The string must be deallocated by the caller.
1717 */
1718xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001719xmlTextReaderReadString(xmlTextReaderPtr reader)
1720{
1721 xmlNodePtr node;
1722
1723 if ((reader == NULL) || (reader->node == NULL))
1724 return(NULL);
1725
1726 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1727 switch (node->type) {
1728 case XML_TEXT_NODE:
1729 if (node->content != NULL)
1730 return(xmlStrdup(node->content));
1731 break;
1732 case XML_ELEMENT_NODE:
1733 if (xmlTextReaderDoExpand(reader) != -1) {
1734 return xmlTextReaderCollectSiblings(node->children);
1735 }
1736 case XML_ATTRIBUTE_NODE:
1737 TODO
1738 break;
1739 default:
1740 break;
1741 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001742 return(NULL);
1743}
1744
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001745#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001746/**
1747 * xmlTextReaderReadBase64:
1748 * @reader: the xmlTextReaderPtr used
1749 * @array: a byte array to store the content.
1750 * @offset: the zero-based index into array where the method should
1751 * begin to write.
1752 * @len: the number of bytes to write.
1753 *
1754 * Reads and decodes the Base64 encoded contents of an element and
1755 * stores the result in a byte buffer.
1756 *
1757 * Returns the number of bytes written to array, or zero if the current
1758 * instance is not positioned on an element or -1 in case of error.
1759 */
1760int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001761xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1762 unsigned char *array ATTRIBUTE_UNUSED,
1763 int offset ATTRIBUTE_UNUSED,
1764 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001765 if ((reader == NULL) || (reader->ctxt == NULL))
1766 return(-1);
1767 if (reader->ctxt->wellFormed != 1)
1768 return(-1);
1769
1770 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1771 return(0);
1772 TODO
1773 return(0);
1774}
1775
1776/**
1777 * xmlTextReaderReadBinHex:
1778 * @reader: the xmlTextReaderPtr used
1779 * @array: a byte array to store the content.
1780 * @offset: the zero-based index into array where the method should
1781 * begin to write.
1782 * @len: the number of bytes to write.
1783 *
1784 * Reads and decodes the BinHex encoded contents of an element and
1785 * stores the result in a byte buffer.
1786 *
1787 * Returns the number of bytes written to array, or zero if the current
1788 * instance is not positioned on an element or -1 in case of error.
1789 */
1790int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001791xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1792 unsigned char *array ATTRIBUTE_UNUSED,
1793 int offset ATTRIBUTE_UNUSED,
1794 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001795 if ((reader == NULL) || (reader->ctxt == NULL))
1796 return(-1);
1797 if (reader->ctxt->wellFormed != 1)
1798 return(-1);
1799
1800 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1801 return(0);
1802 TODO
1803 return(0);
1804}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001805#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001806
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001807/************************************************************************
1808 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001809 * Operating on a preparsed tree *
1810 * *
1811 ************************************************************************/
1812static int
1813xmlTextReaderNextTree(xmlTextReaderPtr reader)
1814{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001815 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001816 return(-1);
1817
1818 if (reader->state == XML_TEXTREADER_END)
1819 return(0);
1820
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001821 if (reader->node == NULL) {
1822 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001823 reader->state = XML_TEXTREADER_END;
1824 return(0);
1825 }
1826
1827 reader->node = reader->doc->children;
1828 reader->state = XML_TEXTREADER_START;
1829 return(1);
1830 }
1831
1832 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1833 if (reader->node->children != 0) {
1834 reader->node = reader->node->children;
1835 reader->depth++;
1836 reader->state = XML_TEXTREADER_START;
1837 return(1);
1838 }
1839
1840 if ((reader->node->type == XML_ELEMENT_NODE) ||
1841 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1842 reader->state = XML_TEXTREADER_BACKTRACK;
1843 return(1);
1844 }
1845 }
1846
1847 if (reader->node->next != 0) {
1848 reader->node = reader->node->next;
1849 reader->state = XML_TEXTREADER_START;
1850 return(1);
1851 }
1852
1853 if (reader->node->parent != 0) {
1854 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1855 reader->state = XML_TEXTREADER_END;
1856 return(0);
1857 }
1858
1859 reader->node = reader->node->parent;
1860 reader->depth--;
1861 reader->state = XML_TEXTREADER_BACKTRACK;
1862 return(1);
1863 }
1864
1865 reader->state = XML_TEXTREADER_END;
1866
1867 return(1);
1868}
1869
1870/**
1871 * xmlTextReaderReadTree:
1872 * @reader: the xmlTextReaderPtr used
1873 *
1874 * Moves the position of the current instance to the next node in
1875 * the stream, exposing its properties.
1876 *
1877 * Returns 1 if the node was read successfully, 0 if there is no more
1878 * nodes to read, or -1 in case of error
1879 */
1880static int
1881xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1882 if (reader->state == XML_TEXTREADER_END)
1883 return(0);
1884
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001885next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001886 if (reader->node == NULL) {
1887 if (reader->doc->children == NULL) {
1888 reader->state = XML_TEXTREADER_END;
1889 return(0);
1890 }
1891
1892 reader->node = reader->doc->children;
1893 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001894 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001895 }
1896
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001897 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1898 (reader->node->type != XML_DTD_NODE) &&
1899 (reader->node->type != XML_XINCLUDE_START) &&
1900 (reader->node->type != XML_ENTITY_REF_NODE)) {
1901 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001902 reader->node = reader->node->children;
1903 reader->depth++;
1904 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001905 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001906 }
1907
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001908 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001909 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001910 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001911 }
1912 }
1913
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001914 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001915 reader->node = reader->node->next;
1916 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001917 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001918 }
1919
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001920 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001921 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1922 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1923 reader->state = XML_TEXTREADER_END;
1924 return(0);
1925 }
1926
1927 reader->node = reader->node->parent;
1928 reader->depth--;
1929 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001930 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001931 }
1932
1933 reader->state = XML_TEXTREADER_END;
1934
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001935found_node:
1936 if ((reader->node->type == XML_XINCLUDE_START) ||
1937 (reader->node->type == XML_XINCLUDE_END))
1938 goto next_node;
1939
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001940 return(1);
1941}
1942
1943/**
William M. Brackb1d53162003-11-18 06:54:40 +00001944 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001945 * @reader: the xmlTextReaderPtr used
1946 *
1947 * Skip to the node following the current one in document order while
1948 * avoiding the subtree if any.
1949 * Currently implemented only for Readers built on a document
1950 *
1951 * Returns 1 if the node was read successfully, 0 if there is no more
1952 * nodes to read, or -1 in case of error
1953 */
1954int
1955xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1956 if (reader == NULL)
1957 return(-1);
1958 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001959 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001960 return(-1);
1961 }
1962
1963 if (reader->state == XML_TEXTREADER_END)
1964 return(0);
1965
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001966 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001967 return(xmlTextReaderNextTree(reader));
1968
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001969 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001970 reader->node = reader->node->next;
1971 reader->state = XML_TEXTREADER_START;
1972 return(1);
1973 }
1974
1975 return(0);
1976}
1977
1978/************************************************************************
1979 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001980 * Constructor and destructors *
1981 * *
1982 ************************************************************************/
1983/**
1984 * xmlNewTextReader:
1985 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001986 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001987 *
1988 * Create an xmlTextReader structure fed with @input
1989 *
1990 * Returns the new xmlTextReaderPtr or NULL in case of error
1991 */
1992xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001993xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001994 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001995
1996 if (input == NULL)
1997 return(NULL);
1998 ret = xmlMalloc(sizeof(xmlTextReader));
1999 if (ret == NULL) {
2000 xmlGenericError(xmlGenericErrorContext,
2001 "xmlNewTextReader : malloc failed\n");
2002 return(NULL);
2003 }
2004 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002005 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002006 ret->entTab = NULL;
2007 ret->entMax = 0;
2008 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002009 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002010 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002011 if (ret->buffer == NULL) {
2012 xmlFree(ret);
2013 xmlGenericError(xmlGenericErrorContext,
2014 "xmlNewTextReader : malloc failed\n");
2015 return(NULL);
2016 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002017 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2018 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002019 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002020 xmlFree(ret);
2021 xmlGenericError(xmlGenericErrorContext,
2022 "xmlNewTextReader : malloc failed\n");
2023 return(NULL);
2024 }
Daniel Veillard81273902003-09-30 00:43:48 +00002025 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002026 ret->startElement = ret->sax->startElement;
2027 ret->sax->startElement = xmlTextReaderStartElement;
2028 ret->endElement = ret->sax->endElement;
2029 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002030#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002031 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002032#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002033 ret->startElementNs = ret->sax->startElementNs;
2034 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2035 ret->endElementNs = ret->sax->endElementNs;
2036 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002037#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002038 } else {
2039 ret->startElementNs = NULL;
2040 ret->endElementNs = NULL;
2041 }
Daniel Veillard81273902003-09-30 00:43:48 +00002042#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002043 ret->characters = ret->sax->characters;
2044 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002045 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002046 ret->cdataBlock = ret->sax->cdataBlock;
2047 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048
Daniel Veillard67df8092002-12-16 22:04:11 +00002049 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002050 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002051 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002052 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002053 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002054 }
2055 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002056 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002057 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002058 ret->base = 0;
2059 ret->cur = 4;
2060 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002061 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002062 ret->base = 0;
2063 ret->cur = 0;
2064 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002065
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002066 if (ret->ctxt == NULL) {
2067 xmlGenericError(xmlGenericErrorContext,
2068 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002069 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002070 xmlFree(ret->sax);
2071 xmlFree(ret);
2072 return(NULL);
2073 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002074 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002075 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002076 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002077 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002078 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002079 /*
2080 * use the parser dictionnary to allocate all elements and attributes names
2081 */
2082 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002083 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002084#ifdef LIBXML_XINCLUDE_ENABLED
2085 ret->xinclude = 0;
2086#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002087#ifdef LIBXML_PATTERN_ENABLED
2088 ret->patternMax = 0;
2089 ret->patternTab = NULL;
2090#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002091 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002092}
2093
2094/**
2095 * xmlNewTextReaderFilename:
2096 * @URI: the URI of the resource to process
2097 *
2098 * Create an xmlTextReader structure fed with the resource at @URI
2099 *
2100 * Returns the new xmlTextReaderPtr or NULL in case of error
2101 */
2102xmlTextReaderPtr
2103xmlNewTextReaderFilename(const char *URI) {
2104 xmlParserInputBufferPtr input;
2105 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002106 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002107
2108 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2109 if (input == NULL)
2110 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002111 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002112 if (ret == NULL) {
2113 xmlFreeParserInputBuffer(input);
2114 return(NULL);
2115 }
2116 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002117 if (ret->ctxt->directory == NULL)
2118 directory = xmlParserGetDirectory(URI);
2119 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2120 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2121 if (directory != NULL)
2122 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002123 return(ret);
2124}
2125
2126/**
2127 * xmlFreeTextReader:
2128 * @reader: the xmlTextReaderPtr
2129 *
2130 * Deallocate all the resources associated to the reader
2131 */
2132void
2133xmlFreeTextReader(xmlTextReaderPtr reader) {
2134 if (reader == NULL)
2135 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002136#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002137 if (reader->rngSchemas != NULL) {
2138 xmlRelaxNGFree(reader->rngSchemas);
2139 reader->rngSchemas = NULL;
2140 }
2141 if (reader->rngValidCtxt != NULL) {
2142 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2143 reader->rngValidCtxt = NULL;
2144 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002145 if (reader->xsdPlug != NULL) {
2146 xmlSchemaSAXUnplug(reader->xsdPlug);
2147 reader->xsdPlug = NULL;
2148 }
2149 if (reader->xsdValidCtxt != NULL) {
2150 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2151 reader->xsdValidCtxt = NULL;
2152 }
2153 if (reader->xsdSchemas != NULL) {
2154 xmlSchemaFree(reader->xsdSchemas);
2155 reader->xsdSchemas = NULL;
2156 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002157#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002158#ifdef LIBXML_XINCLUDE_ENABLED
2159 if (reader->xincctxt != NULL)
2160 xmlXIncludeFreeContext(reader->xincctxt);
2161#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002162#ifdef LIBXML_PATTERN_ENABLED
2163 if (reader->patternTab != NULL) {
2164 int i;
2165 for (i = 0;i < reader->patternNr;i++) {
2166 if (reader->patternTab[i] != NULL)
2167 xmlFreePattern(reader->patternTab[i]);
2168 }
2169 xmlFree(reader->patternTab);
2170 }
2171#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002172 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002173 if (reader->dict == reader->ctxt->dict)
2174 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002175 if (reader->ctxt->myDoc != NULL) {
2176 if (reader->preserve == 0)
2177 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2178 reader->ctxt->myDoc = NULL;
2179 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002180 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2181 (reader->ctxt->vctxt.vstateMax > 0)){
2182 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002183 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002184 reader->ctxt->vctxt.vstateMax = 0;
2185 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002186 if (reader->allocs & XML_TEXTREADER_CTXT)
2187 xmlFreeParserCtxt(reader->ctxt);
2188 }
2189 if (reader->sax != NULL)
2190 xmlFree(reader->sax);
2191 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2192 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002193 if (reader->faketext != NULL) {
2194 xmlFreeNode(reader->faketext);
2195 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002196 if (reader->buffer != NULL)
2197 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002198 if (reader->entTab != NULL)
2199 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002200 if (reader->dict != NULL)
2201 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002202 xmlFree(reader);
2203}
2204
2205/************************************************************************
2206 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002207 * Methods for XmlTextReader *
2208 * *
2209 ************************************************************************/
2210/**
2211 * xmlTextReaderClose:
2212 * @reader: the xmlTextReaderPtr used
2213 *
2214 * This method releases any resources allocated by the current instance
2215 * changes the state to Closed and close any underlying input.
2216 *
2217 * Returns 0 or -1 in case of error
2218 */
2219int
2220xmlTextReaderClose(xmlTextReaderPtr reader) {
2221 if (reader == NULL)
2222 return(-1);
2223 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002224 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002225 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2226 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002227 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002228 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002229 if (reader->preserve == 0)
2230 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002231 reader->ctxt->myDoc = NULL;
2232 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002233 }
2234 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2235 xmlFreeParserInputBuffer(reader->input);
2236 reader->allocs -= XML_TEXTREADER_INPUT;
2237 }
2238 return(0);
2239}
2240
2241/**
2242 * xmlTextReaderGetAttributeNo:
2243 * @reader: the xmlTextReaderPtr used
2244 * @no: the zero-based index of the attribute relative to the containing element
2245 *
2246 * Provides the value of the attribute with the specified index relative
2247 * to the containing element.
2248 *
2249 * Returns a string containing the value of the specified attribute, or NULL
2250 * in case of error. The string must be deallocated by the caller.
2251 */
2252xmlChar *
2253xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2254 xmlChar *ret;
2255 int i;
2256 xmlAttrPtr cur;
2257 xmlNsPtr ns;
2258
2259 if (reader == NULL)
2260 return(NULL);
2261 if (reader->node == NULL)
2262 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002263 if (reader->curnode != NULL)
2264 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002265 /* TODO: handle the xmlDecl */
2266 if (reader->node->type != XML_ELEMENT_NODE)
2267 return(NULL);
2268
2269 ns = reader->node->nsDef;
2270 for (i = 0;(i < no) && (ns != NULL);i++) {
2271 ns = ns->next;
2272 }
2273 if (ns != NULL)
2274 return(xmlStrdup(ns->href));
2275
2276 cur = reader->node->properties;
2277 if (cur == NULL)
2278 return(NULL);
2279 for (;i < no;i++) {
2280 cur = cur->next;
2281 if (cur == NULL)
2282 return(NULL);
2283 }
2284 /* TODO walk the DTD if present */
2285
2286 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2287 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2288 return(ret);
2289}
2290
2291/**
2292 * xmlTextReaderGetAttribute:
2293 * @reader: the xmlTextReaderPtr used
2294 * @name: the qualified name of the attribute.
2295 *
2296 * Provides the value of the attribute with the specified qualified name.
2297 *
2298 * Returns a string containing the value of the specified attribute, or NULL
2299 * in case of error. The string must be deallocated by the caller.
2300 */
2301xmlChar *
2302xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2303 xmlChar *prefix = NULL;
2304 xmlChar *localname;
2305 xmlNsPtr ns;
2306 xmlChar *ret = NULL;
2307
2308 if ((reader == NULL) || (name == NULL))
2309 return(NULL);
2310 if (reader->node == NULL)
2311 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002312 if (reader->curnode != NULL)
2313 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002314
2315 /* TODO: handle the xmlDecl */
2316 if (reader->node->type != XML_ELEMENT_NODE)
2317 return(NULL);
2318
2319 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002320 if (localname == NULL) {
2321 /*
2322 * Namespace default decl
2323 */
2324 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2325 ns = reader->node->nsDef;
2326 while (ns != NULL) {
2327 if (ns->prefix == NULL) {
2328 return(xmlStrdup(ns->href));
2329 }
2330 ns = ns->next;
2331 }
2332 return NULL;
2333 }
2334 return(xmlGetNoNsProp(reader->node, name));
2335 }
2336
2337 /*
2338 * Namespace default decl
2339 */
2340 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2341 ns = reader->node->nsDef;
2342 while (ns != NULL) {
2343 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2344 ret = xmlStrdup(ns->href);
2345 break;
2346 }
2347 ns = ns->next;
2348 }
2349 } else {
2350 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2351 if (ns != NULL)
2352 ret = xmlGetNsProp(reader->node, localname, ns->href);
2353 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002354
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002355 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002356 if (prefix != NULL)
2357 xmlFree(prefix);
2358 return(ret);
2359}
2360
2361
2362/**
2363 * xmlTextReaderGetAttributeNs:
2364 * @reader: the xmlTextReaderPtr used
2365 * @localName: the local name of the attribute.
2366 * @namespaceURI: the namespace URI of the attribute.
2367 *
2368 * Provides the value of the specified attribute
2369 *
2370 * Returns a string containing the value of the specified attribute, or NULL
2371 * in case of error. The string must be deallocated by the caller.
2372 */
2373xmlChar *
2374xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2375 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002376 xmlChar *prefix = NULL;
2377 xmlNsPtr ns;
2378
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002379 if ((reader == NULL) || (localName == NULL))
2380 return(NULL);
2381 if (reader->node == NULL)
2382 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002383 if (reader->curnode != NULL)
2384 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002385
2386 /* TODO: handle the xmlDecl */
2387 if (reader->node->type != XML_ELEMENT_NODE)
2388 return(NULL);
2389
Daniel Veillard45b97e72005-08-20 21:14:28 +00002390 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2391 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2392 prefix = BAD_CAST localName;
2393 }
2394 ns = reader->node->nsDef;
2395 while (ns != NULL) {
2396 if ((prefix == NULL && ns->prefix == NULL) ||
2397 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2398 return xmlStrdup(ns->href);
2399 }
2400 ns = ns->next;
2401 }
2402 return NULL;
2403 }
2404
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002405 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2406}
2407
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002408/**
2409 * xmlTextReaderGetRemainder:
2410 * @reader: the xmlTextReaderPtr used
2411 *
2412 * Method to get the remainder of the buffered XML. this method stops the
2413 * parser, set its state to End Of File and return the input stream with
2414 * what is left that the parser did not use.
2415 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002416 * The implementation is not good, the parser certainly procgressed past
2417 * what's left in reader->input, and there is an allocation problem. Best
2418 * would be to rewrite it differently.
2419 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002420 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2421 * in case of error.
2422 */
2423xmlParserInputBufferPtr
2424xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2425 xmlParserInputBufferPtr ret = NULL;
2426
2427 if (reader == NULL)
2428 return(NULL);
2429 if (reader->node == NULL)
2430 return(NULL);
2431
2432 reader->node = NULL;
2433 reader->curnode = NULL;
2434 reader->mode = XML_TEXTREADER_MODE_EOF;
2435 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002436 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002437 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002438 if (reader->preserve == 0)
2439 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002440 reader->ctxt->myDoc = NULL;
2441 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002442 }
2443 if (reader->allocs & XML_TEXTREADER_INPUT) {
2444 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002445 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002446 reader->allocs -= XML_TEXTREADER_INPUT;
2447 } else {
2448 /*
2449 * Hum, one may need to duplicate the data structure because
2450 * without reference counting the input may be freed twice:
2451 * - by the layer which allocated it.
2452 * - by the layer to which would have been returned to.
2453 */
2454 TODO
2455 return(NULL);
2456 }
2457 return(ret);
2458}
2459
2460/**
2461 * xmlTextReaderLookupNamespace:
2462 * @reader: the xmlTextReaderPtr used
2463 * @prefix: the prefix whose namespace URI is to be resolved. To return
2464 * the default namespace, specify NULL
2465 *
2466 * Resolves a namespace prefix in the scope of the current element.
2467 *
2468 * Returns a string containing the namespace URI to which the prefix maps
2469 * or NULL in case of error. The string must be deallocated by the caller.
2470 */
2471xmlChar *
2472xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2473 xmlNsPtr ns;
2474
2475 if (reader == NULL)
2476 return(NULL);
2477 if (reader->node == NULL)
2478 return(NULL);
2479
2480 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2481 if (ns == NULL)
2482 return(NULL);
2483 return(xmlStrdup(ns->href));
2484}
2485
2486/**
2487 * xmlTextReaderMoveToAttributeNo:
2488 * @reader: the xmlTextReaderPtr used
2489 * @no: the zero-based index of the attribute relative to the containing
2490 * element.
2491 *
2492 * Moves the position of the current instance to the attribute with
2493 * the specified index relative to the containing element.
2494 *
2495 * Returns 1 in case of success, -1 in case of error, 0 if not found
2496 */
2497int
2498xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2499 int i;
2500 xmlAttrPtr cur;
2501 xmlNsPtr ns;
2502
2503 if (reader == NULL)
2504 return(-1);
2505 if (reader->node == NULL)
2506 return(-1);
2507 /* TODO: handle the xmlDecl */
2508 if (reader->node->type != XML_ELEMENT_NODE)
2509 return(-1);
2510
2511 reader->curnode = NULL;
2512
2513 ns = reader->node->nsDef;
2514 for (i = 0;(i < no) && (ns != NULL);i++) {
2515 ns = ns->next;
2516 }
2517 if (ns != NULL) {
2518 reader->curnode = (xmlNodePtr) ns;
2519 return(1);
2520 }
2521
2522 cur = reader->node->properties;
2523 if (cur == NULL)
2524 return(0);
2525 for (;i < no;i++) {
2526 cur = cur->next;
2527 if (cur == NULL)
2528 return(0);
2529 }
2530 /* TODO walk the DTD if present */
2531
2532 reader->curnode = (xmlNodePtr) cur;
2533 return(1);
2534}
2535
2536/**
2537 * xmlTextReaderMoveToAttribute:
2538 * @reader: the xmlTextReaderPtr used
2539 * @name: the qualified name of the attribute.
2540 *
2541 * Moves the position of the current instance to the attribute with
2542 * the specified qualified name.
2543 *
2544 * Returns 1 in case of success, -1 in case of error, 0 if not found
2545 */
2546int
2547xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2548 xmlChar *prefix = NULL;
2549 xmlChar *localname;
2550 xmlNsPtr ns;
2551 xmlAttrPtr prop;
2552
2553 if ((reader == NULL) || (name == NULL))
2554 return(-1);
2555 if (reader->node == NULL)
2556 return(-1);
2557
2558 /* TODO: handle the xmlDecl */
2559 if (reader->node->type != XML_ELEMENT_NODE)
2560 return(0);
2561
2562 localname = xmlSplitQName2(name, &prefix);
2563 if (localname == NULL) {
2564 /*
2565 * Namespace default decl
2566 */
2567 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2568 ns = reader->node->nsDef;
2569 while (ns != NULL) {
2570 if (ns->prefix == NULL) {
2571 reader->curnode = (xmlNodePtr) ns;
2572 return(1);
2573 }
2574 ns = ns->next;
2575 }
2576 return(0);
2577 }
2578
2579 prop = reader->node->properties;
2580 while (prop != NULL) {
2581 /*
2582 * One need to have
2583 * - same attribute names
2584 * - and the attribute carrying that namespace
2585 */
2586 if ((xmlStrEqual(prop->name, name)) &&
2587 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2588 reader->curnode = (xmlNodePtr) prop;
2589 return(1);
2590 }
2591 prop = prop->next;
2592 }
2593 return(0);
2594 }
2595
2596 /*
2597 * Namespace default decl
2598 */
2599 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2600 ns = reader->node->nsDef;
2601 while (ns != NULL) {
2602 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2603 reader->curnode = (xmlNodePtr) ns;
2604 goto found;
2605 }
2606 ns = ns->next;
2607 }
2608 goto not_found;
2609 }
2610 prop = reader->node->properties;
2611 while (prop != NULL) {
2612 /*
2613 * One need to have
2614 * - same attribute names
2615 * - and the attribute carrying that namespace
2616 */
2617 if ((xmlStrEqual(prop->name, localname)) &&
2618 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2619 reader->curnode = (xmlNodePtr) prop;
2620 goto found;
2621 }
2622 prop = prop->next;
2623 }
2624not_found:
2625 if (localname != NULL)
2626 xmlFree(localname);
2627 if (prefix != NULL)
2628 xmlFree(prefix);
2629 return(0);
2630
2631found:
2632 if (localname != NULL)
2633 xmlFree(localname);
2634 if (prefix != NULL)
2635 xmlFree(prefix);
2636 return(1);
2637}
2638
2639/**
2640 * xmlTextReaderMoveToAttributeNs:
2641 * @reader: the xmlTextReaderPtr used
2642 * @localName: the local name of the attribute.
2643 * @namespaceURI: the namespace URI of the attribute.
2644 *
2645 * Moves the position of the current instance to the attribute with the
2646 * specified local name and namespace URI.
2647 *
2648 * Returns 1 in case of success, -1 in case of error, 0 if not found
2649 */
2650int
2651xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2652 const xmlChar *localName, const xmlChar *namespaceURI) {
2653 xmlAttrPtr prop;
2654 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002655 xmlNsPtr ns;
2656 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002657
2658 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2659 return(-1);
2660 if (reader->node == NULL)
2661 return(-1);
2662 if (reader->node->type != XML_ELEMENT_NODE)
2663 return(0);
2664 node = reader->node;
2665
Daniel Veillard45b97e72005-08-20 21:14:28 +00002666 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2667 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2668 prefix = BAD_CAST localName;
2669 }
2670 ns = reader->node->nsDef;
2671 while (ns != NULL) {
2672 if ((prefix == NULL && ns->prefix == NULL) ||
2673 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2674 reader->curnode = (xmlNodePtr) ns;
2675 return(1);
2676 }
2677 ns = ns->next;
2678 }
2679 return(0);
2680 }
2681
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002682 prop = node->properties;
2683 while (prop != NULL) {
2684 /*
2685 * One need to have
2686 * - same attribute names
2687 * - and the attribute carrying that namespace
2688 */
2689 if (xmlStrEqual(prop->name, localName) &&
2690 ((prop->ns != NULL) &&
2691 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2692 reader->curnode = (xmlNodePtr) prop;
2693 return(1);
2694 }
2695 prop = prop->next;
2696 }
2697 return(0);
2698}
2699
2700/**
2701 * xmlTextReaderMoveToFirstAttribute:
2702 * @reader: the xmlTextReaderPtr used
2703 *
2704 * Moves the position of the current instance to the first attribute
2705 * associated with the current node.
2706 *
2707 * Returns 1 in case of success, -1 in case of error, 0 if not found
2708 */
2709int
2710xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2711 if (reader == NULL)
2712 return(-1);
2713 if (reader->node == NULL)
2714 return(-1);
2715 if (reader->node->type != XML_ELEMENT_NODE)
2716 return(0);
2717
2718 if (reader->node->nsDef != NULL) {
2719 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2720 return(1);
2721 }
2722 if (reader->node->properties != NULL) {
2723 reader->curnode = (xmlNodePtr) reader->node->properties;
2724 return(1);
2725 }
2726 return(0);
2727}
2728
2729/**
2730 * xmlTextReaderMoveToNextAttribute:
2731 * @reader: the xmlTextReaderPtr used
2732 *
2733 * Moves the position of the current instance to the next attribute
2734 * associated with the current node.
2735 *
2736 * Returns 1 in case of success, -1 in case of error, 0 if not found
2737 */
2738int
2739xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2740 if (reader == NULL)
2741 return(-1);
2742 if (reader->node == NULL)
2743 return(-1);
2744 if (reader->node->type != XML_ELEMENT_NODE)
2745 return(0);
2746 if (reader->curnode == NULL)
2747 return(xmlTextReaderMoveToFirstAttribute(reader));
2748
2749 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2750 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2751 if (ns->next != NULL) {
2752 reader->curnode = (xmlNodePtr) ns->next;
2753 return(1);
2754 }
2755 if (reader->node->properties != NULL) {
2756 reader->curnode = (xmlNodePtr) reader->node->properties;
2757 return(1);
2758 }
2759 return(0);
2760 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2761 (reader->curnode->next != NULL)) {
2762 reader->curnode = reader->curnode->next;
2763 return(1);
2764 }
2765 return(0);
2766}
2767
2768/**
2769 * xmlTextReaderMoveToElement:
2770 * @reader: the xmlTextReaderPtr used
2771 *
2772 * Moves the position of the current instance to the node that
2773 * contains the current Attribute node.
2774 *
2775 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2776 */
2777int
2778xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2779 if (reader == NULL)
2780 return(-1);
2781 if (reader->node == NULL)
2782 return(-1);
2783 if (reader->node->type != XML_ELEMENT_NODE)
2784 return(0);
2785 if (reader->curnode != NULL) {
2786 reader->curnode = NULL;
2787 return(1);
2788 }
2789 return(0);
2790}
2791
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002792/**
2793 * xmlTextReaderReadAttributeValue:
2794 * @reader: the xmlTextReaderPtr used
2795 *
2796 * Parses an attribute value into one or more Text and EntityReference nodes.
2797 *
2798 * Returns 1 in case of success, 0 if the reader was not positionned on an
2799 * ttribute node or all the attribute values have been read, or -1
2800 * in case of error.
2801 */
2802int
2803xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2804 if (reader == NULL)
2805 return(-1);
2806 if (reader->node == NULL)
2807 return(-1);
2808 if (reader->curnode == NULL)
2809 return(0);
2810 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2811 if (reader->curnode->children == NULL)
2812 return(0);
2813 reader->curnode = reader->curnode->children;
2814 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2815 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2816
2817 if (reader->faketext == NULL) {
2818 reader->faketext = xmlNewDocText(reader->node->doc,
2819 ns->href);
2820 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002821 if ((reader->faketext->content != NULL) &&
2822 (reader->faketext->content !=
2823 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002824 xmlFree(reader->faketext->content);
2825 reader->faketext->content = xmlStrdup(ns->href);
2826 }
2827 reader->curnode = reader->faketext;
2828 } else {
2829 if (reader->curnode->next == NULL)
2830 return(0);
2831 reader->curnode = reader->curnode->next;
2832 }
2833 return(1);
2834}
2835
Daniel Veillarde2811272004-10-19 09:04:23 +00002836/**
2837 * xmlTextReaderConstEncoding:
2838 * @reader: the xmlTextReaderPtr used
2839 *
2840 * Determine the encoding of the document being read.
2841 *
2842 * Returns a string containing the encoding of the document or NULL in
2843 * case of error. The string is deallocated with the reader.
2844 */
2845const xmlChar *
2846xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2847 xmlDocPtr doc = NULL;
2848 if (reader == NULL)
2849 return(NULL);
2850 if (reader->doc != NULL)
2851 doc = reader->doc;
2852 else if (reader->ctxt != NULL)
2853 doc = reader->ctxt->myDoc;
2854 if (doc == NULL)
2855 return(NULL);
2856
2857 if (doc->encoding == NULL)
2858 return(NULL);
2859 else
2860 return(CONSTSTR(doc->encoding));
2861}
2862
2863
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002864/************************************************************************
2865 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002866 * Acces API to the current node *
2867 * *
2868 ************************************************************************/
2869/**
2870 * xmlTextReaderAttributeCount:
2871 * @reader: the xmlTextReaderPtr used
2872 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002873 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002874 *
2875 * Returns 0 i no attributes, -1 in case of error or the attribute count
2876 */
2877int
2878xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2879 int ret;
2880 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002881 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002882 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002883
2884 if (reader == NULL)
2885 return(-1);
2886 if (reader->node == NULL)
2887 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002888
2889 if (reader->curnode != NULL)
2890 node = reader->curnode;
2891 else
2892 node = reader->node;
2893
2894 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002895 return(0);
2896 if ((reader->state == XML_TEXTREADER_END) ||
2897 (reader->state == XML_TEXTREADER_BACKTRACK))
2898 return(0);
2899 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002900 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002901 while (attr != NULL) {
2902 ret++;
2903 attr = attr->next;
2904 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002905 ns = node->nsDef;
2906 while (ns != NULL) {
2907 ret++;
2908 ns = ns->next;
2909 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002910 return(ret);
2911}
2912
2913/**
2914 * xmlTextReaderNodeType:
2915 * @reader: the xmlTextReaderPtr used
2916 *
2917 * Get the node type of the current node
2918 * Reference:
2919 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2920 *
2921 * Returns the xmlNodeType of the current node or -1 in case of error
2922 */
2923int
2924xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002925 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002926
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002927 if (reader == NULL)
2928 return(-1);
2929 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002930 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002931 if (reader->curnode != NULL)
2932 node = reader->curnode;
2933 else
2934 node = reader->node;
2935 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002936 case XML_ELEMENT_NODE:
2937 if ((reader->state == XML_TEXTREADER_END) ||
2938 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002939 return(XML_READER_TYPE_END_ELEMENT);
2940 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002941 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002942 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002943 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002944 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002945 if (xmlIsBlankNode(reader->node)) {
2946 if (xmlNodeGetSpacePreserve(reader->node))
2947 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2948 else
2949 return(XML_READER_TYPE_WHITESPACE);
2950 } else {
2951 return(XML_READER_TYPE_TEXT);
2952 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002953 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002954 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002955 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002956 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002957 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002958 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002959 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002960 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002962 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002963 case XML_DOCUMENT_NODE:
2964 case XML_HTML_DOCUMENT_NODE:
2965#ifdef LIBXML_DOCB_ENABLED
2966 case XML_DOCB_DOCUMENT_NODE:
2967#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002968 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002969 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002970 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002971 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002972 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002973 case XML_DOCUMENT_TYPE_NODE:
2974 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002975 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002976
2977 case XML_ELEMENT_DECL:
2978 case XML_ATTRIBUTE_DECL:
2979 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002980 case XML_XINCLUDE_START:
2981 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002982 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002983 }
2984 return(-1);
2985}
2986
2987/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002988 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002989 * @reader: the xmlTextReaderPtr used
2990 *
2991 * Check if the current node is empty
2992 *
2993 * Returns 1 if empty, 0 if not and -1 in case of error
2994 */
2995int
2996xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2997 if ((reader == NULL) || (reader->node == NULL))
2998 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002999 if (reader->node->type != XML_ELEMENT_NODE)
3000 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003001 if (reader->curnode != NULL)
3002 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003003 if (reader->node->children != NULL)
3004 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003005 if (reader->state == XML_TEXTREADER_END)
3006 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003007 if (reader->doc != NULL)
3008 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003009#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003010 if (reader->in_xinclude > 0)
3011 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003012#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003013 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003014}
3015
3016/**
3017 * xmlTextReaderLocalName:
3018 * @reader: the xmlTextReaderPtr used
3019 *
3020 * The local name of the node.
3021 *
3022 * Returns the local name or NULL if not available
3023 */
3024xmlChar *
3025xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003026 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003027 if ((reader == NULL) || (reader->node == NULL))
3028 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003029 if (reader->curnode != NULL)
3030 node = reader->curnode;
3031 else
3032 node = reader->node;
3033 if (node->type == XML_NAMESPACE_DECL) {
3034 xmlNsPtr ns = (xmlNsPtr) node;
3035 if (ns->prefix == NULL)
3036 return(xmlStrdup(BAD_CAST "xmlns"));
3037 else
3038 return(xmlStrdup(ns->prefix));
3039 }
3040 if ((node->type != XML_ELEMENT_NODE) &&
3041 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003042 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003043 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003044}
3045
3046/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003047 * xmlTextReaderConstLocalName:
3048 * @reader: the xmlTextReaderPtr used
3049 *
3050 * The local name of the node.
3051 *
3052 * Returns the local name or NULL if not available, the
3053 * string will be deallocated with the reader.
3054 */
3055const xmlChar *
3056xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3057 xmlNodePtr node;
3058 if ((reader == NULL) || (reader->node == NULL))
3059 return(NULL);
3060 if (reader->curnode != NULL)
3061 node = reader->curnode;
3062 else
3063 node = reader->node;
3064 if (node->type == XML_NAMESPACE_DECL) {
3065 xmlNsPtr ns = (xmlNsPtr) node;
3066 if (ns->prefix == NULL)
3067 return(CONSTSTR(BAD_CAST "xmlns"));
3068 else
3069 return(ns->prefix);
3070 }
3071 if ((node->type != XML_ELEMENT_NODE) &&
3072 (node->type != XML_ATTRIBUTE_NODE))
3073 return(xmlTextReaderConstName(reader));
3074 return(node->name);
3075}
3076
3077/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003078 * xmlTextReaderName:
3079 * @reader: the xmlTextReaderPtr used
3080 *
3081 * The qualified name of the node, equal to Prefix :LocalName.
3082 *
3083 * Returns the local name or NULL if not available
3084 */
3085xmlChar *
3086xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003087 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003088 xmlChar *ret;
3089
3090 if ((reader == NULL) || (reader->node == NULL))
3091 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003092 if (reader->curnode != NULL)
3093 node = reader->curnode;
3094 else
3095 node = reader->node;
3096 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003097 case XML_ELEMENT_NODE:
3098 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003099 if ((node->ns == NULL) ||
3100 (node->ns->prefix == NULL))
3101 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003102
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003103 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003104 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003105 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003106 return(ret);
3107 case XML_TEXT_NODE:
3108 return(xmlStrdup(BAD_CAST "#text"));
3109 case XML_CDATA_SECTION_NODE:
3110 return(xmlStrdup(BAD_CAST "#cdata-section"));
3111 case XML_ENTITY_NODE:
3112 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003113 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003114 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003115 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003116 case XML_COMMENT_NODE:
3117 return(xmlStrdup(BAD_CAST "#comment"));
3118 case XML_DOCUMENT_NODE:
3119 case XML_HTML_DOCUMENT_NODE:
3120#ifdef LIBXML_DOCB_ENABLED
3121 case XML_DOCB_DOCUMENT_NODE:
3122#endif
3123 return(xmlStrdup(BAD_CAST "#document"));
3124 case XML_DOCUMENT_FRAG_NODE:
3125 return(xmlStrdup(BAD_CAST "#document-fragment"));
3126 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003127 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003128 case XML_DOCUMENT_TYPE_NODE:
3129 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003130 return(xmlStrdup(node->name));
3131 case XML_NAMESPACE_DECL: {
3132 xmlNsPtr ns = (xmlNsPtr) node;
3133
3134 ret = xmlStrdup(BAD_CAST "xmlns");
3135 if (ns->prefix == NULL)
3136 return(ret);
3137 ret = xmlStrcat(ret, BAD_CAST ":");
3138 ret = xmlStrcat(ret, ns->prefix);
3139 return(ret);
3140 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003141
3142 case XML_ELEMENT_DECL:
3143 case XML_ATTRIBUTE_DECL:
3144 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003145 case XML_XINCLUDE_START:
3146 case XML_XINCLUDE_END:
3147 return(NULL);
3148 }
3149 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003150}
3151
3152/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003153 * xmlTextReaderConstName:
3154 * @reader: the xmlTextReaderPtr used
3155 *
3156 * The qualified name of the node, equal to Prefix :LocalName.
3157 *
3158 * Returns the local name or NULL if not available, the string is
3159 * deallocated with the reader.
3160 */
3161const xmlChar *
3162xmlTextReaderConstName(xmlTextReaderPtr reader) {
3163 xmlNodePtr node;
3164
3165 if ((reader == NULL) || (reader->node == NULL))
3166 return(NULL);
3167 if (reader->curnode != NULL)
3168 node = reader->curnode;
3169 else
3170 node = reader->node;
3171 switch (node->type) {
3172 case XML_ELEMENT_NODE:
3173 case XML_ATTRIBUTE_NODE:
3174 if ((node->ns == NULL) ||
3175 (node->ns->prefix == NULL))
3176 return(node->name);
3177 return(CONSTQSTR(node->ns->prefix, node->name));
3178 case XML_TEXT_NODE:
3179 return(CONSTSTR(BAD_CAST "#text"));
3180 case XML_CDATA_SECTION_NODE:
3181 return(CONSTSTR(BAD_CAST "#cdata-section"));
3182 case XML_ENTITY_NODE:
3183 case XML_ENTITY_REF_NODE:
3184 return(CONSTSTR(node->name));
3185 case XML_PI_NODE:
3186 return(CONSTSTR(node->name));
3187 case XML_COMMENT_NODE:
3188 return(CONSTSTR(BAD_CAST "#comment"));
3189 case XML_DOCUMENT_NODE:
3190 case XML_HTML_DOCUMENT_NODE:
3191#ifdef LIBXML_DOCB_ENABLED
3192 case XML_DOCB_DOCUMENT_NODE:
3193#endif
3194 return(CONSTSTR(BAD_CAST "#document"));
3195 case XML_DOCUMENT_FRAG_NODE:
3196 return(CONSTSTR(BAD_CAST "#document-fragment"));
3197 case XML_NOTATION_NODE:
3198 return(CONSTSTR(node->name));
3199 case XML_DOCUMENT_TYPE_NODE:
3200 case XML_DTD_NODE:
3201 return(CONSTSTR(node->name));
3202 case XML_NAMESPACE_DECL: {
3203 xmlNsPtr ns = (xmlNsPtr) node;
3204
3205 if (ns->prefix == NULL)
3206 return(CONSTSTR(BAD_CAST "xmlns"));
3207 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3208 }
3209
3210 case XML_ELEMENT_DECL:
3211 case XML_ATTRIBUTE_DECL:
3212 case XML_ENTITY_DECL:
3213 case XML_XINCLUDE_START:
3214 case XML_XINCLUDE_END:
3215 return(NULL);
3216 }
3217 return(NULL);
3218}
3219
3220/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003221 * xmlTextReaderPrefix:
3222 * @reader: the xmlTextReaderPtr used
3223 *
3224 * A shorthand reference to the namespace associated with the node.
3225 *
3226 * Returns the prefix or NULL if not available
3227 */
3228xmlChar *
3229xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003230 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003231 if ((reader == NULL) || (reader->node == NULL))
3232 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003233 if (reader->curnode != NULL)
3234 node = reader->curnode;
3235 else
3236 node = reader->node;
3237 if (node->type == XML_NAMESPACE_DECL) {
3238 xmlNsPtr ns = (xmlNsPtr) node;
3239 if (ns->prefix == NULL)
3240 return(NULL);
3241 return(xmlStrdup(BAD_CAST "xmlns"));
3242 }
3243 if ((node->type != XML_ELEMENT_NODE) &&
3244 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003245 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003246 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003247 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003248 return(NULL);
3249}
3250
3251/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003252 * xmlTextReaderConstPrefix:
3253 * @reader: the xmlTextReaderPtr used
3254 *
3255 * A shorthand reference to the namespace associated with the node.
3256 *
3257 * Returns the prefix or NULL if not available, the string is deallocated
3258 * with the reader.
3259 */
3260const xmlChar *
3261xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3262 xmlNodePtr node;
3263 if ((reader == NULL) || (reader->node == NULL))
3264 return(NULL);
3265 if (reader->curnode != NULL)
3266 node = reader->curnode;
3267 else
3268 node = reader->node;
3269 if (node->type == XML_NAMESPACE_DECL) {
3270 xmlNsPtr ns = (xmlNsPtr) node;
3271 if (ns->prefix == NULL)
3272 return(NULL);
3273 return(CONSTSTR(BAD_CAST "xmlns"));
3274 }
3275 if ((node->type != XML_ELEMENT_NODE) &&
3276 (node->type != XML_ATTRIBUTE_NODE))
3277 return(NULL);
3278 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3279 return(CONSTSTR(node->ns->prefix));
3280 return(NULL);
3281}
3282
3283/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003284 * xmlTextReaderNamespaceUri:
3285 * @reader: the xmlTextReaderPtr used
3286 *
3287 * The URI defining the namespace associated with the node.
3288 *
3289 * Returns the namespace URI or NULL if not available
3290 */
3291xmlChar *
3292xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003293 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003294 if ((reader == NULL) || (reader->node == NULL))
3295 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003296 if (reader->curnode != NULL)
3297 node = reader->curnode;
3298 else
3299 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003300 if (node->type == XML_NAMESPACE_DECL)
3301 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003302 if ((node->type != XML_ELEMENT_NODE) &&
3303 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003304 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003305 if (node->ns != NULL)
3306 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003307 return(NULL);
3308}
3309
3310/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003311 * xmlTextReaderConstNamespaceUri:
3312 * @reader: the xmlTextReaderPtr used
3313 *
3314 * The URI defining the namespace associated with the node.
3315 *
3316 * Returns the namespace URI or NULL if not available, the string
3317 * will be deallocated with the reader
3318 */
3319const xmlChar *
3320xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3321 xmlNodePtr node;
3322 if ((reader == NULL) || (reader->node == NULL))
3323 return(NULL);
3324 if (reader->curnode != NULL)
3325 node = reader->curnode;
3326 else
3327 node = reader->node;
3328 if (node->type == XML_NAMESPACE_DECL)
3329 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3330 if ((node->type != XML_ELEMENT_NODE) &&
3331 (node->type != XML_ATTRIBUTE_NODE))
3332 return(NULL);
3333 if (node->ns != NULL)
3334 return(CONSTSTR(node->ns->href));
3335 return(NULL);
3336}
3337
3338/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003339 * xmlTextReaderBaseUri:
3340 * @reader: the xmlTextReaderPtr used
3341 *
3342 * The base URI of the node.
3343 *
3344 * Returns the base URI or NULL if not available
3345 */
3346xmlChar *
3347xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3348 if ((reader == NULL) || (reader->node == NULL))
3349 return(NULL);
3350 return(xmlNodeGetBase(NULL, reader->node));
3351}
3352
3353/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003354 * xmlTextReaderConstBaseUri:
3355 * @reader: the xmlTextReaderPtr used
3356 *
3357 * The base URI of the node.
3358 *
3359 * Returns the base URI or NULL if not available, the string
3360 * will be deallocated with the reader
3361 */
3362const xmlChar *
3363xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3364 xmlChar *tmp;
3365 const xmlChar *ret;
3366
3367 if ((reader == NULL) || (reader->node == NULL))
3368 return(NULL);
3369 tmp = xmlNodeGetBase(NULL, reader->node);
3370 if (tmp == NULL)
3371 return(NULL);
3372 ret = CONSTSTR(tmp);
3373 xmlFree(tmp);
3374 return(ret);
3375}
3376
3377/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003378 * xmlTextReaderDepth:
3379 * @reader: the xmlTextReaderPtr used
3380 *
3381 * The depth of the node in the tree.
3382 *
3383 * Returns the depth or -1 in case of error
3384 */
3385int
3386xmlTextReaderDepth(xmlTextReaderPtr reader) {
3387 if (reader == NULL)
3388 return(-1);
3389 if (reader->node == NULL)
3390 return(0);
3391
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003392 if (reader->curnode != NULL) {
3393 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3394 (reader->curnode->type == XML_NAMESPACE_DECL))
3395 return(reader->depth + 1);
3396 return(reader->depth + 2);
3397 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003398 return(reader->depth);
3399}
3400
3401/**
3402 * xmlTextReaderHasAttributes:
3403 * @reader: the xmlTextReaderPtr used
3404 *
3405 * Whether the node has attributes.
3406 *
3407 * Returns 1 if true, 0 if false, and -1 in case or error
3408 */
3409int
3410xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003411 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003412 if (reader == NULL)
3413 return(-1);
3414 if (reader->node == NULL)
3415 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003416 if (reader->curnode != NULL)
3417 node = reader->curnode;
3418 else
3419 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003420
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003421 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003422 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003423 return(1);
3424 /* TODO: handle the xmlDecl */
3425 return(0);
3426}
3427
3428/**
3429 * xmlTextReaderHasValue:
3430 * @reader: the xmlTextReaderPtr used
3431 *
3432 * Whether the node can have a text value.
3433 *
3434 * Returns 1 if true, 0 if false, and -1 in case or error
3435 */
3436int
3437xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003438 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003439 if (reader == NULL)
3440 return(-1);
3441 if (reader->node == NULL)
3442 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003443 if (reader->curnode != NULL)
3444 node = reader->curnode;
3445 else
3446 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003447
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003448 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003449 case XML_ATTRIBUTE_NODE:
3450 case XML_TEXT_NODE:
3451 case XML_CDATA_SECTION_NODE:
3452 case XML_PI_NODE:
3453 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003454 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003455 return(1);
3456 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003457 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003458 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003459 return(0);
3460}
3461
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003462/**
3463 * xmlTextReaderValue:
3464 * @reader: the xmlTextReaderPtr used
3465 *
3466 * Provides the text value of the node if present
3467 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003468 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003469 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003470 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003471xmlChar *
3472xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003473 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003474 if (reader == NULL)
3475 return(NULL);
3476 if (reader->node == NULL)
3477 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003478 if (reader->curnode != NULL)
3479 node = reader->curnode;
3480 else
3481 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003482
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003483 switch (node->type) {
3484 case XML_NAMESPACE_DECL:
3485 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003486 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003487 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003488
3489 if (attr->parent != NULL)
3490 return (xmlNodeListGetString
3491 (attr->parent->doc, attr->children, 1));
3492 else
3493 return (xmlNodeListGetString(NULL, attr->children, 1));
3494 break;
3495 }
3496 case XML_TEXT_NODE:
3497 case XML_CDATA_SECTION_NODE:
3498 case XML_PI_NODE:
3499 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003500 if (node->content != NULL)
3501 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003502 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003503 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003504 }
3505 return(NULL);
3506}
3507
3508/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003509 * xmlTextReaderConstValue:
3510 * @reader: the xmlTextReaderPtr used
3511 *
3512 * Provides the text value of the node if present
3513 *
3514 * Returns the string or NULL if not available. The result will be
3515 * deallocated on the next Read() operation.
3516 */
3517const xmlChar *
3518xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3519 xmlNodePtr node;
3520 if (reader == NULL)
3521 return(NULL);
3522 if (reader->node == NULL)
3523 return(NULL);
3524 if (reader->curnode != NULL)
3525 node = reader->curnode;
3526 else
3527 node = reader->node;
3528
3529 switch (node->type) {
3530 case XML_NAMESPACE_DECL:
3531 return(((xmlNsPtr) node)->href);
3532 case XML_ATTRIBUTE_NODE:{
3533 xmlAttrPtr attr = (xmlAttrPtr) node;
3534
3535 if ((attr->children != NULL) &&
3536 (attr->children->type == XML_TEXT_NODE) &&
3537 (attr->children->next == NULL))
3538 return(attr->children->content);
3539 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003540 if (reader->buffer == NULL)
3541 reader->buffer = xmlBufferCreateSize(100);
3542 if (reader->buffer == NULL) {
3543 xmlGenericError(xmlGenericErrorContext,
3544 "xmlTextReaderSetup : malloc failed\n");
3545 return (NULL);
3546 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003547 reader->buffer->use = 0;
3548 xmlNodeBufGetContent(reader->buffer, node);
3549 return(reader->buffer->content);
3550 }
3551 break;
3552 }
3553 case XML_TEXT_NODE:
3554 case XML_CDATA_SECTION_NODE:
3555 case XML_PI_NODE:
3556 case XML_COMMENT_NODE:
3557 return(node->content);
3558 default:
3559 break;
3560 }
3561 return(NULL);
3562}
3563
3564/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003565 * xmlTextReaderIsDefault:
3566 * @reader: the xmlTextReaderPtr used
3567 *
3568 * Whether an Attribute node was generated from the default value
3569 * defined in the DTD or schema.
3570 *
3571 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3572 */
3573int
3574xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3575 if (reader == NULL)
3576 return(-1);
3577 return(0);
3578}
3579
3580/**
3581 * xmlTextReaderQuoteChar:
3582 * @reader: the xmlTextReaderPtr used
3583 *
3584 * The quotation mark character used to enclose the value of an attribute.
3585 *
3586 * Returns " or ' and -1 in case of error
3587 */
3588int
3589xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3590 if (reader == NULL)
3591 return(-1);
3592 /* TODO maybe lookup the attribute value for " first */
3593 return((int) '"');
3594}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003595
3596/**
3597 * xmlTextReaderXmlLang:
3598 * @reader: the xmlTextReaderPtr used
3599 *
3600 * The xml:lang scope within which the node resides.
3601 *
3602 * Returns the xml:lang value or NULL if none exists.
3603 */
3604xmlChar *
3605xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3606 if (reader == NULL)
3607 return(NULL);
3608 if (reader->node == NULL)
3609 return(NULL);
3610 return(xmlNodeGetLang(reader->node));
3611}
3612
Daniel Veillard67df8092002-12-16 22:04:11 +00003613/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003614 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003615 * @reader: the xmlTextReaderPtr used
3616 *
3617 * The xml:lang scope within which the node resides.
3618 *
3619 * Returns the xml:lang value or NULL if none exists.
3620 */
3621const xmlChar *
3622xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3623 xmlChar *tmp;
3624 const xmlChar *ret;
3625
3626 if (reader == NULL)
3627 return(NULL);
3628 if (reader->node == NULL)
3629 return(NULL);
3630 tmp = xmlNodeGetLang(reader->node);
3631 if (tmp == NULL)
3632 return(NULL);
3633 ret = CONSTSTR(tmp);
3634 xmlFree(tmp);
3635 return(ret);
3636}
3637
3638/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003639 * xmlTextReaderConstString:
3640 * @reader: the xmlTextReaderPtr used
3641 * @str: the string to intern.
3642 *
3643 * Get an interned string from the reader, allows for example to
3644 * speedup string name comparisons
3645 *
3646 * Returns an interned copy of the string or NULL in case of error. The
3647 * string will be deallocated with the reader.
3648 */
3649const xmlChar *
3650xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3651 if (reader == NULL)
3652 return(NULL);
3653 return(CONSTSTR(str));
3654}
3655
3656/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003657 * xmlTextReaderNormalization:
3658 * @reader: the xmlTextReaderPtr used
3659 *
3660 * The value indicating whether to normalize white space and attribute values.
3661 * Since attribute value and end of line normalizations are a MUST in the XML
3662 * specification only the value true is accepted. The broken bahaviour of
3663 * accepting out of range character entities like &#0; is of course not
3664 * supported either.
3665 *
3666 * Returns 1 or -1 in case of error.
3667 */
3668int
3669xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3670 if (reader == NULL)
3671 return(-1);
3672 return(1);
3673}
3674
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003675/************************************************************************
3676 * *
3677 * Extensions to the base APIs *
3678 * *
3679 ************************************************************************/
3680
3681/**
3682 * xmlTextReaderSetParserProp:
3683 * @reader: the xmlTextReaderPtr used
3684 * @prop: the xmlParserProperties to set
3685 * @value: usually 0 or 1 to (de)activate it
3686 *
3687 * Change the parser processing behaviour by changing some of its internal
3688 * properties. Note that some properties can only be changed before any
3689 * read has been done.
3690 *
3691 * Returns 0 if the call was successful, or -1 in case of error
3692 */
3693int
3694xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3695 xmlParserProperties p = (xmlParserProperties) prop;
3696 xmlParserCtxtPtr ctxt;
3697
3698 if ((reader == NULL) || (reader->ctxt == NULL))
3699 return(-1);
3700 ctxt = reader->ctxt;
3701
3702 switch (p) {
3703 case XML_PARSER_LOADDTD:
3704 if (value != 0) {
3705 if (ctxt->loadsubset == 0) {
3706 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3707 return(-1);
3708 ctxt->loadsubset = XML_DETECT_IDS;
3709 }
3710 } else {
3711 ctxt->loadsubset = 0;
3712 }
3713 return(0);
3714 case XML_PARSER_DEFAULTATTRS:
3715 if (value != 0) {
3716 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3717 } else {
3718 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3719 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3720 }
3721 return(0);
3722 case XML_PARSER_VALIDATE:
3723 if (value != 0) {
3724 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003725 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003726 } else {
3727 ctxt->validate = 0;
3728 }
3729 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003730 case XML_PARSER_SUBST_ENTITIES:
3731 if (value != 0) {
3732 ctxt->replaceEntities = 1;
3733 } else {
3734 ctxt->replaceEntities = 0;
3735 }
3736 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003737 }
3738 return(-1);
3739}
3740
3741/**
3742 * xmlTextReaderGetParserProp:
3743 * @reader: the xmlTextReaderPtr used
3744 * @prop: the xmlParserProperties to get
3745 *
3746 * Read the parser internal property.
3747 *
3748 * Returns the value, usually 0 or 1, or -1 in case of error.
3749 */
3750int
3751xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3752 xmlParserProperties p = (xmlParserProperties) prop;
3753 xmlParserCtxtPtr ctxt;
3754
3755 if ((reader == NULL) || (reader->ctxt == NULL))
3756 return(-1);
3757 ctxt = reader->ctxt;
3758
3759 switch (p) {
3760 case XML_PARSER_LOADDTD:
3761 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3762 return(1);
3763 return(0);
3764 case XML_PARSER_DEFAULTATTRS:
3765 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3766 return(1);
3767 return(0);
3768 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003769 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003770 case XML_PARSER_SUBST_ENTITIES:
3771 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003772 }
3773 return(-1);
3774}
3775
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003776
Daniel Veillarde18fc182002-12-28 22:56:33 +00003777/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003778 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003779 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003780 *
3781 * Provide the line number of the current parsing point.
3782 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003783 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003784 */
3785int
3786xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3787{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003788 if ((reader == NULL) || (reader->ctxt == NULL) ||
3789 (reader->ctxt->input == NULL)) {
3790 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003791 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003792 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003793}
3794
3795/**
3796 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003797 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003798 *
3799 * Provide the column number of the current parsing point.
3800 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003801 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003802 */
3803int
3804xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3805{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003806 if ((reader == NULL) || (reader->ctxt == NULL) ||
3807 (reader->ctxt->input == NULL)) {
3808 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003809 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003810 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003811}
3812
3813/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003814 * xmlTextReaderCurrentNode:
3815 * @reader: the xmlTextReaderPtr used
3816 *
3817 * Hacking interface allowing to get the xmlNodePtr correponding to the
3818 * current node being accessed by the xmlTextReader. This is dangerous
3819 * because the underlying node may be destroyed on the next Reads.
3820 *
3821 * Returns the xmlNodePtr or NULL in case of error.
3822 */
3823xmlNodePtr
3824xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3825 if (reader == NULL)
3826 return(NULL);
3827
3828 if (reader->curnode != NULL)
3829 return(reader->curnode);
3830 return(reader->node);
3831}
3832
3833/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003834 * xmlTextReaderPreserve:
3835 * @reader: the xmlTextReaderPtr used
3836 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003837 * This tells the XML Reader to preserve the current node.
3838 * The caller must also use xmlTextReaderCurrentDoc() to
3839 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003840 *
3841 * Returns the xmlNodePtr or NULL in case of error.
3842 */
3843xmlNodePtr
3844xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3845 xmlNodePtr cur, parent;
3846
3847 if (reader == NULL)
3848 return(NULL);
3849
3850 if (reader->curnode != NULL)
3851 cur = reader->curnode;
3852 else
3853 cur = reader->node;
3854 if (cur == NULL)
3855 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003856
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003857 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003858 cur->extra |= NODE_IS_PRESERVED;
3859 cur->extra |= NODE_IS_SPRESERVED;
3860 }
3861 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003862
3863 parent = cur->parent;;
3864 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003865 if (parent->type == XML_ELEMENT_NODE)
3866 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003867 parent = parent->parent;
3868 }
3869 return(cur);
3870}
3871
Daniel Veillard1e906612003-12-05 14:57:46 +00003872#ifdef LIBXML_PATTERN_ENABLED
3873/**
3874 * xmlTextReaderPreservePattern:
3875 * @reader: the xmlTextReaderPtr used
3876 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003877 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003878 *
3879 * This tells the XML Reader to preserve all nodes matched by the
3880 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3881 * keep an handle on the resulting document once parsing has finished
3882 *
3883 * Returns a positive number in case of success and -1 in case of error
3884 */
3885int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003886xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3887 const xmlChar **namespaces)
3888{
Daniel Veillard1e906612003-12-05 14:57:46 +00003889 xmlPatternPtr comp;
3890
3891 if ((reader == NULL) || (pattern == NULL))
3892 return(-1);
3893
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003894 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003895 if (comp == NULL)
3896 return(-1);
3897
3898 if (reader->patternMax <= 0) {
3899 reader->patternMax = 4;
3900 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3901 sizeof(reader->patternTab[0]));
3902 if (reader->patternTab == NULL) {
3903 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3904 return (-1);
3905 }
3906 }
3907 if (reader->patternNr >= reader->patternMax) {
3908 xmlPatternPtr *tmp;
3909 reader->patternMax *= 2;
3910 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3911 reader->patternMax *
3912 sizeof(reader->patternTab[0]));
3913 if (tmp == NULL) {
3914 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3915 reader->patternMax /= 2;
3916 return (-1);
3917 }
3918 reader->patternTab = tmp;
3919 }
3920 reader->patternTab[reader->patternNr] = comp;
3921 return(reader->patternNr++);
3922}
3923#endif
3924
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003925/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003926 * xmlTextReaderCurrentDoc:
3927 * @reader: the xmlTextReaderPtr used
3928 *
3929 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003930 * current document being accessed by the xmlTextReader.
3931 * NOTE: as a result of this call, the reader will not destroy the
3932 * associated XML document and calling xmlFreeDoc() on the result
3933 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003934 *
3935 * Returns the xmlDocPtr or NULL in case of error.
3936 */
3937xmlDocPtr
3938xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003939 if (reader == NULL)
3940 return(NULL);
3941 if (reader->doc != NULL)
3942 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003943 if ((reader == NULL) || (reader->ctxt == NULL) ||
3944 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003945 return(NULL);
3946
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003947 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003948 return(reader->ctxt->myDoc);
3949}
3950
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003951#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003952
3953static char *
3954xmlTextReaderBuildMessage(const char *msg, va_list ap);
3955
Daniel Veillardffa3c742005-07-21 13:24:09 +00003956static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003957xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3958
Daniel Veillardffa3c742005-07-21 13:24:09 +00003959static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003960xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3961
Daniel Veillardffa3c742005-07-21 13:24:09 +00003962static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003963{
3964 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3965 char * str;
3966 va_list ap;
3967
3968 va_start(ap,msg);
3969 str = xmlTextReaderBuildMessage(msg,ap);
3970 if (!reader->errorFunc) {
3971 xmlTextReaderValidityError(ctx, "%s", str);
3972 } else {
3973 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3974 }
3975 if (str != NULL)
3976 xmlFree(str);
3977 va_end(ap);
3978}
3979
Daniel Veillardffa3c742005-07-21 13:24:09 +00003980static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003981{
3982 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3983 char * str;
3984 va_list ap;
3985
3986 va_start(ap,msg);
3987 str = xmlTextReaderBuildMessage(msg,ap);
3988 if (!reader->errorFunc) {
3989 xmlTextReaderValidityWarning(ctx, "%s", str);
3990 } else {
3991 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3992 }
3993 if (str != NULL)
3994 xmlFree(str);
3995 va_end(ap);
3996}
3997
3998static void
3999xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4000
4001static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4002{
4003 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4004
4005 if (reader->sErrorFunc) {
4006 reader->sErrorFunc(reader->errorFuncArg, error);
4007 } else {
4008 xmlTextReaderStructuredError(reader, error);
4009 }
4010}
4011
Daniel Veillardf4e55762003-04-15 23:32:22 +00004012/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004013 * xmlTextReaderRelaxNGSetSchema:
4014 * @reader: the xmlTextReaderPtr used
4015 * @schema: a precompiled RelaxNG schema
4016 *
4017 * Use RelaxNG to validate the document as it is processed.
4018 * Activation is only possible before the first Read().
4019 * if @schema is NULL, then RelaxNG validation is desactivated.
4020 @ The @schema should not be freed until the reader is deallocated
4021 * or its use has been deactivated.
4022 *
4023 * Returns 0 in case the RelaxNG validation could be (des)activated and
4024 * -1 in case of error.
4025 */
4026int
4027xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004028 if (reader == NULL)
4029 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004030 if (schema == NULL) {
4031 if (reader->rngSchemas != NULL) {
4032 xmlRelaxNGFree(reader->rngSchemas);
4033 reader->rngSchemas = NULL;
4034 }
4035 if (reader->rngValidCtxt != NULL) {
4036 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4037 reader->rngValidCtxt = NULL;
4038 }
4039 return(0);
4040 }
4041 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4042 return(-1);
4043 if (reader->rngSchemas != NULL) {
4044 xmlRelaxNGFree(reader->rngSchemas);
4045 reader->rngSchemas = NULL;
4046 }
4047 if (reader->rngValidCtxt != NULL) {
4048 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4049 reader->rngValidCtxt = NULL;
4050 }
4051 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4052 if (reader->rngValidCtxt == NULL)
4053 return(-1);
4054 if (reader->errorFunc != NULL) {
4055 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004056 xmlTextReaderValidityErrorRelay,
4057 xmlTextReaderValidityWarningRelay,
4058 reader);
4059 }
4060 if (reader->sErrorFunc != NULL) {
4061 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4062 xmlTextReaderValidityStructuredRelay,
4063 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004064 }
4065 reader->rngValidErrors = 0;
4066 reader->rngFullNode = NULL;
4067 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4068 return(0);
4069}
4070
4071/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004072 * xmlTextReaderSetSchema:
4073 * @reader: the xmlTextReaderPtr used
4074 * @schema: a precompiled Schema schema
4075 *
4076 * Use XSD Schema to validate the document as it is processed.
4077 * Activation is only possible before the first Read().
4078 * if @schema is NULL, then Schema validation is desactivated.
4079 @ The @schema should not be freed until the reader is deallocated
4080 * or its use has been deactivated.
4081 *
4082 * Returns 0 in case the Schema validation could be (des)activated and
4083 * -1 in case of error.
4084 */
4085int
4086xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4087 if (reader == NULL)
4088 return(-1);
4089 if (schema == NULL) {
4090 if (reader->xsdPlug != NULL) {
4091 xmlSchemaSAXUnplug(reader->xsdPlug);
4092 reader->xsdPlug = NULL;
4093 }
4094 if (reader->xsdValidCtxt != NULL) {
4095 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4096 reader->xsdValidCtxt = NULL;
4097 }
4098 if (reader->xsdSchemas != NULL) {
4099 xmlSchemaFree(reader->xsdSchemas);
4100 reader->xsdSchemas = NULL;
4101 }
4102 return(0);
4103 }
4104 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4105 return(-1);
4106 if (reader->xsdPlug != NULL) {
4107 xmlSchemaSAXUnplug(reader->xsdPlug);
4108 reader->xsdPlug = NULL;
4109 }
4110 if (reader->xsdValidCtxt != NULL) {
4111 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4112 reader->xsdValidCtxt = NULL;
4113 }
4114 if (reader->xsdSchemas != NULL) {
4115 xmlSchemaFree(reader->xsdSchemas);
4116 reader->xsdSchemas = NULL;
4117 }
4118 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4119 if (reader->xsdValidCtxt == NULL) {
4120 xmlSchemaFree(reader->xsdSchemas);
4121 reader->xsdSchemas = NULL;
4122 return(-1);
4123 }
4124 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4125 &(reader->ctxt->sax),
4126 &(reader->ctxt->userData));
4127 if (reader->xsdPlug == NULL) {
4128 xmlSchemaFree(reader->xsdSchemas);
4129 reader->xsdSchemas = NULL;
4130 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4131 reader->xsdValidCtxt = NULL;
4132 return(-1);
4133 }
4134 if (reader->errorFunc != NULL) {
4135 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004136 xmlTextReaderValidityErrorRelay,
4137 xmlTextReaderValidityWarningRelay,
4138 reader);
4139 }
4140 if (reader->sErrorFunc != NULL) {
4141 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4142 xmlTextReaderValidityStructuredRelay,
4143 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004144 }
4145 reader->xsdValidErrors = 0;
4146 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4147 return(0);
4148}
4149
4150/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004151 * xmlTextReaderRelaxNGValidate:
4152 * @reader: the xmlTextReaderPtr used
4153 * @rng: the path to a RelaxNG schema or NULL
4154 *
4155 * Use RelaxNG to validate the document as it is processed.
4156 * Activation is only possible before the first Read().
4157 * if @rng is NULL, then RelaxNG validation is desactivated.
4158 *
4159 * Returns 0 in case the RelaxNG validation could be (des)activated and
4160 * -1 in case of error.
4161 */
4162int
4163xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4164 xmlRelaxNGParserCtxtPtr ctxt;
4165
4166 if (reader == NULL)
4167 return(-1);
4168
4169 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004170 if (reader->rngValidCtxt != NULL) {
4171 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4172 reader->rngValidCtxt = NULL;
4173 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004174 if (reader->rngSchemas != NULL) {
4175 xmlRelaxNGFree(reader->rngSchemas);
4176 reader->rngSchemas = NULL;
4177 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004178 return(0);
4179 }
4180 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4181 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004182 if (reader->rngSchemas != NULL) {
4183 xmlRelaxNGFree(reader->rngSchemas);
4184 reader->rngSchemas = NULL;
4185 }
4186 if (reader->rngValidCtxt != NULL) {
4187 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4188 reader->rngValidCtxt = NULL;
4189 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004190 ctxt = xmlRelaxNGNewParserCtxt(rng);
4191 if (reader->errorFunc != NULL) {
4192 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004193 xmlTextReaderValidityErrorRelay,
4194 xmlTextReaderValidityWarningRelay,
4195 reader);
4196 }
4197 if (reader->sErrorFunc != NULL) {
4198 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4199 xmlTextReaderValidityStructuredRelay,
4200 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004201 }
4202 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4203 xmlRelaxNGFreeParserCtxt(ctxt);
4204 if (reader->rngSchemas == NULL)
4205 return(-1);
4206 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004207 if (reader->rngValidCtxt == NULL) {
4208 xmlRelaxNGFree(reader->rngSchemas);
4209 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004210 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004211 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004212 if (reader->errorFunc != NULL) {
4213 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004214 xmlTextReaderValidityErrorRelay,
4215 xmlTextReaderValidityWarningRelay,
4216 reader);
4217 }
4218 if (reader->sErrorFunc != NULL) {
4219 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4220 xmlTextReaderValidityStructuredRelay,
4221 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004222 }
4223 reader->rngValidErrors = 0;
4224 reader->rngFullNode = NULL;
4225 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4226 return(0);
4227}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004228
4229/**
4230 * xmlTextReaderSchemaValidate:
4231 * @reader: the xmlTextReaderPtr used
4232 * @xsd: the path to a W3C XSD schema or NULL
4233 *
4234 * Use W3C XSD schema to validate the document as it is processed.
4235 * Activation is only possible before the first Read().
4236 * if @xsd is NULL, then RelaxNG validation is desactivated.
4237 *
4238 * Returns 0 in case the schemas validation could be (des)activated and
4239 * -1 in case of error.
4240 */
4241int
4242xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4243 xmlSchemaParserCtxtPtr ctxt;
4244
4245 if (reader == NULL)
4246 return(-1);
4247
4248 if (xsd == NULL) {
4249 if (reader->xsdPlug != NULL) {
4250 xmlSchemaSAXUnplug(reader->xsdPlug);
4251 reader->xsdPlug = NULL;
4252 }
4253 if (reader->xsdSchemas != NULL) {
4254 xmlSchemaFree(reader->xsdSchemas);
4255 reader->xsdSchemas = NULL;
4256 }
4257 if (reader->xsdValidCtxt != NULL) {
4258 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4259 reader->xsdValidCtxt = NULL;
4260 }
4261 return(0);
4262 }
4263 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4264 (reader->ctxt == NULL))
4265 return(-1);
4266 if (reader->xsdPlug != NULL) {
4267 xmlSchemaSAXUnplug(reader->xsdPlug);
4268 reader->xsdPlug = NULL;
4269 }
4270 if (reader->xsdValidCtxt != NULL) {
4271 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4272 reader->xsdValidCtxt = NULL;
4273 }
4274 if (reader->xsdSchemas != NULL) {
4275 xmlSchemaFree(reader->xsdSchemas);
4276 reader->xsdSchemas = NULL;
4277 }
4278 ctxt = xmlSchemaNewParserCtxt(xsd);
4279 if (reader->errorFunc != NULL) {
4280 xmlSchemaSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004281 xmlTextReaderValidityErrorRelay,
4282 xmlTextReaderValidityWarningRelay,
4283 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004284 }
4285 reader->xsdSchemas = xmlSchemaParse(ctxt);
4286 xmlSchemaFreeParserCtxt(ctxt);
4287 if (reader->xsdSchemas == NULL)
4288 return(-1);
4289 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4290 if (reader->xsdValidCtxt == NULL) {
4291 xmlSchemaFree(reader->xsdSchemas);
4292 reader->xsdSchemas = NULL;
4293 return(-1);
4294 }
4295 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4296 &(reader->ctxt->sax),
4297 &(reader->ctxt->userData));
4298 if (reader->xsdPlug == NULL) {
4299 xmlSchemaFree(reader->xsdSchemas);
4300 reader->xsdSchemas = NULL;
4301 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4302 reader->xsdValidCtxt = NULL;
4303 return(-1);
4304 }
4305 if (reader->errorFunc != NULL) {
4306 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004307 xmlTextReaderValidityErrorRelay,
4308 xmlTextReaderValidityWarningRelay,
4309 reader);
4310 }
4311 if (reader->sErrorFunc != NULL) {
4312 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4313 xmlTextReaderValidityStructuredRelay,
4314 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004315 }
4316 reader->xsdValidErrors = 0;
4317 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4318 return(0);
4319}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004320#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004321
Daniel Veillarde2811272004-10-19 09:04:23 +00004322/**
4323 * xmlTextReaderIsNamespaceDecl:
4324 * @reader: the xmlTextReaderPtr used
4325 *
4326 * Determine whether the current node is a namespace declaration
4327 * rather than a regular attribute.
4328 *
4329 * Returns 1 if the current node is a namespace declaration, 0 if it
4330 * is a regular attribute or other type of node, or -1 in case of
4331 * error.
4332 */
4333int
4334xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4335 xmlNodePtr node;
4336 if (reader == NULL)
4337 return(-1);
4338 if (reader->node == NULL)
4339 return(-1);
4340 if (reader->curnode != NULL)
4341 node = reader->curnode;
4342 else
4343 node = reader->node;
4344
4345 if (XML_NAMESPACE_DECL == node->type)
4346 return(1);
4347 else
4348 return(0);
4349}
4350
4351/**
4352 * xmlTextReaderConstXmlVersion:
4353 * @reader: the xmlTextReaderPtr used
4354 *
4355 * Determine the XML version of the document being read.
4356 *
4357 * Returns a string containing the XML version of the document or NULL
4358 * in case of error. The string is deallocated with the reader.
4359 */
4360const xmlChar *
4361xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4362 xmlDocPtr doc = NULL;
4363 if (reader == NULL)
4364 return(NULL);
4365 if (reader->doc != NULL)
4366 doc = reader->doc;
4367 else if (reader->ctxt != NULL)
4368 doc = reader->ctxt->myDoc;
4369 if (doc == NULL)
4370 return(NULL);
4371
4372 if (doc->version == NULL)
4373 return(NULL);
4374 else
4375 return(CONSTSTR(doc->version));
4376}
4377
4378/**
4379 * xmlTextReaderStandalone:
4380 * @reader: the xmlTextReaderPtr used
4381 *
4382 * Determine the standalone status of the document being read.
4383 *
4384 * Returns 1 if the document was declared to be standalone, 0 if it
4385 * was declared to be not standalone, or -1 if the document did not
4386 * specify its standalone status or in case of error.
4387 */
4388int
4389xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4390 xmlDocPtr doc = NULL;
4391 if (reader == NULL)
4392 return(-1);
4393 if (reader->doc != NULL)
4394 doc = reader->doc;
4395 else if (reader->ctxt != NULL)
4396 doc = reader->ctxt->myDoc;
4397 if (doc == NULL)
4398 return(-1);
4399
4400 return(doc->standalone);
4401}
4402
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004403/************************************************************************
4404 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004405 * Error Handling Extensions *
4406 * *
4407 ************************************************************************/
4408
4409/* helper to build a xmlMalloc'ed string from a format and va_list */
4410static char *
4411xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4412 int size;
4413 int chars;
4414 char *larger;
4415 char *str;
4416
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004417 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004418 if (str == NULL) {
4419 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4420 return NULL;
4421 }
4422
4423 size = 150;
4424
4425 while (1) {
4426 chars = vsnprintf(str, size, msg, ap);
4427 if ((chars > -1) && (chars < size))
4428 break;
4429 if (chars > -1)
4430 size += chars + 1;
4431 else
4432 size += 100;
4433 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4434 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4435 xmlFree(str);
4436 return NULL;
4437 }
4438 str = larger;
4439 }
4440
4441 return str;
4442}
4443
Daniel Veillard417be3a2003-01-20 21:26:34 +00004444/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004445 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004446 * @locator: the xmlTextReaderLocatorPtr used
4447 *
4448 * Obtain the line number for the given locator.
4449 *
4450 * Returns the line number or -1 in case of error.
4451 */
4452int
4453xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4454 /* we know that locator is a xmlParserCtxtPtr */
4455 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4456 int ret = -1;
4457
Daniel Veillardce682bc2004-11-05 17:22:25 +00004458 if (locator == NULL)
4459 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004460 if (ctx->node != NULL) {
4461 ret = xmlGetLineNo(ctx->node);
4462 }
4463 else {
4464 /* inspired from error.c */
4465 xmlParserInputPtr input;
4466 input = ctx->input;
4467 if ((input->filename == NULL) && (ctx->inputNr > 1))
4468 input = ctx->inputTab[ctx->inputNr - 2];
4469 if (input != NULL) {
4470 ret = input->line;
4471 }
4472 else {
4473 ret = -1;
4474 }
4475 }
4476
4477 return ret;
4478}
4479
4480/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004481 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004482 * @locator: the xmlTextReaderLocatorPtr used
4483 *
4484 * Obtain the base URI for the given locator.
4485 *
4486 * Returns the base URI or NULL in case of error.
4487 */
4488xmlChar *
4489xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4490 /* we know that locator is a xmlParserCtxtPtr */
4491 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4492 xmlChar *ret = NULL;
4493
Daniel Veillardce682bc2004-11-05 17:22:25 +00004494 if (locator == NULL)
4495 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004496 if (ctx->node != NULL) {
4497 ret = xmlNodeGetBase(NULL,ctx->node);
4498 }
4499 else {
4500 /* inspired from error.c */
4501 xmlParserInputPtr input;
4502 input = ctx->input;
4503 if ((input->filename == NULL) && (ctx->inputNr > 1))
4504 input = ctx->inputTab[ctx->inputNr - 2];
4505 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004506 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004507 }
4508 else {
4509 ret = NULL;
4510 }
4511 }
4512
4513 return ret;
4514}
4515
Daniel Veillard26f70262003-01-16 22:45:08 +00004516static void
William M. Brack899e64a2003-09-26 18:03:42 +00004517xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004518 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4519 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4520
William M. Bracka3215c72004-07-31 16:24:01 +00004521 if (str != NULL) {
4522 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004523 reader->errorFunc(reader->errorFuncArg,
4524 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004525 severity,
4526 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004527 xmlFree(str);
4528 }
4529}
4530
4531static void
William M. Brack93d004f2004-02-03 00:14:10 +00004532xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4533 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4534 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4535
4536 if (error && reader->sErrorFunc) {
4537 reader->sErrorFunc(reader->errorFuncArg,
4538 (xmlErrorPtr) error);
4539 }
4540}
4541
Daniel Veillardffa3c742005-07-21 13:24:09 +00004542static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004543xmlTextReaderError(void *ctxt, const char *msg, ...) {
4544 va_list ap;
4545
4546 va_start(ap,msg);
4547 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004548 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004549 xmlTextReaderBuildMessage(msg,ap));
4550 va_end(ap);
4551
4552}
4553
Daniel Veillardffa3c742005-07-21 13:24:09 +00004554static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004555xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4556 va_list ap;
4557
4558 va_start(ap,msg);
4559 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004560 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004561 xmlTextReaderBuildMessage(msg,ap));
4562 va_end(ap);
4563}
4564
Daniel Veillardffa3c742005-07-21 13:24:09 +00004565static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004566xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4567 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004568 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004569
Daniel Veillard417be3a2003-01-20 21:26:34 +00004570 if ((len > 1) && (msg[len - 2] != ':')) {
4571 /*
4572 * some callbacks only report locator information:
4573 * skip them (mimicking behaviour in error.c)
4574 */
4575 va_start(ap,msg);
4576 xmlTextReaderGenericError(ctxt,
4577 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4578 xmlTextReaderBuildMessage(msg,ap));
4579 va_end(ap);
4580 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004581}
4582
Daniel Veillardffa3c742005-07-21 13:24:09 +00004583static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004584xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4585 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004586 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004587
Daniel Veillard417be3a2003-01-20 21:26:34 +00004588 if ((len != 0) && (msg[len - 1] != ':')) {
4589 /*
4590 * some callbacks only report locator information:
4591 * skip them (mimicking behaviour in error.c)
4592 */
4593 va_start(ap,msg);
4594 xmlTextReaderGenericError(ctxt,
4595 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4596 xmlTextReaderBuildMessage(msg,ap));
4597 va_end(ap);
4598 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004599}
4600
4601/**
4602 * xmlTextReaderSetErrorHandler:
4603 * @reader: the xmlTextReaderPtr used
4604 * @f: the callback function to call on error and warnings
4605 * @arg: a user argument to pass to the callback function
4606 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004607 * Register a callback function that will be called on error and warnings.
4608 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004609 * If @f is NULL, the default error and warning handlers are restored.
4610 */
4611void
4612xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4613 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004614 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004615 if (f != NULL) {
4616 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004617 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004618 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4619 reader->ctxt->sax->warning = xmlTextReaderWarning;
4620 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4621 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004622 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004623 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004624#ifdef LIBXML_SCHEMAS_ENABLED
4625 if (reader->rngValidCtxt) {
4626 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4627 xmlTextReaderValidityErrorRelay,
4628 xmlTextReaderValidityWarningRelay,
4629 reader);
4630 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4631 }
4632 if (reader->xsdValidCtxt) {
4633 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4634 xmlTextReaderValidityErrorRelay,
4635 xmlTextReaderValidityWarningRelay,
4636 reader);
4637 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4638 }
4639#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004640 }
4641 else {
4642 /* restore defaults */
4643 reader->ctxt->sax->error = xmlParserError;
4644 reader->ctxt->vctxt.error = xmlParserValidityError;
4645 reader->ctxt->sax->warning = xmlParserWarning;
4646 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4647 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004648 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004649 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004650#ifdef LIBXML_SCHEMAS_ENABLED
4651 if (reader->rngValidCtxt) {
4652 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4653 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4654 }
4655 if (reader->xsdValidCtxt) {
4656 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4657 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4658 }
4659#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004660 }
4661}
4662
Daniel Veillard417be3a2003-01-20 21:26:34 +00004663/**
William M. Brack93d004f2004-02-03 00:14:10 +00004664* xmlTextReaderSetStructuredErrorHandler:
4665 * @reader: the xmlTextReaderPtr used
4666 * @f: the callback function to call on error and warnings
4667 * @arg: a user argument to pass to the callback function
4668 *
4669 * Register a callback function that will be called on error and warnings.
4670 *
4671 * If @f is NULL, the default error and warning handlers are restored.
4672 */
4673void
4674xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4675 xmlStructuredErrorFunc f,
4676 void *arg) {
4677 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004678 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004679 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4680 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4681 reader->ctxt->sax->warning = xmlTextReaderWarning;
4682 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4683 reader->sErrorFunc = f;
4684 reader->errorFunc = NULL;
4685 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004686#ifdef LIBXML_SCHEMAS_ENABLED
4687 if (reader->rngValidCtxt) {
4688 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4689 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4690 xmlTextReaderValidityStructuredRelay,
4691 reader);
4692 }
4693 if (reader->xsdValidCtxt) {
4694 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4695 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4696 xmlTextReaderValidityStructuredRelay,
4697 reader);
4698 }
4699#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004700 }
4701 else {
4702 /* restore defaults */
4703 reader->ctxt->sax->error = xmlParserError;
4704 reader->ctxt->sax->serror = NULL;
4705 reader->ctxt->vctxt.error = xmlParserValidityError;
4706 reader->ctxt->sax->warning = xmlParserWarning;
4707 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4708 reader->errorFunc = NULL;
4709 reader->sErrorFunc = NULL;
4710 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004711#ifdef LIBXML_SCHEMAS_ENABLED
4712 if (reader->rngValidCtxt) {
4713 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4714 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4715 }
4716 if (reader->xsdValidCtxt) {
4717 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4718 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4719 }
4720#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004721 }
4722}
4723
4724/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004725 * xmlTextReaderIsValid:
4726 * @reader: the xmlTextReaderPtr used
4727 *
4728 * Retrieve the validity status from the parser context
4729 *
4730 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4731 */
4732int
4733xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004734 if (reader == NULL) return(-1);
4735#ifdef LIBXML_SCHEMAS_ENABLED
4736 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4737 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004738 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4739 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004740#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004741 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004742 return(reader->ctxt->valid);
4743 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004744}
4745
4746/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004747 * xmlTextReaderGetErrorHandler:
4748 * @reader: the xmlTextReaderPtr used
4749 * @f: the callback function or NULL is no callback has been registered
4750 * @arg: a user argument
4751 *
4752 * Retrieve the error callback function and user argument.
4753 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004754void
4755xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4756 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004757 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004758 if (f != NULL) *f = reader->errorFunc;
4759 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004760}
4761
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004762
4763/************************************************************************
4764 * *
4765 * New set (2.6.0) of simpler and more flexible APIs *
4766 * *
4767 ************************************************************************/
4768
4769/**
4770 * xmlTextReaderSetup:
4771 * @reader: an XML reader
4772 * @URL: the base URL to use for the document
4773 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004774 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004775 * @reuse: keep the context for reuse
4776 *
4777 * Setup an XML reader with new options
4778 *
4779 * Returns 0 in case of success and -1 in case of error.
4780 */
4781static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004782xmlTextReaderSetup(xmlTextReaderPtr reader,
4783 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004784 const char *encoding, int options)
4785{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004786 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004787 return (-1);
4788
Daniel Veillard8874b942005-08-25 13:19:21 +00004789 /*
4790 * we force the generation of compact text nodes on the reader
4791 * since usr applications should never modify the tree
4792 */
4793 options |= XML_PARSE_COMPACT;
4794
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004795 reader->doc = NULL;
4796 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004797 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004798 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004799 if ((input != NULL) && (reader->input != NULL) &&
4800 (reader->allocs & XML_TEXTREADER_INPUT)) {
4801 xmlFreeParserInputBuffer(reader->input);
4802 reader->input = NULL;
4803 reader->allocs -= XML_TEXTREADER_INPUT;
4804 }
4805 if (input != NULL) {
4806 reader->input = input;
4807 reader->allocs |= XML_TEXTREADER_INPUT;
4808 }
4809 if (reader->buffer == NULL)
4810 reader->buffer = xmlBufferCreateSize(100);
4811 if (reader->buffer == NULL) {
4812 xmlGenericError(xmlGenericErrorContext,
4813 "xmlTextReaderSetup : malloc failed\n");
4814 return (-1);
4815 }
4816 if (reader->sax == NULL)
4817 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4818 if (reader->sax == NULL) {
4819 xmlGenericError(xmlGenericErrorContext,
4820 "xmlTextReaderSetup : malloc failed\n");
4821 return (-1);
4822 }
4823 xmlSAXVersion(reader->sax, 2);
4824 reader->startElement = reader->sax->startElement;
4825 reader->sax->startElement = xmlTextReaderStartElement;
4826 reader->endElement = reader->sax->endElement;
4827 reader->sax->endElement = xmlTextReaderEndElement;
4828#ifdef LIBXML_SAX1_ENABLED
4829 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4830#endif /* LIBXML_SAX1_ENABLED */
4831 reader->startElementNs = reader->sax->startElementNs;
4832 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4833 reader->endElementNs = reader->sax->endElementNs;
4834 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4835#ifdef LIBXML_SAX1_ENABLED
4836 } else {
4837 reader->startElementNs = NULL;
4838 reader->endElementNs = NULL;
4839 }
4840#endif /* LIBXML_SAX1_ENABLED */
4841 reader->characters = reader->sax->characters;
4842 reader->sax->characters = xmlTextReaderCharacters;
4843 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4844 reader->cdataBlock = reader->sax->cdataBlock;
4845 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4846
4847 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4848 reader->node = NULL;
4849 reader->curnode = NULL;
4850 if (input != NULL) {
4851 if (reader->input->buffer->use < 4) {
4852 xmlParserInputBufferRead(input, 4);
4853 }
4854 if (reader->ctxt == NULL) {
4855 if (reader->input->buffer->use >= 4) {
4856 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4857 (const char *) reader->input->buffer->content, 4, URL);
4858 reader->base = 0;
4859 reader->cur = 4;
4860 } else {
4861 reader->ctxt =
4862 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4863 reader->base = 0;
4864 reader->cur = 0;
4865 }
4866 } else {
4867 xmlParserInputPtr inputStream;
4868 xmlParserInputBufferPtr buf;
4869 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4870
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004871 xmlCtxtReset(reader->ctxt);
4872 buf = xmlAllocParserInputBuffer(enc);
4873 if (buf == NULL) return(-1);
4874 inputStream = xmlNewInputStream(reader->ctxt);
4875 if (inputStream == NULL) {
4876 xmlFreeParserInputBuffer(buf);
4877 return(-1);
4878 }
4879
4880 if (URL == NULL)
4881 inputStream->filename = NULL;
4882 else
4883 inputStream->filename = (char *)
4884 xmlCanonicPath((const xmlChar *) URL);
4885 inputStream->buf = buf;
4886 inputStream->base = inputStream->buf->buffer->content;
4887 inputStream->cur = inputStream->buf->buffer->content;
4888 inputStream->end =
4889 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4890
4891 inputPush(reader->ctxt, inputStream);
4892 reader->cur = 0;
4893 }
4894 if (reader->ctxt == NULL) {
4895 xmlGenericError(xmlGenericErrorContext,
4896 "xmlTextReaderSetup : malloc failed\n");
4897 return (-1);
4898 }
4899 }
4900 if (reader->dict != NULL) {
4901 if (reader->ctxt->dict != NULL) {
4902 if (reader->dict != reader->ctxt->dict) {
4903 xmlDictFree(reader->dict);
4904 reader->dict = reader->ctxt->dict;
4905 }
4906 } else {
4907 reader->ctxt->dict = reader->dict;
4908 }
4909 } else {
4910 if (reader->ctxt->dict == NULL)
4911 reader->ctxt->dict = xmlDictCreate();
4912 reader->dict = reader->ctxt->dict;
4913 }
4914 reader->ctxt->_private = reader;
4915 reader->ctxt->linenumbers = 1;
4916 reader->ctxt->dictNames = 1;
4917 /*
4918 * use the parser dictionnary to allocate all elements and attributes names
4919 */
4920 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004921 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004922
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004923#ifdef LIBXML_XINCLUDE_ENABLED
4924 if (reader->xincctxt != NULL) {
4925 xmlXIncludeFreeContext(reader->xincctxt);
4926 reader->xincctxt = NULL;
4927 }
4928 if (options & XML_PARSE_XINCLUDE) {
4929 reader->xinclude = 1;
4930 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4931 options -= XML_PARSE_XINCLUDE;
4932 } else
4933 reader->xinclude = 0;
4934 reader->in_xinclude = 0;
4935#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004936#ifdef LIBXML_PATTERN_ENABLED
4937 if (reader->patternTab == NULL) {
4938 reader->patternNr = 0;
4939 reader->patternMax = 0;
4940 }
4941 while (reader->patternNr > 0) {
4942 reader->patternNr--;
4943 if (reader->patternTab[reader->patternNr] != NULL) {
4944 xmlFreePattern(reader->patternTab[reader->patternNr]);
4945 reader->patternTab[reader->patternNr] = NULL;
4946 }
4947 }
4948#endif
4949
Daniel Veillardc36965d2003-12-02 10:28:48 +00004950 if (options & XML_PARSE_DTDVALID)
4951 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4952
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004953 xmlCtxtUseOptions(reader->ctxt, options);
4954 if (encoding != NULL) {
4955 xmlCharEncodingHandlerPtr hdlr;
4956
4957 hdlr = xmlFindCharEncodingHandler(encoding);
4958 if (hdlr != NULL)
4959 xmlSwitchToEncoding(reader->ctxt, hdlr);
4960 }
4961 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4962 (reader->ctxt->input->filename == NULL))
4963 reader->ctxt->input->filename = (char *)
4964 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004965
4966 reader->doc = NULL;
4967
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004968 return (0);
4969}
4970
4971/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004972 * xmlTextReaderByteConsumed:
4973 * @reader: an XML reader
4974 *
4975 * This function provides the current index of the parser used
4976 * by the reader, relative to the start of the current entity.
4977 * This function actually just wraps a call to xmlBytesConsumed()
4978 * for the parser context associated with the reader.
4979 * See xmlBytesConsumed() for more information.
4980 *
4981 * Returns the index in bytes from the beginning of the entity or -1
4982 * in case the index could not be computed.
4983 */
4984long
4985xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4986 if ((reader == NULL) || (reader->ctxt == NULL))
4987 return(-1);
4988 return(xmlByteConsumed(reader->ctxt));
4989}
4990
4991
4992/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004993 * xmlReaderWalker:
4994 * @doc: a preparsed document
4995 *
4996 * Create an xmltextReader for a preparsed document.
4997 *
4998 * Returns the new reader or NULL in case of error.
4999 */
5000xmlTextReaderPtr
5001xmlReaderWalker(xmlDocPtr doc)
5002{
5003 xmlTextReaderPtr ret;
5004
5005 if (doc == NULL)
5006 return(NULL);
5007
5008 ret = xmlMalloc(sizeof(xmlTextReader));
5009 if (ret == NULL) {
5010 xmlGenericError(xmlGenericErrorContext,
5011 "xmlNewTextReader : malloc failed\n");
5012 return(NULL);
5013 }
5014 memset(ret, 0, sizeof(xmlTextReader));
5015 ret->entNr = 0;
5016 ret->input = NULL;
5017 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5018 ret->node = NULL;
5019 ret->curnode = NULL;
5020 ret->base = 0;
5021 ret->cur = 0;
5022 ret->allocs = XML_TEXTREADER_CTXT;
5023 ret->doc = doc;
5024 ret->state = XML_TEXTREADER_START;
5025 ret->dict = xmlDictCreate();
5026 return(ret);
5027}
5028
5029/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005030 * xmlReaderForDoc:
5031 * @cur: a pointer to a zero terminated string
5032 * @URL: the base URL to use for the document
5033 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005034 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005035 *
5036 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005037 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005038 *
5039 * Returns the new reader or NULL in case of error.
5040 */
5041xmlTextReaderPtr
5042xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5043 int options)
5044{
5045 int len;
5046
5047 if (cur == NULL)
5048 return (NULL);
5049 len = xmlStrlen(cur);
5050
5051 return (xmlReaderForMemory
5052 ((const char *) cur, len, URL, encoding, options));
5053}
5054
5055/**
5056 * xmlReaderForFile:
5057 * @filename: a file or URL
5058 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005059 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005060 *
5061 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005062 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005063 *
5064 * Returns the new reader or NULL in case of error.
5065 */
5066xmlTextReaderPtr
5067xmlReaderForFile(const char *filename, const char *encoding, int options)
5068{
5069 xmlTextReaderPtr reader;
5070
5071 reader = xmlNewTextReaderFilename(filename);
5072 if (reader == NULL)
5073 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005074 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005075 return (reader);
5076}
5077
5078/**
5079 * xmlReaderForMemory:
5080 * @buffer: a pointer to a char array
5081 * @size: the size of the array
5082 * @URL: the base URL to use for the document
5083 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005084 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005085 *
5086 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005087 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005088 *
5089 * Returns the new reader or NULL in case of error.
5090 */
5091xmlTextReaderPtr
5092xmlReaderForMemory(const char *buffer, int size, const char *URL,
5093 const char *encoding, int options)
5094{
5095 xmlTextReaderPtr reader;
5096 xmlParserInputBufferPtr buf;
5097
Daniel Veillard21924522004-02-19 16:37:07 +00005098 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005099 XML_CHAR_ENCODING_NONE);
5100 if (buf == NULL) {
5101 return (NULL);
5102 }
5103 reader = xmlNewTextReader(buf, URL);
5104 if (reader == NULL) {
5105 xmlFreeParserInputBuffer(buf);
5106 return (NULL);
5107 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005108 reader->allocs |= XML_TEXTREADER_INPUT;
5109 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005110 return (reader);
5111}
5112
5113/**
5114 * xmlReaderForFd:
5115 * @fd: an open file descriptor
5116 * @URL: the base URL to use for the document
5117 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005118 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005119 *
5120 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005121 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005122 * NOTE that the file descriptor will not be closed when the
5123 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005124 *
5125 * Returns the new reader or NULL in case of error.
5126 */
5127xmlTextReaderPtr
5128xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5129{
5130 xmlTextReaderPtr reader;
5131 xmlParserInputBufferPtr input;
5132
5133 if (fd < 0)
5134 return (NULL);
5135
5136 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5137 if (input == NULL)
5138 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005139 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005140 reader = xmlNewTextReader(input, URL);
5141 if (reader == NULL) {
5142 xmlFreeParserInputBuffer(input);
5143 return (NULL);
5144 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005145 reader->allocs |= XML_TEXTREADER_INPUT;
5146 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005147 return (reader);
5148}
5149
5150/**
5151 * xmlReaderForIO:
5152 * @ioread: an I/O read function
5153 * @ioclose: an I/O close function
5154 * @ioctx: an I/O handler
5155 * @URL: the base URL to use for the document
5156 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005157 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005158 *
5159 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005160 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005161 *
5162 * Returns the new reader or NULL in case of error.
5163 */
5164xmlTextReaderPtr
5165xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5166 void *ioctx, const char *URL, const char *encoding,
5167 int options)
5168{
5169 xmlTextReaderPtr reader;
5170 xmlParserInputBufferPtr input;
5171
5172 if (ioread == NULL)
5173 return (NULL);
5174
5175 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5176 XML_CHAR_ENCODING_NONE);
5177 if (input == NULL)
5178 return (NULL);
5179 reader = xmlNewTextReader(input, URL);
5180 if (reader == NULL) {
5181 xmlFreeParserInputBuffer(input);
5182 return (NULL);
5183 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005184 reader->allocs |= XML_TEXTREADER_INPUT;
5185 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005186 return (reader);
5187}
5188
5189/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005190 * xmlReaderNewWalker:
5191 * @reader: an XML reader
5192 * @doc: a preparsed document
5193 *
5194 * Setup an xmltextReader to parse a preparsed XML document.
5195 * This reuses the existing @reader xmlTextReader.
5196 *
5197 * Returns 0 in case of success and -1 in case of error
5198 */
5199int
5200xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5201{
5202 if (doc == NULL)
5203 return (-1);
5204 if (reader == NULL)
5205 return (-1);
5206
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005207 if (reader->input != NULL) {
5208 xmlFreeParserInputBuffer(reader->input);
5209 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005210 if (reader->ctxt != NULL) {
5211 xmlCtxtReset(reader->ctxt);
5212 }
5213
5214 reader->entNr = 0;
5215 reader->input = NULL;
5216 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5217 reader->node = NULL;
5218 reader->curnode = NULL;
5219 reader->base = 0;
5220 reader->cur = 0;
5221 reader->allocs = XML_TEXTREADER_CTXT;
5222 reader->doc = doc;
5223 reader->state = XML_TEXTREADER_START;
5224 if (reader->dict == NULL) {
5225 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5226 reader->dict = reader->ctxt->dict;
5227 else
5228 reader->dict = xmlDictCreate();
5229 }
5230 return(0);
5231}
5232
5233/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005234 * xmlReaderNewDoc:
5235 * @reader: an XML reader
5236 * @cur: a pointer to a zero terminated string
5237 * @URL: the base URL to use for the document
5238 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005239 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005240 *
5241 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005242 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005243 * This reuses the existing @reader xmlTextReader.
5244 *
5245 * Returns 0 in case of success and -1 in case of error
5246 */
5247int
5248xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5249 const char *URL, const char *encoding, int options)
5250{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005251
5252 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005253
5254 if (cur == NULL)
5255 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005256 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005257 return (-1);
5258
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005259 len = xmlStrlen(cur);
5260 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5261 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005262}
5263
5264/**
5265 * xmlReaderNewFile:
5266 * @reader: an XML reader
5267 * @filename: a file or URL
5268 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005269 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005270 *
5271 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005272 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005273 * This reuses the existing @reader xmlTextReader.
5274 *
5275 * Returns 0 in case of success and -1 in case of error
5276 */
5277int
5278xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5279 const char *encoding, int options)
5280{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005281 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005282
5283 if (filename == NULL)
5284 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005285 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005286 return (-1);
5287
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005288 input =
5289 xmlParserInputBufferCreateFilename(filename,
5290 XML_CHAR_ENCODING_NONE);
5291 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005292 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005293 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005294}
5295
5296/**
5297 * xmlReaderNewMemory:
5298 * @reader: an XML reader
5299 * @buffer: a pointer to a char array
5300 * @size: the size of the array
5301 * @URL: the base URL to use for the document
5302 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005303 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005304 *
5305 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005306 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005307 * This reuses the existing @reader xmlTextReader.
5308 *
5309 * Returns 0 in case of success and -1 in case of error
5310 */
5311int
5312xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5313 const char *URL, const char *encoding, int options)
5314{
5315 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005316
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005317 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005318 return (-1);
5319 if (buffer == NULL)
5320 return (-1);
5321
Daniel Veillard21924522004-02-19 16:37:07 +00005322 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005323 XML_CHAR_ENCODING_NONE);
5324 if (input == NULL) {
5325 return (-1);
5326 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005327 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005328}
5329
5330/**
5331 * xmlReaderNewFd:
5332 * @reader: an XML reader
5333 * @fd: an open file descriptor
5334 * @URL: the base URL to use for the document
5335 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005336 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005337 *
5338 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005339 * NOTE that the file descriptor will not be closed when the
5340 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005341 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005342 * This reuses the existing @reader xmlTextReader.
5343 *
5344 * Returns 0 in case of success and -1 in case of error
5345 */
5346int
5347xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5348 const char *URL, const char *encoding, int options)
5349{
5350 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005351
5352 if (fd < 0)
5353 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005354 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005355 return (-1);
5356
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005357 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5358 if (input == NULL)
5359 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005360 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005361 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005362}
5363
5364/**
5365 * xmlReaderNewIO:
5366 * @reader: an XML reader
5367 * @ioread: an I/O read function
5368 * @ioclose: an I/O close function
5369 * @ioctx: an I/O handler
5370 * @URL: the base URL to use for the document
5371 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005372 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005373 *
5374 * Setup an xmltextReader to parse an XML document from I/O functions
5375 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005376 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377 * This reuses the existing @reader xmlTextReader.
5378 *
5379 * Returns 0 in case of success and -1 in case of error
5380 */
5381int
5382xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5383 xmlInputCloseCallback ioclose, void *ioctx,
5384 const char *URL, const char *encoding, int options)
5385{
5386 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005387
5388 if (ioread == NULL)
5389 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005390 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005391 return (-1);
5392
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005393 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5394 XML_CHAR_ENCODING_NONE);
5395 if (input == NULL)
5396 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005397 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005398}
Daniel Veillard26f70262003-01-16 22:45:08 +00005399/************************************************************************
5400 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005401 * Utilities *
5402 * *
5403 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005404#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005405/**
5406 * xmlBase64Decode:
5407 * @in: the input buffer
5408 * @inlen: the size of the input (in), the size read from it (out)
5409 * @to: the output buffer
5410 * @tolen: the size of the output (in), the size written to (out)
5411 *
5412 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005413 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005414 *
5415 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5416 * 2 if there wasn't enough space on the output or -1 in case of error.
5417 */
5418static int
5419xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5420 unsigned char *to, unsigned long *tolen) {
5421 unsigned long incur; /* current index in in[] */
5422 unsigned long inblk; /* last block index in in[] */
5423 unsigned long outcur; /* current index in out[] */
5424 unsigned long inmax; /* size of in[] */
5425 unsigned long outmax; /* size of out[] */
5426 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005427 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005428 int nbintmp; /* number of byte in intmp[] */
5429 int is_ignore; /* cur should be ignored */
5430 int is_end = 0; /* the end of the base64 was found */
5431 int retval = 1;
5432 int i;
5433
5434 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5435 return(-1);
5436
5437 incur = 0;
5438 inblk = 0;
5439 outcur = 0;
5440 inmax = *inlen;
5441 outmax = *tolen;
5442 nbintmp = 0;
5443
5444 while (1) {
5445 if (incur >= inmax)
5446 break;
5447 cur = in[incur++];
5448 is_ignore = 0;
5449 if ((cur >= 'A') && (cur <= 'Z'))
5450 cur = cur - 'A';
5451 else if ((cur >= 'a') && (cur <= 'z'))
5452 cur = cur - 'a' + 26;
5453 else if ((cur >= '0') && (cur <= '9'))
5454 cur = cur - '0' + 52;
5455 else if (cur == '+')
5456 cur = 62;
5457 else if (cur == '/')
5458 cur = 63;
5459 else if (cur == '.')
5460 cur = 0;
5461 else if (cur == '=') /*no op , end of the base64 stream */
5462 is_end = 1;
5463 else {
5464 is_ignore = 1;
5465 if (nbintmp == 0)
5466 inblk = incur;
5467 }
5468
5469 if (!is_ignore) {
5470 int nbouttmp = 3;
5471 int is_break = 0;
5472
5473 if (is_end) {
5474 if (nbintmp == 0)
5475 break;
5476 if ((nbintmp == 1) || (nbintmp == 2))
5477 nbouttmp = 1;
5478 else
5479 nbouttmp = 2;
5480 nbintmp = 3;
5481 is_break = 1;
5482 }
5483 intmp[nbintmp++] = cur;
5484 /*
5485 * if intmp is full, push the 4byte sequence as a 3 byte
5486 * sequence out
5487 */
5488 if (nbintmp == 4) {
5489 nbintmp = 0;
5490 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5491 outtmp[1] =
5492 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5493 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5494 if (outcur + 3 >= outmax) {
5495 retval = 2;
5496 break;
5497 }
5498
5499 for (i = 0; i < nbouttmp; i++)
5500 to[outcur++] = outtmp[i];
5501 inblk = incur;
5502 }
5503
5504 if (is_break) {
5505 retval = 0;
5506 break;
5507 }
5508 }
5509 }
5510
5511 *tolen = outcur;
5512 *inlen = inblk;
5513 return (retval);
5514}
5515
5516/*
5517 * Test routine for the xmlBase64Decode function
5518 */
5519#if 0
5520int main(int argc, char **argv) {
5521 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5522 char output[100];
5523 char output2[100];
5524 char output3[100];
5525 unsigned long inlen = strlen(input);
5526 unsigned long outlen = 100;
5527 int ret;
5528 unsigned long cons, tmp, tmp2, prod;
5529
5530 /*
5531 * Direct
5532 */
5533 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5534
5535 output[outlen] = 0;
5536 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5537
5538 /*
5539 * output chunking
5540 */
5541 cons = 0;
5542 prod = 0;
5543 while (cons < inlen) {
5544 tmp = 5;
5545 tmp2 = inlen - cons;
5546
5547 printf("%ld %ld\n", cons, prod);
5548 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5549 cons += tmp2;
5550 prod += tmp;
5551 printf("%ld %ld\n", cons, prod);
5552 }
5553 output2[outlen] = 0;
5554 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5555
5556 /*
5557 * input chunking
5558 */
5559 cons = 0;
5560 prod = 0;
5561 while (cons < inlen) {
5562 tmp = 100 - prod;
5563 tmp2 = inlen - cons;
5564 if (tmp2 > 5)
5565 tmp2 = 5;
5566
5567 printf("%ld %ld\n", cons, prod);
5568 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5569 cons += tmp2;
5570 prod += tmp;
5571 printf("%ld %ld\n", cons, prod);
5572 }
5573 output3[outlen] = 0;
5574 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5575 return(0);
5576
5577}
5578#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005579#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005580#define bottom_xmlreader
5581#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005582#endif /* LIBXML_READER_ENABLED */