blob: d3e35d4532ac463fcfc4a1f8d552778aa099540f [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 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000134 int rngValidErrors;/* The number of errors detected */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000135 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 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000139 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
140 int xsdValidErrors;/* The number of errors detected */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000141 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000142#endif
143#ifdef LIBXML_XINCLUDE_ENABLED
144 /* Handling of XInclude processing */
145 int xinclude; /* is xinclude asked for */
146 const xmlChar * xinclude_name; /* the xinclude name from dict */
147 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
148 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000149#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000150#ifdef LIBXML_PATTERN_ENABLED
151 int patternNr; /* number of preserve patterns */
152 int patternMax; /* max preserve patterns */
153 xmlPatternPtr *patternTab; /* array of preserve patterns */
154#endif
155 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000156 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000157 /* Structured error handling */
158 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000159};
160
Daniel Veillarde8039df2003-10-27 11:25:13 +0000161#define NODE_IS_EMPTY 0x1
162#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000163#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000164
Daniel Veillarde72c5082003-09-19 12:44:05 +0000165/**
166 * CONSTSTR:
167 *
168 * Macro used to return an interned string
169 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000170#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
171#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
172
173static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
174static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000175
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000176/************************************************************************
177 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000178 * Our own version of the freeing routines as we recycle nodes *
179 * *
180 ************************************************************************/
181/**
182 * DICT_FREE:
183 * @str: a string
184 *
185 * Free a string if it is not owned by the "dict" dictionnary in the
186 * current scope
187 */
188#define DICT_FREE(str) \
189 if ((str) && ((!dict) || \
190 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
191 xmlFree((char *)(str));
192
193static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
194static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
195
196/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000197 * xmlFreeID:
198 * @not: A id
199 *
200 * Deallocate the memory used by an id definition
201 */
202static void
203xmlFreeID(xmlIDPtr id) {
204 xmlDictPtr dict = NULL;
205
206 if (id == NULL) return;
207
208 if (id->doc != NULL)
209 dict = id->doc->dict;
210
211 if (id->value != NULL)
212 DICT_FREE(id->value)
213 xmlFree(id);
214}
215
216/**
217 * xmlTextReaderRemoveID:
218 * @doc: the document
219 * @attr: the attribute
220 *
221 * Remove the given attribute from the ID table maintained internally.
222 *
223 * Returns -1 if the lookup failed and 0 otherwise
224 */
225static int
226xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
227 xmlIDTablePtr table;
228 xmlIDPtr id;
229 xmlChar *ID;
230
231 if (doc == NULL) return(-1);
232 if (attr == NULL) return(-1);
233 table = (xmlIDTablePtr) doc->ids;
234 if (table == NULL)
235 return(-1);
236
237 if (attr == NULL)
238 return(-1);
239 ID = xmlNodeListGetString(doc, attr->children, 1);
240 if (ID == NULL)
241 return(-1);
242 id = xmlHashLookup(table, ID);
243 xmlFree(ID);
244 if (id == NULL || id->attr != attr) {
245 return(-1);
246 }
247 id->name = attr->name;
248 id->attr = NULL;
249 return(0);
250}
251
252/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000253 * xmlTextReaderFreeProp:
254 * @reader: the xmlTextReaderPtr used
255 * @cur: the node
256 *
257 * Free a node.
258 */
259static void
260xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
261 xmlDictPtr dict;
262
263 dict = reader->ctxt->dict;
264 if (cur == NULL) return;
265
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000266 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
267 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
268
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000269 /* Check for ID removal -> leading to invalid references ! */
270 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
271 ((cur->parent->doc->intSubset != NULL) ||
272 (cur->parent->doc->extSubset != NULL))) {
273 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000274 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000275 }
276 if (cur->children != NULL)
277 xmlTextReaderFreeNodeList(reader, cur->children);
278
279 DICT_FREE(cur->name);
280 if ((reader != NULL) && (reader->ctxt != NULL) &&
281 (reader->ctxt->freeAttrsNr < 100)) {
282 cur->next = reader->ctxt->freeAttrs;
283 reader->ctxt->freeAttrs = cur;
284 reader->ctxt->freeAttrsNr++;
285 } else {
286 xmlFree(cur);
287 }
288}
289
290/**
291 * xmlTextReaderFreePropList:
292 * @reader: the xmlTextReaderPtr used
293 * @cur: the first property in the list
294 *
295 * Free a property and all its siblings, all the children are freed too.
296 */
297static void
298xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
299 xmlAttrPtr next;
300 if (cur == NULL) return;
301 while (cur != NULL) {
302 next = cur->next;
303 xmlTextReaderFreeProp(reader, cur);
304 cur = next;
305 }
306}
307
308/**
309 * xmlTextReaderFreeNodeList:
310 * @reader: the xmlTextReaderPtr used
311 * @cur: the first node in the list
312 *
313 * Free a node and all its siblings, this is a recursive behaviour, all
314 * the children are freed too.
315 */
316static void
317xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
318 xmlNodePtr next;
319 xmlDictPtr dict;
320
321 dict = reader->ctxt->dict;
322 if (cur == NULL) return;
323 if (cur->type == XML_NAMESPACE_DECL) {
324 xmlFreeNsList((xmlNsPtr) cur);
325 return;
326 }
327 if ((cur->type == XML_DOCUMENT_NODE) ||
328 (cur->type == XML_HTML_DOCUMENT_NODE)) {
329 xmlFreeDoc((xmlDocPtr) cur);
330 return;
331 }
332 while (cur != NULL) {
333 next = cur->next;
334 /* unroll to speed up freeing the document */
335 if (cur->type != XML_DTD_NODE) {
336
337 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000338 (cur->type != XML_ENTITY_REF_NODE)) {
339 if (cur->children->parent == cur)
340 xmlTextReaderFreeNodeList(reader, cur->children);
341 cur->children = NULL;
342 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000343
344 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
345 xmlDeregisterNodeDefaultValue(cur);
346
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000347 if (((cur->type == XML_ELEMENT_NODE) ||
348 (cur->type == XML_XINCLUDE_START) ||
349 (cur->type == XML_XINCLUDE_END)) &&
350 (cur->properties != NULL))
351 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000352 if ((cur->content != (xmlChar *) &(cur->properties)) &&
353 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000354 (cur->type != XML_XINCLUDE_START) &&
355 (cur->type != XML_XINCLUDE_END) &&
356 (cur->type != XML_ENTITY_REF_NODE)) {
357 DICT_FREE(cur->content);
358 }
359 if (((cur->type == XML_ELEMENT_NODE) ||
360 (cur->type == XML_XINCLUDE_START) ||
361 (cur->type == XML_XINCLUDE_END)) &&
362 (cur->nsDef != NULL))
363 xmlFreeNsList(cur->nsDef);
364
365 /*
366 * we don't free element names here they are interned now
367 */
368 if ((cur->type != XML_TEXT_NODE) &&
369 (cur->type != XML_COMMENT_NODE))
370 DICT_FREE(cur->name);
371 if (((cur->type == XML_ELEMENT_NODE) ||
372 (cur->type == XML_TEXT_NODE)) &&
373 (reader != NULL) && (reader->ctxt != NULL) &&
374 (reader->ctxt->freeElemsNr < 100)) {
375 cur->next = reader->ctxt->freeElems;
376 reader->ctxt->freeElems = cur;
377 reader->ctxt->freeElemsNr++;
378 } else {
379 xmlFree(cur);
380 }
381 }
382 cur = next;
383 }
384}
385
386/**
387 * xmlTextReaderFreeNode:
388 * @reader: the xmlTextReaderPtr used
389 * @cur: the node
390 *
391 * Free a node, this is a recursive behaviour, all the children are freed too.
392 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
393 */
394static void
395xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
396 xmlDictPtr dict;
397
398 dict = reader->ctxt->dict;
399 if (cur->type == XML_DTD_NODE) {
400 xmlFreeDtd((xmlDtdPtr) cur);
401 return;
402 }
403 if (cur->type == XML_NAMESPACE_DECL) {
404 xmlFreeNs((xmlNsPtr) cur);
405 return;
406 }
407 if (cur->type == XML_ATTRIBUTE_NODE) {
408 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
409 return;
410 }
411
412 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000413 (cur->type != XML_ENTITY_REF_NODE)) {
414 if (cur->children->parent == cur)
415 xmlTextReaderFreeNodeList(reader, cur->children);
416 cur->children = NULL;
417 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000418
419 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
420 xmlDeregisterNodeDefaultValue(cur);
421
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000422 if (((cur->type == XML_ELEMENT_NODE) ||
423 (cur->type == XML_XINCLUDE_START) ||
424 (cur->type == XML_XINCLUDE_END)) &&
425 (cur->properties != NULL))
426 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000427 if ((cur->content != (xmlChar *) &(cur->properties)) &&
428 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000429 (cur->type != XML_XINCLUDE_START) &&
430 (cur->type != XML_XINCLUDE_END) &&
431 (cur->type != XML_ENTITY_REF_NODE)) {
432 DICT_FREE(cur->content);
433 }
434 if (((cur->type == XML_ELEMENT_NODE) ||
435 (cur->type == XML_XINCLUDE_START) ||
436 (cur->type == XML_XINCLUDE_END)) &&
437 (cur->nsDef != NULL))
438 xmlFreeNsList(cur->nsDef);
439
440 /*
441 * we don't free names here they are interned now
442 */
443 if ((cur->type != XML_TEXT_NODE) &&
444 (cur->type != XML_COMMENT_NODE))
445 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000446
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000447 if (((cur->type == XML_ELEMENT_NODE) ||
448 (cur->type == XML_TEXT_NODE)) &&
449 (reader != NULL) && (reader->ctxt != NULL) &&
450 (reader->ctxt->freeElemsNr < 100)) {
451 cur->next = reader->ctxt->freeElems;
452 reader->ctxt->freeElems = cur;
453 reader->ctxt->freeElemsNr++;
454 } else {
455 xmlFree(cur);
456 }
457}
458
459/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000460 * xmlTextReaderFreeIDTable:
461 * @table: An id table
462 *
463 * Deallocate the memory used by an ID hash table.
464 */
William M. Brack60f394e2003-11-16 06:25:42 +0000465static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000466xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
467 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
468}
469
470/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000471 * xmlTextReaderFreeDoc:
472 * @reader: the xmlTextReaderPtr used
473 * @cur: pointer to the document
474 *
475 * Free up all the structures used by a document, tree included.
476 */
477static void
478xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
479 xmlDtdPtr extSubset, intSubset;
480
481 if (cur == NULL) return;
482
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000483 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
484 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
485
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000486 /*
487 * Do this before freeing the children list to avoid ID lookups
488 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000489 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000490 cur->ids = NULL;
491 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
492 cur->refs = NULL;
493 extSubset = cur->extSubset;
494 intSubset = cur->intSubset;
495 if (intSubset == extSubset)
496 extSubset = NULL;
497 if (extSubset != NULL) {
498 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
499 cur->extSubset = NULL;
500 xmlFreeDtd(extSubset);
501 }
502 if (intSubset != NULL) {
503 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
504 cur->intSubset = NULL;
505 xmlFreeDtd(intSubset);
506 }
507
508 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
509
510 if (cur->version != NULL) xmlFree((char *) cur->version);
511 if (cur->name != NULL) xmlFree((char *) cur->name);
512 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
513 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
514 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000515 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000516
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000517 xmlFree(cur);
518}
519
520/************************************************************************
521 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000522 * The reader core parser *
523 * *
524 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000525#ifdef DEBUG_READER
526static void
527xmlTextReaderDebug(xmlTextReaderPtr reader) {
528 if ((reader == NULL) || (reader->ctxt == NULL)) {
529 fprintf(stderr, "xmlTextReader NULL\n");
530 return;
531 }
532 fprintf(stderr, "xmlTextReader: state %d depth %d ",
533 reader->state, reader->depth);
534 if (reader->node == NULL) {
535 fprintf(stderr, "node = NULL\n");
536 } else {
537 fprintf(stderr, "node %s\n", reader->node->name);
538 }
539 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
540 reader->base, reader->cur, reader->ctxt->nodeNr);
541 if (reader->input->buffer == NULL) {
542 fprintf(stderr, "buffer is NULL\n");
543 } else {
544#ifdef LIBXML_DEBUG_ENABLED
545 xmlDebugDumpString(stderr,
546 &reader->input->buffer->content[reader->cur]);
547#endif
548 fprintf(stderr, "\n");
549 }
550}
551#endif
552
553/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000554 * xmlTextReaderEntPush:
555 * @reader: the xmlTextReaderPtr used
556 * @value: the entity reference node
557 *
558 * Pushes a new entity reference node on top of the entities stack
559 *
560 * Returns 0 in case of error, the index in the stack otherwise
561 */
562static int
563xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
564{
565 if (reader->entMax <= 0) {
566 reader->entMax = 10;
567 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
568 sizeof(reader->entTab[0]));
569 if (reader->entTab == NULL) {
570 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
571 return (0);
572 }
573 }
574 if (reader->entNr >= reader->entMax) {
575 reader->entMax *= 2;
576 reader->entTab =
577 (xmlNodePtr *) xmlRealloc(reader->entTab,
578 reader->entMax *
579 sizeof(reader->entTab[0]));
580 if (reader->entTab == NULL) {
581 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
582 return (0);
583 }
584 }
585 reader->entTab[reader->entNr] = value;
586 reader->ent = value;
587 return (reader->entNr++);
588}
589
590/**
591 * xmlTextReaderEntPop:
592 * @reader: the xmlTextReaderPtr used
593 *
594 * Pops the top element entity from the entities stack
595 *
596 * Returns the entity just removed
597 */
598static xmlNodePtr
599xmlTextReaderEntPop(xmlTextReaderPtr reader)
600{
601 xmlNodePtr ret;
602
603 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000604 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000605 reader->entNr--;
606 if (reader->entNr > 0)
607 reader->ent = reader->entTab[reader->entNr - 1];
608 else
609 reader->ent = NULL;
610 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000611 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000612 return (ret);
613}
614
615/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000616 * xmlTextReaderStartElement:
617 * @ctx: the user data (XML parser context)
618 * @fullname: The element name, including namespace prefix
619 * @atts: An array of name/value attributes pairs, NULL terminated
620 *
621 * called when an opening tag has been processed.
622 */
623static void
624xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
625 const xmlChar **atts) {
626 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
627 xmlTextReaderPtr reader = ctxt->_private;
628
629#ifdef DEBUG_CALLBACKS
630 printf("xmlTextReaderStartElement(%s)\n", fullname);
631#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000632 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000633 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000634 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
635 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
636 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000637 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000638 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000639 if (reader != NULL)
640 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000641}
642
643/**
644 * xmlTextReaderEndElement:
645 * @ctx: the user data (XML parser context)
646 * @fullname: The element name, including namespace prefix
647 *
648 * called when an ending tag has been processed.
649 */
650static void
651xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
652 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
653 xmlTextReaderPtr reader = ctxt->_private;
654
655#ifdef DEBUG_CALLBACKS
656 printf("xmlTextReaderEndElement(%s)\n", fullname);
657#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000659 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000660 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000661}
662
663/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000664 * xmlTextReaderStartElementNs:
665 * @ctx: the user data (XML parser context)
666 * @localname: the local name of the element
667 * @prefix: the element namespace prefix if available
668 * @URI: the element namespace name if available
669 * @nb_namespaces: number of namespace definitions on that node
670 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
671 * @nb_attributes: the number of attributes on that node
672 * nb_defaulted: the number of defaulted attributes.
673 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
674 * attribute values.
675 *
676 * called when an opening tag has been processed.
677 */
678static void
679xmlTextReaderStartElementNs(void *ctx,
680 const xmlChar *localname,
681 const xmlChar *prefix,
682 const xmlChar *URI,
683 int nb_namespaces,
684 const xmlChar **namespaces,
685 int nb_attributes,
686 int nb_defaulted,
687 const xmlChar **attributes)
688{
689 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
690 xmlTextReaderPtr reader = ctxt->_private;
691
692#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000693 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000694#endif
695 if ((reader != NULL) && (reader->startElementNs != NULL)) {
696 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
697 namespaces, nb_attributes, nb_defaulted,
698 attributes);
699 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
700 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
701 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000702 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000703 }
704 if (reader != NULL)
705 reader->state = XML_TEXTREADER_ELEMENT;
706}
707
708/**
709 * xmlTextReaderEndElementNs:
710 * @ctx: the user data (XML parser context)
711 * @localname: the local name of the element
712 * @prefix: the element namespace prefix if available
713 * @URI: the element namespace name if available
714 *
715 * called when an ending tag has been processed.
716 */
717static void
718xmlTextReaderEndElementNs(void *ctx,
719 const xmlChar * localname,
720 const xmlChar * prefix,
721 const xmlChar * URI)
722{
723 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
724 xmlTextReaderPtr reader = ctxt->_private;
725
726#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000727 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000728#endif
729 if ((reader != NULL) && (reader->endElementNs != NULL)) {
730 reader->endElementNs(ctx, localname, prefix, URI);
731 }
732}
733
734
735/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000736 * xmlTextReaderCharacters:
737 * @ctx: the user data (XML parser context)
738 * @ch: a xmlChar string
739 * @len: the number of xmlChar
740 *
741 * receiving some chars from the parser.
742 */
743static void
744xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
745{
746 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
747 xmlTextReaderPtr reader = ctxt->_private;
748
749#ifdef DEBUG_CALLBACKS
750 printf("xmlTextReaderCharacters()\n");
751#endif
752 if ((reader != NULL) && (reader->characters != NULL)) {
753 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000754 }
755}
756
757/**
758 * xmlTextReaderCDataBlock:
759 * @ctx: the user data (XML parser context)
760 * @value: The pcdata content
761 * @len: the block length
762 *
763 * called when a pcdata block has been parsed
764 */
765static void
766xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
767{
768 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
769 xmlTextReaderPtr reader = ctxt->_private;
770
771#ifdef DEBUG_CALLBACKS
772 printf("xmlTextReaderCDataBlock()\n");
773#endif
774 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
775 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000776 }
777}
778
779/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000780 * xmlTextReaderPushData:
781 * @reader: the xmlTextReaderPtr used
782 *
783 * Push data down the progressive parser until a significant callback
784 * got raised.
785 *
786 * Returns -1 in case of failure, 0 otherwise
787 */
788static int
789xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000790 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000791 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000792 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000793
794 if ((reader->input == NULL) || (reader->input->buffer == NULL))
795 return(-1);
796
Daniel Veillardea7751d2002-12-20 00:16:24 +0000797 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 reader->state = XML_TEXTREADER_NONE;
799 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000800
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000801 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000802 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000803 /*
804 * Refill the buffer unless we are at the end of the stream
805 */
806 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
807 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000808 if ((val == 0) &&
809 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
810 if (inbuf->use == reader->cur) {
811 reader->mode = XML_TEXTREADER_MODE_EOF;
812 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000813 }
814 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000815 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000816 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000817 if ((oldstate != XML_TEXTREADER_START) ||
818 (reader->ctxt->myDoc != NULL))
819 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000820 } else if (val == 0) {
821 /* mark the end of the stream and process the remains */
822 reader->mode = XML_TEXTREADER_MODE_EOF;
823 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000824 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000825
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000826 } else
827 break;
828 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000829 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 * parse by block of CHUNK_SIZE bytes, various tests show that
831 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000832 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000833 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000834 val = xmlParseChunk(reader->ctxt,
835 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000836 CHUNK_SIZE, 0);
837 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000838 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000840 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000841 s = inbuf->use - reader->cur;
842 val = xmlParseChunk(reader->ctxt,
843 (const char *) &inbuf->content[reader->cur],
844 s, 0);
845 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000846 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000847 return(-1);
848 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000849 }
850 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000851
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000852 /*
853 * Discard the consumed input when needed and possible
854 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000855 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000856 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
857 if ((reader->cur >= 4096) &&
858 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
859 val = xmlBufferShrink(inbuf, reader->cur);
860 if (val >= 0) {
861 reader->cur -= val;
862 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000863 }
864 }
865 }
866
867 /*
868 * At the end of the stream signal that the work is done to the Push
869 * parser.
870 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000871 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000872 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000873 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000874 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000875 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000876 s, 1);
877 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000878 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000879 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000880 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000881 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000882 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000883 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000884 return(0);
885}
886
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000887#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000888/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000889 * xmlTextReaderValidatePush:
890 * @reader: the xmlTextReaderPtr used
891 *
892 * Push the current node for validation
893 */
894static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000895xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000896 xmlNodePtr node = reader->node;
897
Daniel Veillardf54cd532004-02-25 11:52:31 +0000898#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000899 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
900 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
901 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
902 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
903 reader->ctxt->myDoc, node, node->name);
904 } else {
905 /* TODO use the BuildQName interface */
906 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000907
Daniel Veillardf4e55762003-04-15 23:32:22 +0000908 qname = xmlStrdup(node->ns->prefix);
909 qname = xmlStrcat(qname, BAD_CAST ":");
910 qname = xmlStrcat(qname, node->name);
911 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
912 reader->ctxt->myDoc, node, qname);
913 if (qname != NULL)
914 xmlFree(qname);
915 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000916 }
917#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000918#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000919 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000920 (reader->rngValidCtxt != NULL)) {
921 int ret;
922
923 if (reader->rngFullNode != NULL) return;
924 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
925 reader->ctxt->myDoc,
926 node);
927 if (ret == 0) {
928 /*
929 * this element requires a full tree
930 */
931 node = xmlTextReaderExpand(reader);
932 if (node == NULL) {
933printf("Expand failed !\n");
934 ret = -1;
935 } else {
936 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
937 reader->ctxt->myDoc,
938 node);
939 reader->rngFullNode = node;
940 }
941 }
942 if (ret != 1)
943 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000944 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000945#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000946}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000947
948/**
949 * xmlTextReaderValidateCData:
950 * @reader: the xmlTextReaderPtr used
951 * @data: pointer to the CData
952 * @len: lenght of the CData block in bytes.
953 *
954 * Push some CData for validation
955 */
956static void
957xmlTextReaderValidateCData(xmlTextReaderPtr reader,
958 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000959#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000960 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
961 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
962 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
963 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000964 }
965#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000966#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000967 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000968 (reader->rngValidCtxt != NULL)) {
969 int ret;
970
971 if (reader->rngFullNode != NULL) return;
972 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
973 if (ret != 1)
974 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000975 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000976#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000977}
978
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000979/**
980 * xmlTextReaderValidatePop:
981 * @reader: the xmlTextReaderPtr used
982 *
983 * Pop the current node from validation
984 */
985static void
986xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
987 xmlNodePtr node = reader->node;
988
Daniel Veillardf54cd532004-02-25 11:52:31 +0000989#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000990 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
991 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
992 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
993 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
994 reader->ctxt->myDoc, node, node->name);
995 } else {
996 /* TODO use the BuildQName interface */
997 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000998
Daniel Veillardf4e55762003-04-15 23:32:22 +0000999 qname = xmlStrdup(node->ns->prefix);
1000 qname = xmlStrcat(qname, BAD_CAST ":");
1001 qname = xmlStrcat(qname, node->name);
1002 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1003 reader->ctxt->myDoc, node, qname);
1004 if (qname != NULL)
1005 xmlFree(qname);
1006 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007 }
1008#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001009#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001010 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001011 (reader->rngValidCtxt != NULL)) {
1012 int ret;
1013
1014 if (reader->rngFullNode != NULL) {
1015 if (node == reader->rngFullNode)
1016 reader->rngFullNode = NULL;
1017 return;
1018 }
1019 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1020 reader->ctxt->myDoc,
1021 node);
1022 if (ret != 1)
1023 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001024 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001025#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001026}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001027
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001028/**
1029 * xmlTextReaderValidateEntity:
1030 * @reader: the xmlTextReaderPtr used
1031 *
1032 * Handle the validation when an entity reference is encountered and
1033 * entity substitution is not activated. As a result the parser interface
1034 * must walk through the entity and do the validation calls
1035 */
1036static void
1037xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1038 xmlNodePtr oldnode = reader->node;
1039 xmlNodePtr node = reader->node;
1040 xmlParserCtxtPtr ctxt = reader->ctxt;
1041
1042 do {
1043 if (node->type == XML_ENTITY_REF_NODE) {
1044 /*
1045 * Case where the underlying tree is not availble, lookup the entity
1046 * and walk it.
1047 */
1048 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1049 (ctxt->sax->getEntity != NULL)) {
1050 node->children = (xmlNodePtr)
1051 ctxt->sax->getEntity(ctxt, node->name);
1052 }
1053
1054 if ((node->children != NULL) &&
1055 (node->children->type == XML_ENTITY_DECL) &&
1056 (node->children->children != NULL)) {
1057 xmlTextReaderEntPush(reader, node);
1058 node = node->children->children;
1059 continue;
1060 } else {
1061 /*
1062 * The error has probably be raised already.
1063 */
1064 if (node == oldnode)
1065 break;
1066 node = node->next;
1067 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001068#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001069 } else if (node->type == XML_ELEMENT_NODE) {
1070 reader->node = node;
1071 xmlTextReaderValidatePush(reader);
1072 } else if ((node->type == XML_TEXT_NODE) ||
1073 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001074 xmlTextReaderValidateCData(reader, node->content,
1075 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001076#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001077 }
1078
1079 /*
1080 * go to next node
1081 */
1082 if (node->children != NULL) {
1083 node = node->children;
1084 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001085 } else if (node->type == XML_ELEMENT_NODE) {
1086 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001087 }
1088 if (node->next != NULL) {
1089 node = node->next;
1090 continue;
1091 }
1092 do {
1093 node = node->parent;
1094 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001095 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 if (reader->entNr == 0) {
1097 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001098 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001099 xmlUnlinkNode(tmp);
1100 xmlTextReaderFreeNode(reader, tmp);
1101 } else
1102 break;
1103 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001104 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001105 reader->node = node;
1106 xmlTextReaderValidatePop(reader);
1107 }
1108 if ((node->type == XML_ENTITY_DECL) &&
1109 (reader->ent != NULL) && (reader->ent->children == node)) {
1110 node = xmlTextReaderEntPop(reader);
1111 }
1112 if (node == oldnode)
1113 break;
1114 if (node->next != NULL) {
1115 node = node->next;
1116 break;
1117 }
1118 } while ((node != NULL) && (node != oldnode));
1119 } while ((node != NULL) && (node != oldnode));
1120 reader->node = oldnode;
1121}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001122#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001123
1124
1125/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001126 * xmlTextReaderGetSuccessor:
1127 * @cur: the current node
1128 *
1129 * Get the successor of a node if available.
1130 *
1131 * Returns the successor node or NULL
1132 */
1133static xmlNodePtr
1134xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1135 if (cur == NULL) return(NULL) ; /* ERROR */
1136 if (cur->next != NULL) return(cur->next) ;
1137 do {
1138 cur = cur->parent;
1139 if (cur == NULL) return(NULL);
1140 if (cur->next != NULL) return(cur->next);
1141 } while (cur != NULL);
1142 return(cur);
1143}
1144
1145/**
1146 * xmlTextReaderDoExpand:
1147 * @reader: the xmlTextReaderPtr used
1148 *
1149 * Makes sure that the current node is fully read as well as all its
1150 * descendant. It means the full DOM subtree must be available at the
1151 * end of the call.
1152 *
1153 * Returns 1 if the node was expanded successfully, 0 if there is no more
1154 * nodes to read, or -1 in case of error
1155 */
1156static int
1157xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1158 int val;
1159
1160 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1161 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001162 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001163 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1164
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001165 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1166 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001167 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001168 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001169 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1170 return(1);
1171 val = xmlTextReaderPushData(reader);
1172 if (val < 0)
1173 return(-1);
1174 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1175 return(1);
1176}
1177
1178/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001179 * xmlTextReaderCollectSiblings:
1180 * @node: the first child
1181 *
1182 * Traverse depth-first through all sibling nodes and their children
1183 * nodes and concatenate their content. This is an auxiliary function
1184 * to xmlTextReaderReadString.
1185 *
1186 * Returns a string containing the content, or NULL in case of error.
1187 */
1188static xmlChar *
1189xmlTextReaderCollectSiblings(xmlNodePtr node)
1190{
1191 xmlBufferPtr buffer;
1192 xmlChar *ret;
1193
1194 buffer = xmlBufferCreate();
1195 if (buffer == NULL)
1196 return NULL;
1197
1198 for ( ; node != NULL; node = node->next) {
1199 switch (node->type) {
1200 case XML_TEXT_NODE:
1201 case XML_CDATA_SECTION_NODE:
1202 xmlBufferCat(buffer, node->content);
1203 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001204 case XML_ELEMENT_NODE: {
1205 xmlChar *tmp;
1206
1207 tmp = xmlTextReaderCollectSiblings(node->children);
1208 xmlBufferCat(buffer, tmp);
1209 xmlFree(tmp);
1210 break;
1211 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001212 default:
1213 break;
1214 }
1215 }
1216 ret = buffer->content;
1217 buffer->content = NULL;
1218 xmlBufferFree(buffer);
1219 return(ret);
1220}
1221
1222/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001223 * xmlTextReaderRead:
1224 * @reader: the xmlTextReaderPtr used
1225 *
1226 * Moves the position of the current instance to the next node in
1227 * the stream, exposing its properties.
1228 *
1229 * Returns 1 if the node was read successfully, 0 if there is no more
1230 * nodes to read, or -1 in case of error
1231 */
1232int
1233xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001234 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001235 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001236 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001237
William M. Brack1af55582004-07-22 17:18:00 +00001238
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001239 if (reader == NULL)
1240 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001241 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001242 if (reader->doc != NULL)
1243 return(xmlTextReaderReadTree(reader));
1244 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001245 return(-1);
1246 if (reader->ctxt->wellFormed != 1)
1247 return(-1);
1248
1249#ifdef DEBUG_READER
1250 fprintf(stderr, "\nREAD ");
1251 DUMP_READER
1252#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001253 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1254 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001255 /*
1256 * Initial state
1257 */
1258 do {
1259 val = xmlTextReaderPushData(reader);
1260 if (val < 0)
1261 return(-1);
1262 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001263 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1264 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001265 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001266 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001267 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001268 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001269 if (reader->node == NULL)
1270 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001271 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001273 if (reader->ctxt->myDoc != NULL) {
1274 reader->node = reader->ctxt->myDoc->children;
1275 }
1276 if (reader->node == NULL)
1277 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001278 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001279 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001280 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001281 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001282 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001283 }
1284 oldstate = reader->state;
1285 olddepth = reader->ctxt->nodeNr;
1286 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001287
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001289 if (reader->node == NULL) {
1290 if (reader->mode == XML_TEXTREADER_DONE)
1291 return(0);
1292 else
1293 return(-1);
1294 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001295
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001296 /*
1297 * If we are not backtracking on ancestors or examined nodes,
1298 * that the parser didn't finished or that we arent at the end
1299 * of stream, continue processing.
1300 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001301 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001302 (reader->ctxt->nodeNr == olddepth) &&
1303 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001304 (reader->node->children == NULL) ||
1305 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001306 ((reader->node->children != NULL) &&
1307 (reader->node->children->type == XML_TEXT_NODE) &&
1308 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001309 (reader->node->type == XML_DTD_NODE) ||
1310 (reader->node->type == XML_DOCUMENT_NODE) ||
1311 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001312 ((reader->ctxt->node == NULL) ||
1313 (reader->ctxt->node == reader->node) ||
1314 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001315 (reader->ctxt->instate != XML_PARSER_EOF)) {
1316 val = xmlTextReaderPushData(reader);
1317 if (val < 0)
1318 return(-1);
1319 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001320 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001321 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001323 if ((reader->node->children != NULL) &&
1324 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001325 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001326 (reader->node->type != XML_DTD_NODE)) {
1327 reader->node = reader->node->children;
1328 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001329 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001330 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 }
1332 }
1333 if (reader->node->next != NULL) {
1334 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001335 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001336 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001337 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1338#ifdef LIBXML_XINCLUDE_ENABLED
1339 && (reader->in_xinclude <= 0)
1340#endif
1341 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001342 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001343 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001345#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001346 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001347 (reader->node->type == XML_ELEMENT_NODE))
1348 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001349#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001350 if ((reader->preserves > 0) &&
1351 (reader->node->extra & NODE_IS_SPRESERVED))
1352 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001353 reader->node = reader->node->next;
1354 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001355
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001356 /*
1357 * Cleanup of the old node
1358 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001359 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001360#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001361 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001362#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001363 (reader->entNr == 0) &&
1364 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001365 (reader->node->prev->type != XML_DTD_NODE) &&
1366 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001367 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001368 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001369 xmlUnlinkNode(tmp);
1370 xmlTextReaderFreeNode(reader, tmp);
1371 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001372 }
1373
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001374 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001375 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001376 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001377 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001378 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001379 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001380 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001381 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001382 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001383#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001384 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001385 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001386#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001387 if ((reader->preserves > 0) &&
1388 (reader->node->extra & NODE_IS_SPRESERVED))
1389 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001390 reader->node = reader->node->parent;
1391 if ((reader->node == NULL) ||
1392 (reader->node->type == XML_DOCUMENT_NODE) ||
1393#ifdef LIBXML_DOCB_ENABLED
1394 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1395#endif
1396 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001397 if (reader->mode != XML_TEXTREADER_DONE) {
1398 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1399 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001400 if (val != 0)
1401 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001402 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001403 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001404 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001405
1406 /*
1407 * Cleanup of the old node
1408 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001409 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001410#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001411 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001412#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001413 (reader->entNr == 0) &&
1414 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001415 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001416 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001417 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001418 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001419 }
1420
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001421 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001422 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001423 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001424#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001425 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001426#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001427 (reader->entNr == 0) &&
1428 (reader->node->last != NULL) &&
1429 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1430 xmlNodePtr tmp = reader->node->last;
1431 xmlUnlinkNode(tmp);
1432 xmlTextReaderFreeNode(reader, tmp);
1433 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001434 reader->depth--;
1435 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001436
1437node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001438 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001439
1440 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001441 * If we are in the middle of a piece of CDATA make sure it's finished
1442 */
1443 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001444 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001445 ((reader->node->type == XML_TEXT_NODE) ||
1446 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001447 if (xmlTextReaderExpand(reader) == NULL)
1448 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001449 }
1450
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001451#ifdef LIBXML_XINCLUDE_ENABLED
1452 /*
1453 * Handle XInclude if asked for
1454 */
1455 if ((reader->xinclude) && (reader->node != NULL) &&
1456 (reader->node->type == XML_ELEMENT_NODE) &&
1457 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001458 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1459 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001460 if (reader->xincctxt == NULL) {
1461 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001462 xmlXIncludeSetFlags(reader->xincctxt,
1463 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001464 }
1465 /*
1466 * expand that node and process it
1467 */
William M. Brack42331a92004-07-29 07:07:16 +00001468 if (xmlTextReaderExpand(reader) == NULL)
1469 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001470 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1471 }
1472 if (reader->node->type == XML_XINCLUDE_START) {
1473 reader->in_xinclude++;
1474 goto get_next_node;
1475 }
1476 if (reader->node->type == XML_XINCLUDE_END) {
1477 reader->in_xinclude--;
1478 goto get_next_node;
1479 }
1480#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001481 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001482 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001483 */
1484 if ((reader->node != NULL) &&
1485 (reader->node->type == XML_ENTITY_REF_NODE) &&
1486 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1487 /*
1488 * Case where the underlying tree is not availble, lookup the entity
1489 * and walk it.
1490 */
1491 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1492 (reader->ctxt->sax->getEntity != NULL)) {
1493 reader->node->children = (xmlNodePtr)
1494 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1495 }
1496
1497 if ((reader->node->children != NULL) &&
1498 (reader->node->children->type == XML_ENTITY_DECL) &&
1499 (reader->node->children->children != NULL)) {
1500 xmlTextReaderEntPush(reader, reader->node);
1501 reader->node = reader->node->children->children;
1502 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001503#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001504 } else if ((reader->node != NULL) &&
1505 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001506 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001507 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001508#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001509 }
1510 if ((reader->node != NULL) &&
1511 (reader->node->type == XML_ENTITY_DECL) &&
1512 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1513 reader->node = xmlTextReaderEntPop(reader);
1514 reader->depth++;
1515 goto get_next_node;
1516 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001517#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001518 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001519 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001520
1521 if ((node->type == XML_ELEMENT_NODE) &&
1522 ((reader->state != XML_TEXTREADER_END) &&
1523 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1524 xmlTextReaderValidatePush(reader);
1525 } else if ((node->type == XML_TEXT_NODE) ||
1526 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001527 xmlTextReaderValidateCData(reader, node->content,
1528 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001529 }
1530 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001531#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001532#ifdef LIBXML_PATTERN_ENABLED
1533 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1534 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1535 int i;
1536 for (i = 0;i < reader->patternNr;i++) {
1537 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1538 xmlTextReaderPreserve(reader);
1539 break;
1540 }
1541 }
1542 }
1543#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001544#ifdef LIBXML_SCHEMAS_ENABLED
1545 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1546 (reader->xsdValidErrors == 0) &&
1547 (reader->xsdValidCtxt != NULL)) {
1548 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1549 }
1550#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001551 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001552node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001553 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001554 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001555}
1556
Daniel Veillard67df8092002-12-16 22:04:11 +00001557/**
1558 * xmlTextReaderReadState:
1559 * @reader: the xmlTextReaderPtr used
1560 *
1561 * Gets the read state of the reader.
1562 *
1563 * Returns the state value, or -1 in case of error
1564 */
1565int
1566xmlTextReaderReadState(xmlTextReaderPtr reader) {
1567 if (reader == NULL)
1568 return(-1);
1569 return(reader->mode);
1570}
1571
1572/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001573 * xmlTextReaderExpand:
1574 * @reader: the xmlTextReaderPtr used
1575 *
1576 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001577 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001578 *
1579 * Returns a node pointer valid until the next xmlTextReaderRead() call
1580 * or NULL in case of error.
1581 */
1582xmlNodePtr
1583xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001584 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001585 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001586 if (reader->doc != NULL)
1587 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001588 if (reader->ctxt == NULL)
1589 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001590 if (xmlTextReaderDoExpand(reader) < 0)
1591 return(NULL);
1592 return(reader->node);
1593}
1594
1595/**
1596 * xmlTextReaderNext:
1597 * @reader: the xmlTextReaderPtr used
1598 *
1599 * Skip to the node following the current one in document order while
1600 * avoiding the subtree if any.
1601 *
1602 * Returns 1 if the node was read successfully, 0 if there is no more
1603 * nodes to read, or -1 in case of error
1604 */
1605int
1606xmlTextReaderNext(xmlTextReaderPtr reader) {
1607 int ret;
1608 xmlNodePtr cur;
1609
1610 if (reader == NULL)
1611 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001612 if (reader->doc != NULL)
1613 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001614 cur = reader->node;
1615 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1616 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001617 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001618 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001619 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001620 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001621 do {
1622 ret = xmlTextReaderRead(reader);
1623 if (ret != 1)
1624 return(ret);
1625 } while (reader->node != cur);
1626 return(xmlTextReaderRead(reader));
1627}
1628
1629/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001630 * xmlTextReaderReadInnerXml:
1631 * @reader: the xmlTextReaderPtr used
1632 *
1633 * Reads the contents of the current node, including child nodes and markup.
1634 *
1635 * Returns a string containing the XML content, or NULL if the current node
1636 * is neither an element nor attribute, or has no child nodes. The
1637 * string must be deallocated by the caller.
1638 */
1639xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001640xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1641{
1642 xmlChar *resbuf;
1643 xmlNodePtr node, cur_node;
1644 xmlBufferPtr buff, buff2;
1645 xmlDocPtr doc;
1646
1647 if (xmlTextReaderExpand(reader) == NULL) {
1648 return NULL;
1649 }
1650 doc = reader->doc;
1651 buff = xmlBufferCreate();
1652 for (cur_node = reader->node->children; cur_node != NULL;
1653 cur_node = cur_node->next) {
1654 node = xmlDocCopyNode(cur_node, doc, 1);
1655 buff2 = xmlBufferCreate();
1656 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1657 xmlFreeNode(node);
1658 xmlBufferFree(buff2);
1659 xmlBufferFree(buff);
1660 return NULL;
1661 }
1662 xmlBufferCat(buff, buff2->content);
1663 xmlFreeNode(node);
1664 xmlBufferFree(buff2);
1665 }
1666 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001667 buff->content = NULL;
1668
1669 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001670 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001671}
1672
1673/**
1674 * xmlTextReaderReadOuterXml:
1675 * @reader: the xmlTextReaderPtr used
1676 *
1677 * Reads the contents of the current node, including child nodes and markup.
1678 *
1679 * Returns a string containing the XML content, or NULL if the current node
1680 * is neither an element nor attribute, or has no child nodes. The
1681 * string must be deallocated by the caller.
1682 */
1683xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001684xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1685{
1686 xmlChar *resbuf;
1687 xmlNodePtr node;
1688 xmlBufferPtr buff;
1689 xmlDocPtr doc;
1690
1691 node = reader->node;
1692 doc = reader->doc;
1693 if (xmlTextReaderExpand(reader) == NULL) {
1694 return NULL;
1695 }
1696 node = xmlDocCopyNode(node, doc, 1);
1697 buff = xmlBufferCreate();
1698 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1699 xmlFreeNode(node);
1700 xmlBufferFree(buff);
1701 return NULL;
1702 }
1703
1704 resbuf = buff->content;
1705 buff->content = NULL;
1706
1707 xmlFreeNode(node);
1708 xmlBufferFree(buff);
1709 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001710}
1711
1712/**
1713 * xmlTextReaderReadString:
1714 * @reader: the xmlTextReaderPtr used
1715 *
1716 * Reads the contents of an element or a text node as a string.
1717 *
1718 * Returns a string containing the contents of the Element or Text node,
1719 * or NULL if the reader is positioned on any other type of node.
1720 * The string must be deallocated by the caller.
1721 */
1722xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001723xmlTextReaderReadString(xmlTextReaderPtr reader)
1724{
1725 xmlNodePtr node;
1726
1727 if ((reader == NULL) || (reader->node == NULL))
1728 return(NULL);
1729
1730 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1731 switch (node->type) {
1732 case XML_TEXT_NODE:
1733 if (node->content != NULL)
1734 return(xmlStrdup(node->content));
1735 break;
1736 case XML_ELEMENT_NODE:
1737 if (xmlTextReaderDoExpand(reader) != -1) {
1738 return xmlTextReaderCollectSiblings(node->children);
1739 }
1740 case XML_ATTRIBUTE_NODE:
1741 TODO
1742 break;
1743 default:
1744 break;
1745 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001746 return(NULL);
1747}
1748
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001749#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001750/**
1751 * xmlTextReaderReadBase64:
1752 * @reader: the xmlTextReaderPtr used
1753 * @array: a byte array to store the content.
1754 * @offset: the zero-based index into array where the method should
1755 * begin to write.
1756 * @len: the number of bytes to write.
1757 *
1758 * Reads and decodes the Base64 encoded contents of an element and
1759 * stores the result in a byte buffer.
1760 *
1761 * Returns the number of bytes written to array, or zero if the current
1762 * instance is not positioned on an element or -1 in case of error.
1763 */
1764int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001765xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1766 unsigned char *array ATTRIBUTE_UNUSED,
1767 int offset ATTRIBUTE_UNUSED,
1768 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001769 if ((reader == NULL) || (reader->ctxt == NULL))
1770 return(-1);
1771 if (reader->ctxt->wellFormed != 1)
1772 return(-1);
1773
1774 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1775 return(0);
1776 TODO
1777 return(0);
1778}
1779
1780/**
1781 * xmlTextReaderReadBinHex:
1782 * @reader: the xmlTextReaderPtr used
1783 * @array: a byte array to store the content.
1784 * @offset: the zero-based index into array where the method should
1785 * begin to write.
1786 * @len: the number of bytes to write.
1787 *
1788 * Reads and decodes the BinHex encoded contents of an element and
1789 * stores the result in a byte buffer.
1790 *
1791 * Returns the number of bytes written to array, or zero if the current
1792 * instance is not positioned on an element or -1 in case of error.
1793 */
1794int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001795xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1796 unsigned char *array ATTRIBUTE_UNUSED,
1797 int offset ATTRIBUTE_UNUSED,
1798 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001799 if ((reader == NULL) || (reader->ctxt == NULL))
1800 return(-1);
1801 if (reader->ctxt->wellFormed != 1)
1802 return(-1);
1803
1804 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1805 return(0);
1806 TODO
1807 return(0);
1808}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001809#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001810
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001811/************************************************************************
1812 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001813 * Operating on a preparsed tree *
1814 * *
1815 ************************************************************************/
1816static int
1817xmlTextReaderNextTree(xmlTextReaderPtr reader)
1818{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001819 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001820 return(-1);
1821
1822 if (reader->state == XML_TEXTREADER_END)
1823 return(0);
1824
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001825 if (reader->node == NULL) {
1826 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001827 reader->state = XML_TEXTREADER_END;
1828 return(0);
1829 }
1830
1831 reader->node = reader->doc->children;
1832 reader->state = XML_TEXTREADER_START;
1833 return(1);
1834 }
1835
1836 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1837 if (reader->node->children != 0) {
1838 reader->node = reader->node->children;
1839 reader->depth++;
1840 reader->state = XML_TEXTREADER_START;
1841 return(1);
1842 }
1843
1844 if ((reader->node->type == XML_ELEMENT_NODE) ||
1845 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1846 reader->state = XML_TEXTREADER_BACKTRACK;
1847 return(1);
1848 }
1849 }
1850
1851 if (reader->node->next != 0) {
1852 reader->node = reader->node->next;
1853 reader->state = XML_TEXTREADER_START;
1854 return(1);
1855 }
1856
1857 if (reader->node->parent != 0) {
1858 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1859 reader->state = XML_TEXTREADER_END;
1860 return(0);
1861 }
1862
1863 reader->node = reader->node->parent;
1864 reader->depth--;
1865 reader->state = XML_TEXTREADER_BACKTRACK;
1866 return(1);
1867 }
1868
1869 reader->state = XML_TEXTREADER_END;
1870
1871 return(1);
1872}
1873
1874/**
1875 * xmlTextReaderReadTree:
1876 * @reader: the xmlTextReaderPtr used
1877 *
1878 * Moves the position of the current instance to the next node in
1879 * the stream, exposing its properties.
1880 *
1881 * Returns 1 if the node was read successfully, 0 if there is no more
1882 * nodes to read, or -1 in case of error
1883 */
1884static int
1885xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1886 if (reader->state == XML_TEXTREADER_END)
1887 return(0);
1888
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001889next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001890 if (reader->node == NULL) {
1891 if (reader->doc->children == NULL) {
1892 reader->state = XML_TEXTREADER_END;
1893 return(0);
1894 }
1895
1896 reader->node = reader->doc->children;
1897 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001898 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001899 }
1900
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001901 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1902 (reader->node->type != XML_DTD_NODE) &&
1903 (reader->node->type != XML_XINCLUDE_START) &&
1904 (reader->node->type != XML_ENTITY_REF_NODE)) {
1905 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001906 reader->node = reader->node->children;
1907 reader->depth++;
1908 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001909 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 }
1911
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001912 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001913 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001914 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001915 }
1916 }
1917
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001918 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001919 reader->node = reader->node->next;
1920 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001921 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001922 }
1923
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001924 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001925 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1926 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1927 reader->state = XML_TEXTREADER_END;
1928 return(0);
1929 }
1930
1931 reader->node = reader->node->parent;
1932 reader->depth--;
1933 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001934 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001935 }
1936
1937 reader->state = XML_TEXTREADER_END;
1938
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001939found_node:
1940 if ((reader->node->type == XML_XINCLUDE_START) ||
1941 (reader->node->type == XML_XINCLUDE_END))
1942 goto next_node;
1943
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001944 return(1);
1945}
1946
1947/**
William M. Brackb1d53162003-11-18 06:54:40 +00001948 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001949 * @reader: the xmlTextReaderPtr used
1950 *
1951 * Skip to the node following the current one in document order while
1952 * avoiding the subtree if any.
1953 * Currently implemented only for Readers built on a document
1954 *
1955 * Returns 1 if the node was read successfully, 0 if there is no more
1956 * nodes to read, or -1 in case of error
1957 */
1958int
1959xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1960 if (reader == NULL)
1961 return(-1);
1962 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001963 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001964 return(-1);
1965 }
1966
1967 if (reader->state == XML_TEXTREADER_END)
1968 return(0);
1969
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001970 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001971 return(xmlTextReaderNextTree(reader));
1972
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001973 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001974 reader->node = reader->node->next;
1975 reader->state = XML_TEXTREADER_START;
1976 return(1);
1977 }
1978
1979 return(0);
1980}
1981
1982/************************************************************************
1983 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001984 * Constructor and destructors *
1985 * *
1986 ************************************************************************/
1987/**
1988 * xmlNewTextReader:
1989 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001990 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001991 *
1992 * Create an xmlTextReader structure fed with @input
1993 *
1994 * Returns the new xmlTextReaderPtr or NULL in case of error
1995 */
1996xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001997xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001998 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001999
2000 if (input == NULL)
2001 return(NULL);
2002 ret = xmlMalloc(sizeof(xmlTextReader));
2003 if (ret == NULL) {
2004 xmlGenericError(xmlGenericErrorContext,
2005 "xmlNewTextReader : malloc failed\n");
2006 return(NULL);
2007 }
2008 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002009 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002010 ret->entTab = NULL;
2011 ret->entMax = 0;
2012 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002013 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002014 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002015 if (ret->buffer == NULL) {
2016 xmlFree(ret);
2017 xmlGenericError(xmlGenericErrorContext,
2018 "xmlNewTextReader : malloc failed\n");
2019 return(NULL);
2020 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002021 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2022 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002023 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002024 xmlFree(ret);
2025 xmlGenericError(xmlGenericErrorContext,
2026 "xmlNewTextReader : malloc failed\n");
2027 return(NULL);
2028 }
Daniel Veillard81273902003-09-30 00:43:48 +00002029 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002030 ret->startElement = ret->sax->startElement;
2031 ret->sax->startElement = xmlTextReaderStartElement;
2032 ret->endElement = ret->sax->endElement;
2033 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002034#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002035 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002036#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002037 ret->startElementNs = ret->sax->startElementNs;
2038 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2039 ret->endElementNs = ret->sax->endElementNs;
2040 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002041#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002042 } else {
2043 ret->startElementNs = NULL;
2044 ret->endElementNs = NULL;
2045 }
Daniel Veillard81273902003-09-30 00:43:48 +00002046#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002047 ret->characters = ret->sax->characters;
2048 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002049 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002050 ret->cdataBlock = ret->sax->cdataBlock;
2051 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002052
Daniel Veillard67df8092002-12-16 22:04:11 +00002053 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002054 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002055 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002056 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002057 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002058 }
2059 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002060 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002061 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002062 ret->base = 0;
2063 ret->cur = 4;
2064 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002065 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002066 ret->base = 0;
2067 ret->cur = 0;
2068 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002069
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002070 if (ret->ctxt == NULL) {
2071 xmlGenericError(xmlGenericErrorContext,
2072 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002073 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002074 xmlFree(ret->sax);
2075 xmlFree(ret);
2076 return(NULL);
2077 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002078 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002079 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002080 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002081 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002082 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002083 /*
2084 * use the parser dictionnary to allocate all elements and attributes names
2085 */
2086 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002087 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002088#ifdef LIBXML_XINCLUDE_ENABLED
2089 ret->xinclude = 0;
2090#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002091#ifdef LIBXML_PATTERN_ENABLED
2092 ret->patternMax = 0;
2093 ret->patternTab = NULL;
2094#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002095 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002096}
2097
2098/**
2099 * xmlNewTextReaderFilename:
2100 * @URI: the URI of the resource to process
2101 *
2102 * Create an xmlTextReader structure fed with the resource at @URI
2103 *
2104 * Returns the new xmlTextReaderPtr or NULL in case of error
2105 */
2106xmlTextReaderPtr
2107xmlNewTextReaderFilename(const char *URI) {
2108 xmlParserInputBufferPtr input;
2109 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002110 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002111
2112 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2113 if (input == NULL)
2114 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002115 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002116 if (ret == NULL) {
2117 xmlFreeParserInputBuffer(input);
2118 return(NULL);
2119 }
2120 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002121 if (ret->ctxt->directory == NULL)
2122 directory = xmlParserGetDirectory(URI);
2123 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2124 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2125 if (directory != NULL)
2126 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002127 return(ret);
2128}
2129
2130/**
2131 * xmlFreeTextReader:
2132 * @reader: the xmlTextReaderPtr
2133 *
2134 * Deallocate all the resources associated to the reader
2135 */
2136void
2137xmlFreeTextReader(xmlTextReaderPtr reader) {
2138 if (reader == NULL)
2139 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002140#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002141 if (reader->rngSchemas != NULL) {
2142 xmlRelaxNGFree(reader->rngSchemas);
2143 reader->rngSchemas = NULL;
2144 }
2145 if (reader->rngValidCtxt != NULL) {
2146 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2147 reader->rngValidCtxt = NULL;
2148 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002149 if (reader->xsdPlug != NULL) {
2150 xmlSchemaSAXUnplug(reader->xsdPlug);
2151 reader->xsdPlug = NULL;
2152 }
2153 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002154 if (! reader->xsdPreserveCtxt)
2155 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002156 reader->xsdValidCtxt = NULL;
2157 }
2158 if (reader->xsdSchemas != NULL) {
2159 xmlSchemaFree(reader->xsdSchemas);
2160 reader->xsdSchemas = NULL;
2161 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002162#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002163#ifdef LIBXML_XINCLUDE_ENABLED
2164 if (reader->xincctxt != NULL)
2165 xmlXIncludeFreeContext(reader->xincctxt);
2166#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002167#ifdef LIBXML_PATTERN_ENABLED
2168 if (reader->patternTab != NULL) {
2169 int i;
2170 for (i = 0;i < reader->patternNr;i++) {
2171 if (reader->patternTab[i] != NULL)
2172 xmlFreePattern(reader->patternTab[i]);
2173 }
2174 xmlFree(reader->patternTab);
2175 }
2176#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002177 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002178 if (reader->dict == reader->ctxt->dict)
2179 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002180 if (reader->ctxt->myDoc != NULL) {
2181 if (reader->preserve == 0)
2182 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2183 reader->ctxt->myDoc = NULL;
2184 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002185 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2186 (reader->ctxt->vctxt.vstateMax > 0)){
2187 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002188 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002189 reader->ctxt->vctxt.vstateMax = 0;
2190 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002191 if (reader->allocs & XML_TEXTREADER_CTXT)
2192 xmlFreeParserCtxt(reader->ctxt);
2193 }
2194 if (reader->sax != NULL)
2195 xmlFree(reader->sax);
2196 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2197 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002198 if (reader->faketext != NULL) {
2199 xmlFreeNode(reader->faketext);
2200 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002201 if (reader->buffer != NULL)
2202 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002203 if (reader->entTab != NULL)
2204 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002205 if (reader->dict != NULL)
2206 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002207 xmlFree(reader);
2208}
2209
2210/************************************************************************
2211 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002212 * Methods for XmlTextReader *
2213 * *
2214 ************************************************************************/
2215/**
2216 * xmlTextReaderClose:
2217 * @reader: the xmlTextReaderPtr used
2218 *
2219 * This method releases any resources allocated by the current instance
2220 * changes the state to Closed and close any underlying input.
2221 *
2222 * Returns 0 or -1 in case of error
2223 */
2224int
2225xmlTextReaderClose(xmlTextReaderPtr reader) {
2226 if (reader == NULL)
2227 return(-1);
2228 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002229 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002230 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2231 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002232 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002233 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002234 if (reader->preserve == 0)
2235 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002236 reader->ctxt->myDoc = NULL;
2237 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002238 }
2239 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2240 xmlFreeParserInputBuffer(reader->input);
2241 reader->allocs -= XML_TEXTREADER_INPUT;
2242 }
2243 return(0);
2244}
2245
2246/**
2247 * xmlTextReaderGetAttributeNo:
2248 * @reader: the xmlTextReaderPtr used
2249 * @no: the zero-based index of the attribute relative to the containing element
2250 *
2251 * Provides the value of the attribute with the specified index relative
2252 * to the containing element.
2253 *
2254 * Returns a string containing the value of the specified attribute, or NULL
2255 * in case of error. The string must be deallocated by the caller.
2256 */
2257xmlChar *
2258xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2259 xmlChar *ret;
2260 int i;
2261 xmlAttrPtr cur;
2262 xmlNsPtr ns;
2263
2264 if (reader == NULL)
2265 return(NULL);
2266 if (reader->node == NULL)
2267 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002268 if (reader->curnode != NULL)
2269 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002270 /* TODO: handle the xmlDecl */
2271 if (reader->node->type != XML_ELEMENT_NODE)
2272 return(NULL);
2273
2274 ns = reader->node->nsDef;
2275 for (i = 0;(i < no) && (ns != NULL);i++) {
2276 ns = ns->next;
2277 }
2278 if (ns != NULL)
2279 return(xmlStrdup(ns->href));
2280
2281 cur = reader->node->properties;
2282 if (cur == NULL)
2283 return(NULL);
2284 for (;i < no;i++) {
2285 cur = cur->next;
2286 if (cur == NULL)
2287 return(NULL);
2288 }
2289 /* TODO walk the DTD if present */
2290
2291 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2292 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2293 return(ret);
2294}
2295
2296/**
2297 * xmlTextReaderGetAttribute:
2298 * @reader: the xmlTextReaderPtr used
2299 * @name: the qualified name of the attribute.
2300 *
2301 * Provides the value of the attribute with the specified qualified name.
2302 *
2303 * Returns a string containing the value of the specified attribute, or NULL
2304 * in case of error. The string must be deallocated by the caller.
2305 */
2306xmlChar *
2307xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2308 xmlChar *prefix = NULL;
2309 xmlChar *localname;
2310 xmlNsPtr ns;
2311 xmlChar *ret = NULL;
2312
2313 if ((reader == NULL) || (name == NULL))
2314 return(NULL);
2315 if (reader->node == NULL)
2316 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002317 if (reader->curnode != NULL)
2318 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002319
2320 /* TODO: handle the xmlDecl */
2321 if (reader->node->type != XML_ELEMENT_NODE)
2322 return(NULL);
2323
2324 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002325 if (localname == NULL) {
2326 /*
2327 * Namespace default decl
2328 */
2329 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2330 ns = reader->node->nsDef;
2331 while (ns != NULL) {
2332 if (ns->prefix == NULL) {
2333 return(xmlStrdup(ns->href));
2334 }
2335 ns = ns->next;
2336 }
2337 return NULL;
2338 }
2339 return(xmlGetNoNsProp(reader->node, name));
2340 }
2341
2342 /*
2343 * Namespace default decl
2344 */
2345 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2346 ns = reader->node->nsDef;
2347 while (ns != NULL) {
2348 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2349 ret = xmlStrdup(ns->href);
2350 break;
2351 }
2352 ns = ns->next;
2353 }
2354 } else {
2355 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2356 if (ns != NULL)
2357 ret = xmlGetNsProp(reader->node, localname, ns->href);
2358 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002359
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002360 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002361 if (prefix != NULL)
2362 xmlFree(prefix);
2363 return(ret);
2364}
2365
2366
2367/**
2368 * xmlTextReaderGetAttributeNs:
2369 * @reader: the xmlTextReaderPtr used
2370 * @localName: the local name of the attribute.
2371 * @namespaceURI: the namespace URI of the attribute.
2372 *
2373 * Provides the value of the specified attribute
2374 *
2375 * Returns a string containing the value of the specified attribute, or NULL
2376 * in case of error. The string must be deallocated by the caller.
2377 */
2378xmlChar *
2379xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2380 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002381 xmlChar *prefix = NULL;
2382 xmlNsPtr ns;
2383
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002384 if ((reader == NULL) || (localName == NULL))
2385 return(NULL);
2386 if (reader->node == NULL)
2387 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002388 if (reader->curnode != NULL)
2389 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002390
2391 /* TODO: handle the xmlDecl */
2392 if (reader->node->type != XML_ELEMENT_NODE)
2393 return(NULL);
2394
Daniel Veillard45b97e72005-08-20 21:14:28 +00002395 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2396 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2397 prefix = BAD_CAST localName;
2398 }
2399 ns = reader->node->nsDef;
2400 while (ns != NULL) {
2401 if ((prefix == NULL && ns->prefix == NULL) ||
2402 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2403 return xmlStrdup(ns->href);
2404 }
2405 ns = ns->next;
2406 }
2407 return NULL;
2408 }
2409
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002410 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2411}
2412
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002413/**
2414 * xmlTextReaderGetRemainder:
2415 * @reader: the xmlTextReaderPtr used
2416 *
2417 * Method to get the remainder of the buffered XML. this method stops the
2418 * parser, set its state to End Of File and return the input stream with
2419 * what is left that the parser did not use.
2420 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002421 * The implementation is not good, the parser certainly procgressed past
2422 * what's left in reader->input, and there is an allocation problem. Best
2423 * would be to rewrite it differently.
2424 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002425 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2426 * in case of error.
2427 */
2428xmlParserInputBufferPtr
2429xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2430 xmlParserInputBufferPtr ret = NULL;
2431
2432 if (reader == NULL)
2433 return(NULL);
2434 if (reader->node == NULL)
2435 return(NULL);
2436
2437 reader->node = NULL;
2438 reader->curnode = NULL;
2439 reader->mode = XML_TEXTREADER_MODE_EOF;
2440 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002441 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002442 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002443 if (reader->preserve == 0)
2444 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002445 reader->ctxt->myDoc = NULL;
2446 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002447 }
2448 if (reader->allocs & XML_TEXTREADER_INPUT) {
2449 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002450 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002451 reader->allocs -= XML_TEXTREADER_INPUT;
2452 } else {
2453 /*
2454 * Hum, one may need to duplicate the data structure because
2455 * without reference counting the input may be freed twice:
2456 * - by the layer which allocated it.
2457 * - by the layer to which would have been returned to.
2458 */
2459 TODO
2460 return(NULL);
2461 }
2462 return(ret);
2463}
2464
2465/**
2466 * xmlTextReaderLookupNamespace:
2467 * @reader: the xmlTextReaderPtr used
2468 * @prefix: the prefix whose namespace URI is to be resolved. To return
2469 * the default namespace, specify NULL
2470 *
2471 * Resolves a namespace prefix in the scope of the current element.
2472 *
2473 * Returns a string containing the namespace URI to which the prefix maps
2474 * or NULL in case of error. The string must be deallocated by the caller.
2475 */
2476xmlChar *
2477xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2478 xmlNsPtr ns;
2479
2480 if (reader == NULL)
2481 return(NULL);
2482 if (reader->node == NULL)
2483 return(NULL);
2484
2485 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2486 if (ns == NULL)
2487 return(NULL);
2488 return(xmlStrdup(ns->href));
2489}
2490
2491/**
2492 * xmlTextReaderMoveToAttributeNo:
2493 * @reader: the xmlTextReaderPtr used
2494 * @no: the zero-based index of the attribute relative to the containing
2495 * element.
2496 *
2497 * Moves the position of the current instance to the attribute with
2498 * the specified index relative to the containing element.
2499 *
2500 * Returns 1 in case of success, -1 in case of error, 0 if not found
2501 */
2502int
2503xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2504 int i;
2505 xmlAttrPtr cur;
2506 xmlNsPtr ns;
2507
2508 if (reader == NULL)
2509 return(-1);
2510 if (reader->node == NULL)
2511 return(-1);
2512 /* TODO: handle the xmlDecl */
2513 if (reader->node->type != XML_ELEMENT_NODE)
2514 return(-1);
2515
2516 reader->curnode = NULL;
2517
2518 ns = reader->node->nsDef;
2519 for (i = 0;(i < no) && (ns != NULL);i++) {
2520 ns = ns->next;
2521 }
2522 if (ns != NULL) {
2523 reader->curnode = (xmlNodePtr) ns;
2524 return(1);
2525 }
2526
2527 cur = reader->node->properties;
2528 if (cur == NULL)
2529 return(0);
2530 for (;i < no;i++) {
2531 cur = cur->next;
2532 if (cur == NULL)
2533 return(0);
2534 }
2535 /* TODO walk the DTD if present */
2536
2537 reader->curnode = (xmlNodePtr) cur;
2538 return(1);
2539}
2540
2541/**
2542 * xmlTextReaderMoveToAttribute:
2543 * @reader: the xmlTextReaderPtr used
2544 * @name: the qualified name of the attribute.
2545 *
2546 * Moves the position of the current instance to the attribute with
2547 * the specified qualified name.
2548 *
2549 * Returns 1 in case of success, -1 in case of error, 0 if not found
2550 */
2551int
2552xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2553 xmlChar *prefix = NULL;
2554 xmlChar *localname;
2555 xmlNsPtr ns;
2556 xmlAttrPtr prop;
2557
2558 if ((reader == NULL) || (name == NULL))
2559 return(-1);
2560 if (reader->node == NULL)
2561 return(-1);
2562
2563 /* TODO: handle the xmlDecl */
2564 if (reader->node->type != XML_ELEMENT_NODE)
2565 return(0);
2566
2567 localname = xmlSplitQName2(name, &prefix);
2568 if (localname == NULL) {
2569 /*
2570 * Namespace default decl
2571 */
2572 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2573 ns = reader->node->nsDef;
2574 while (ns != NULL) {
2575 if (ns->prefix == NULL) {
2576 reader->curnode = (xmlNodePtr) ns;
2577 return(1);
2578 }
2579 ns = ns->next;
2580 }
2581 return(0);
2582 }
2583
2584 prop = reader->node->properties;
2585 while (prop != NULL) {
2586 /*
2587 * One need to have
2588 * - same attribute names
2589 * - and the attribute carrying that namespace
2590 */
2591 if ((xmlStrEqual(prop->name, name)) &&
2592 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2593 reader->curnode = (xmlNodePtr) prop;
2594 return(1);
2595 }
2596 prop = prop->next;
2597 }
2598 return(0);
2599 }
2600
2601 /*
2602 * Namespace default decl
2603 */
2604 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2605 ns = reader->node->nsDef;
2606 while (ns != NULL) {
2607 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2608 reader->curnode = (xmlNodePtr) ns;
2609 goto found;
2610 }
2611 ns = ns->next;
2612 }
2613 goto not_found;
2614 }
2615 prop = reader->node->properties;
2616 while (prop != NULL) {
2617 /*
2618 * One need to have
2619 * - same attribute names
2620 * - and the attribute carrying that namespace
2621 */
2622 if ((xmlStrEqual(prop->name, localname)) &&
2623 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2624 reader->curnode = (xmlNodePtr) prop;
2625 goto found;
2626 }
2627 prop = prop->next;
2628 }
2629not_found:
2630 if (localname != NULL)
2631 xmlFree(localname);
2632 if (prefix != NULL)
2633 xmlFree(prefix);
2634 return(0);
2635
2636found:
2637 if (localname != NULL)
2638 xmlFree(localname);
2639 if (prefix != NULL)
2640 xmlFree(prefix);
2641 return(1);
2642}
2643
2644/**
2645 * xmlTextReaderMoveToAttributeNs:
2646 * @reader: the xmlTextReaderPtr used
2647 * @localName: the local name of the attribute.
2648 * @namespaceURI: the namespace URI of the attribute.
2649 *
2650 * Moves the position of the current instance to the attribute with the
2651 * specified local name and namespace URI.
2652 *
2653 * Returns 1 in case of success, -1 in case of error, 0 if not found
2654 */
2655int
2656xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2657 const xmlChar *localName, const xmlChar *namespaceURI) {
2658 xmlAttrPtr prop;
2659 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002660 xmlNsPtr ns;
2661 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002662
2663 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2664 return(-1);
2665 if (reader->node == NULL)
2666 return(-1);
2667 if (reader->node->type != XML_ELEMENT_NODE)
2668 return(0);
2669 node = reader->node;
2670
Daniel Veillard45b97e72005-08-20 21:14:28 +00002671 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2672 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2673 prefix = BAD_CAST localName;
2674 }
2675 ns = reader->node->nsDef;
2676 while (ns != NULL) {
2677 if ((prefix == NULL && ns->prefix == NULL) ||
2678 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2679 reader->curnode = (xmlNodePtr) ns;
2680 return(1);
2681 }
2682 ns = ns->next;
2683 }
2684 return(0);
2685 }
2686
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002687 prop = node->properties;
2688 while (prop != NULL) {
2689 /*
2690 * One need to have
2691 * - same attribute names
2692 * - and the attribute carrying that namespace
2693 */
2694 if (xmlStrEqual(prop->name, localName) &&
2695 ((prop->ns != NULL) &&
2696 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2697 reader->curnode = (xmlNodePtr) prop;
2698 return(1);
2699 }
2700 prop = prop->next;
2701 }
2702 return(0);
2703}
2704
2705/**
2706 * xmlTextReaderMoveToFirstAttribute:
2707 * @reader: the xmlTextReaderPtr used
2708 *
2709 * Moves the position of the current instance to the first attribute
2710 * associated with the current node.
2711 *
2712 * Returns 1 in case of success, -1 in case of error, 0 if not found
2713 */
2714int
2715xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2716 if (reader == NULL)
2717 return(-1);
2718 if (reader->node == NULL)
2719 return(-1);
2720 if (reader->node->type != XML_ELEMENT_NODE)
2721 return(0);
2722
2723 if (reader->node->nsDef != NULL) {
2724 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2725 return(1);
2726 }
2727 if (reader->node->properties != NULL) {
2728 reader->curnode = (xmlNodePtr) reader->node->properties;
2729 return(1);
2730 }
2731 return(0);
2732}
2733
2734/**
2735 * xmlTextReaderMoveToNextAttribute:
2736 * @reader: the xmlTextReaderPtr used
2737 *
2738 * Moves the position of the current instance to the next attribute
2739 * associated with the current node.
2740 *
2741 * Returns 1 in case of success, -1 in case of error, 0 if not found
2742 */
2743int
2744xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2745 if (reader == NULL)
2746 return(-1);
2747 if (reader->node == NULL)
2748 return(-1);
2749 if (reader->node->type != XML_ELEMENT_NODE)
2750 return(0);
2751 if (reader->curnode == NULL)
2752 return(xmlTextReaderMoveToFirstAttribute(reader));
2753
2754 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2755 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2756 if (ns->next != NULL) {
2757 reader->curnode = (xmlNodePtr) ns->next;
2758 return(1);
2759 }
2760 if (reader->node->properties != NULL) {
2761 reader->curnode = (xmlNodePtr) reader->node->properties;
2762 return(1);
2763 }
2764 return(0);
2765 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2766 (reader->curnode->next != NULL)) {
2767 reader->curnode = reader->curnode->next;
2768 return(1);
2769 }
2770 return(0);
2771}
2772
2773/**
2774 * xmlTextReaderMoveToElement:
2775 * @reader: the xmlTextReaderPtr used
2776 *
2777 * Moves the position of the current instance to the node that
2778 * contains the current Attribute node.
2779 *
2780 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2781 */
2782int
2783xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2784 if (reader == NULL)
2785 return(-1);
2786 if (reader->node == NULL)
2787 return(-1);
2788 if (reader->node->type != XML_ELEMENT_NODE)
2789 return(0);
2790 if (reader->curnode != NULL) {
2791 reader->curnode = NULL;
2792 return(1);
2793 }
2794 return(0);
2795}
2796
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002797/**
2798 * xmlTextReaderReadAttributeValue:
2799 * @reader: the xmlTextReaderPtr used
2800 *
2801 * Parses an attribute value into one or more Text and EntityReference nodes.
2802 *
2803 * Returns 1 in case of success, 0 if the reader was not positionned on an
2804 * ttribute node or all the attribute values have been read, or -1
2805 * in case of error.
2806 */
2807int
2808xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2809 if (reader == NULL)
2810 return(-1);
2811 if (reader->node == NULL)
2812 return(-1);
2813 if (reader->curnode == NULL)
2814 return(0);
2815 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2816 if (reader->curnode->children == NULL)
2817 return(0);
2818 reader->curnode = reader->curnode->children;
2819 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2820 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2821
2822 if (reader->faketext == NULL) {
2823 reader->faketext = xmlNewDocText(reader->node->doc,
2824 ns->href);
2825 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002826 if ((reader->faketext->content != NULL) &&
2827 (reader->faketext->content !=
2828 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002829 xmlFree(reader->faketext->content);
2830 reader->faketext->content = xmlStrdup(ns->href);
2831 }
2832 reader->curnode = reader->faketext;
2833 } else {
2834 if (reader->curnode->next == NULL)
2835 return(0);
2836 reader->curnode = reader->curnode->next;
2837 }
2838 return(1);
2839}
2840
Daniel Veillarde2811272004-10-19 09:04:23 +00002841/**
2842 * xmlTextReaderConstEncoding:
2843 * @reader: the xmlTextReaderPtr used
2844 *
2845 * Determine the encoding of the document being read.
2846 *
2847 * Returns a string containing the encoding of the document or NULL in
2848 * case of error. The string is deallocated with the reader.
2849 */
2850const xmlChar *
2851xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2852 xmlDocPtr doc = NULL;
2853 if (reader == NULL)
2854 return(NULL);
2855 if (reader->doc != NULL)
2856 doc = reader->doc;
2857 else if (reader->ctxt != NULL)
2858 doc = reader->ctxt->myDoc;
2859 if (doc == NULL)
2860 return(NULL);
2861
2862 if (doc->encoding == NULL)
2863 return(NULL);
2864 else
2865 return(CONSTSTR(doc->encoding));
2866}
2867
2868
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002869/************************************************************************
2870 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002871 * Acces API to the current node *
2872 * *
2873 ************************************************************************/
2874/**
2875 * xmlTextReaderAttributeCount:
2876 * @reader: the xmlTextReaderPtr used
2877 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002878 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002879 *
2880 * Returns 0 i no attributes, -1 in case of error or the attribute count
2881 */
2882int
2883xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2884 int ret;
2885 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002886 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002887 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002888
2889 if (reader == NULL)
2890 return(-1);
2891 if (reader->node == NULL)
2892 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002893
2894 if (reader->curnode != NULL)
2895 node = reader->curnode;
2896 else
2897 node = reader->node;
2898
2899 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002900 return(0);
2901 if ((reader->state == XML_TEXTREADER_END) ||
2902 (reader->state == XML_TEXTREADER_BACKTRACK))
2903 return(0);
2904 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002905 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002906 while (attr != NULL) {
2907 ret++;
2908 attr = attr->next;
2909 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002910 ns = node->nsDef;
2911 while (ns != NULL) {
2912 ret++;
2913 ns = ns->next;
2914 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002915 return(ret);
2916}
2917
2918/**
2919 * xmlTextReaderNodeType:
2920 * @reader: the xmlTextReaderPtr used
2921 *
2922 * Get the node type of the current node
2923 * Reference:
2924 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2925 *
2926 * Returns the xmlNodeType of the current node or -1 in case of error
2927 */
2928int
2929xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002930 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002931
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002932 if (reader == NULL)
2933 return(-1);
2934 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002935 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002936 if (reader->curnode != NULL)
2937 node = reader->curnode;
2938 else
2939 node = reader->node;
2940 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002941 case XML_ELEMENT_NODE:
2942 if ((reader->state == XML_TEXTREADER_END) ||
2943 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002944 return(XML_READER_TYPE_END_ELEMENT);
2945 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002946 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002947 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002948 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002949 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002950 if (xmlIsBlankNode(reader->node)) {
2951 if (xmlNodeGetSpacePreserve(reader->node))
2952 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2953 else
2954 return(XML_READER_TYPE_WHITESPACE);
2955 } else {
2956 return(XML_READER_TYPE_TEXT);
2957 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002958 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002959 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002960 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002961 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002962 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002963 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002964 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002965 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002966 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002967 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002968 case XML_DOCUMENT_NODE:
2969 case XML_HTML_DOCUMENT_NODE:
2970#ifdef LIBXML_DOCB_ENABLED
2971 case XML_DOCB_DOCUMENT_NODE:
2972#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002973 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002974 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002975 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002976 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002977 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002978 case XML_DOCUMENT_TYPE_NODE:
2979 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002980 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002981
2982 case XML_ELEMENT_DECL:
2983 case XML_ATTRIBUTE_DECL:
2984 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985 case XML_XINCLUDE_START:
2986 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002987 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002988 }
2989 return(-1);
2990}
2991
2992/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002993 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002994 * @reader: the xmlTextReaderPtr used
2995 *
2996 * Check if the current node is empty
2997 *
2998 * Returns 1 if empty, 0 if not and -1 in case of error
2999 */
3000int
3001xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3002 if ((reader == NULL) || (reader->node == NULL))
3003 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003004 if (reader->node->type != XML_ELEMENT_NODE)
3005 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003006 if (reader->curnode != NULL)
3007 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003008 if (reader->node->children != NULL)
3009 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003010 if (reader->state == XML_TEXTREADER_END)
3011 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003012 if (reader->doc != NULL)
3013 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003014#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003015 if (reader->in_xinclude > 0)
3016 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003017#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003018 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003019}
3020
3021/**
3022 * xmlTextReaderLocalName:
3023 * @reader: the xmlTextReaderPtr used
3024 *
3025 * The local name of the node.
3026 *
3027 * Returns the local name or NULL if not available
3028 */
3029xmlChar *
3030xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003031 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003032 if ((reader == NULL) || (reader->node == NULL))
3033 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003034 if (reader->curnode != NULL)
3035 node = reader->curnode;
3036 else
3037 node = reader->node;
3038 if (node->type == XML_NAMESPACE_DECL) {
3039 xmlNsPtr ns = (xmlNsPtr) node;
3040 if (ns->prefix == NULL)
3041 return(xmlStrdup(BAD_CAST "xmlns"));
3042 else
3043 return(xmlStrdup(ns->prefix));
3044 }
3045 if ((node->type != XML_ELEMENT_NODE) &&
3046 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003047 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003048 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003049}
3050
3051/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003052 * xmlTextReaderConstLocalName:
3053 * @reader: the xmlTextReaderPtr used
3054 *
3055 * The local name of the node.
3056 *
3057 * Returns the local name or NULL if not available, the
3058 * string will be deallocated with the reader.
3059 */
3060const xmlChar *
3061xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3062 xmlNodePtr node;
3063 if ((reader == NULL) || (reader->node == NULL))
3064 return(NULL);
3065 if (reader->curnode != NULL)
3066 node = reader->curnode;
3067 else
3068 node = reader->node;
3069 if (node->type == XML_NAMESPACE_DECL) {
3070 xmlNsPtr ns = (xmlNsPtr) node;
3071 if (ns->prefix == NULL)
3072 return(CONSTSTR(BAD_CAST "xmlns"));
3073 else
3074 return(ns->prefix);
3075 }
3076 if ((node->type != XML_ELEMENT_NODE) &&
3077 (node->type != XML_ATTRIBUTE_NODE))
3078 return(xmlTextReaderConstName(reader));
3079 return(node->name);
3080}
3081
3082/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003083 * xmlTextReaderName:
3084 * @reader: the xmlTextReaderPtr used
3085 *
3086 * The qualified name of the node, equal to Prefix :LocalName.
3087 *
3088 * Returns the local name or NULL if not available
3089 */
3090xmlChar *
3091xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003092 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003093 xmlChar *ret;
3094
3095 if ((reader == NULL) || (reader->node == NULL))
3096 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003097 if (reader->curnode != NULL)
3098 node = reader->curnode;
3099 else
3100 node = reader->node;
3101 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003102 case XML_ELEMENT_NODE:
3103 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003104 if ((node->ns == NULL) ||
3105 (node->ns->prefix == NULL))
3106 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003107
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003108 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003109 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003110 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003111 return(ret);
3112 case XML_TEXT_NODE:
3113 return(xmlStrdup(BAD_CAST "#text"));
3114 case XML_CDATA_SECTION_NODE:
3115 return(xmlStrdup(BAD_CAST "#cdata-section"));
3116 case XML_ENTITY_NODE:
3117 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003118 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003119 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003120 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003121 case XML_COMMENT_NODE:
3122 return(xmlStrdup(BAD_CAST "#comment"));
3123 case XML_DOCUMENT_NODE:
3124 case XML_HTML_DOCUMENT_NODE:
3125#ifdef LIBXML_DOCB_ENABLED
3126 case XML_DOCB_DOCUMENT_NODE:
3127#endif
3128 return(xmlStrdup(BAD_CAST "#document"));
3129 case XML_DOCUMENT_FRAG_NODE:
3130 return(xmlStrdup(BAD_CAST "#document-fragment"));
3131 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003132 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003133 case XML_DOCUMENT_TYPE_NODE:
3134 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003135 return(xmlStrdup(node->name));
3136 case XML_NAMESPACE_DECL: {
3137 xmlNsPtr ns = (xmlNsPtr) node;
3138
3139 ret = xmlStrdup(BAD_CAST "xmlns");
3140 if (ns->prefix == NULL)
3141 return(ret);
3142 ret = xmlStrcat(ret, BAD_CAST ":");
3143 ret = xmlStrcat(ret, ns->prefix);
3144 return(ret);
3145 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003146
3147 case XML_ELEMENT_DECL:
3148 case XML_ATTRIBUTE_DECL:
3149 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003150 case XML_XINCLUDE_START:
3151 case XML_XINCLUDE_END:
3152 return(NULL);
3153 }
3154 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003155}
3156
3157/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003158 * xmlTextReaderConstName:
3159 * @reader: the xmlTextReaderPtr used
3160 *
3161 * The qualified name of the node, equal to Prefix :LocalName.
3162 *
3163 * Returns the local name or NULL if not available, the string is
3164 * deallocated with the reader.
3165 */
3166const xmlChar *
3167xmlTextReaderConstName(xmlTextReaderPtr reader) {
3168 xmlNodePtr node;
3169
3170 if ((reader == NULL) || (reader->node == NULL))
3171 return(NULL);
3172 if (reader->curnode != NULL)
3173 node = reader->curnode;
3174 else
3175 node = reader->node;
3176 switch (node->type) {
3177 case XML_ELEMENT_NODE:
3178 case XML_ATTRIBUTE_NODE:
3179 if ((node->ns == NULL) ||
3180 (node->ns->prefix == NULL))
3181 return(node->name);
3182 return(CONSTQSTR(node->ns->prefix, node->name));
3183 case XML_TEXT_NODE:
3184 return(CONSTSTR(BAD_CAST "#text"));
3185 case XML_CDATA_SECTION_NODE:
3186 return(CONSTSTR(BAD_CAST "#cdata-section"));
3187 case XML_ENTITY_NODE:
3188 case XML_ENTITY_REF_NODE:
3189 return(CONSTSTR(node->name));
3190 case XML_PI_NODE:
3191 return(CONSTSTR(node->name));
3192 case XML_COMMENT_NODE:
3193 return(CONSTSTR(BAD_CAST "#comment"));
3194 case XML_DOCUMENT_NODE:
3195 case XML_HTML_DOCUMENT_NODE:
3196#ifdef LIBXML_DOCB_ENABLED
3197 case XML_DOCB_DOCUMENT_NODE:
3198#endif
3199 return(CONSTSTR(BAD_CAST "#document"));
3200 case XML_DOCUMENT_FRAG_NODE:
3201 return(CONSTSTR(BAD_CAST "#document-fragment"));
3202 case XML_NOTATION_NODE:
3203 return(CONSTSTR(node->name));
3204 case XML_DOCUMENT_TYPE_NODE:
3205 case XML_DTD_NODE:
3206 return(CONSTSTR(node->name));
3207 case XML_NAMESPACE_DECL: {
3208 xmlNsPtr ns = (xmlNsPtr) node;
3209
3210 if (ns->prefix == NULL)
3211 return(CONSTSTR(BAD_CAST "xmlns"));
3212 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3213 }
3214
3215 case XML_ELEMENT_DECL:
3216 case XML_ATTRIBUTE_DECL:
3217 case XML_ENTITY_DECL:
3218 case XML_XINCLUDE_START:
3219 case XML_XINCLUDE_END:
3220 return(NULL);
3221 }
3222 return(NULL);
3223}
3224
3225/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003226 * xmlTextReaderPrefix:
3227 * @reader: the xmlTextReaderPtr used
3228 *
3229 * A shorthand reference to the namespace associated with the node.
3230 *
3231 * Returns the prefix or NULL if not available
3232 */
3233xmlChar *
3234xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003235 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003236 if ((reader == NULL) || (reader->node == NULL))
3237 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003238 if (reader->curnode != NULL)
3239 node = reader->curnode;
3240 else
3241 node = reader->node;
3242 if (node->type == XML_NAMESPACE_DECL) {
3243 xmlNsPtr ns = (xmlNsPtr) node;
3244 if (ns->prefix == NULL)
3245 return(NULL);
3246 return(xmlStrdup(BAD_CAST "xmlns"));
3247 }
3248 if ((node->type != XML_ELEMENT_NODE) &&
3249 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003250 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003251 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003252 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003253 return(NULL);
3254}
3255
3256/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003257 * xmlTextReaderConstPrefix:
3258 * @reader: the xmlTextReaderPtr used
3259 *
3260 * A shorthand reference to the namespace associated with the node.
3261 *
3262 * Returns the prefix or NULL if not available, the string is deallocated
3263 * with the reader.
3264 */
3265const xmlChar *
3266xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3267 xmlNodePtr node;
3268 if ((reader == NULL) || (reader->node == NULL))
3269 return(NULL);
3270 if (reader->curnode != NULL)
3271 node = reader->curnode;
3272 else
3273 node = reader->node;
3274 if (node->type == XML_NAMESPACE_DECL) {
3275 xmlNsPtr ns = (xmlNsPtr) node;
3276 if (ns->prefix == NULL)
3277 return(NULL);
3278 return(CONSTSTR(BAD_CAST "xmlns"));
3279 }
3280 if ((node->type != XML_ELEMENT_NODE) &&
3281 (node->type != XML_ATTRIBUTE_NODE))
3282 return(NULL);
3283 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3284 return(CONSTSTR(node->ns->prefix));
3285 return(NULL);
3286}
3287
3288/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003289 * xmlTextReaderNamespaceUri:
3290 * @reader: the xmlTextReaderPtr used
3291 *
3292 * The URI defining the namespace associated with the node.
3293 *
3294 * Returns the namespace URI or NULL if not available
3295 */
3296xmlChar *
3297xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003298 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003299 if ((reader == NULL) || (reader->node == NULL))
3300 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003301 if (reader->curnode != NULL)
3302 node = reader->curnode;
3303 else
3304 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003305 if (node->type == XML_NAMESPACE_DECL)
3306 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003307 if ((node->type != XML_ELEMENT_NODE) &&
3308 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003309 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003310 if (node->ns != NULL)
3311 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003312 return(NULL);
3313}
3314
3315/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003316 * xmlTextReaderConstNamespaceUri:
3317 * @reader: the xmlTextReaderPtr used
3318 *
3319 * The URI defining the namespace associated with the node.
3320 *
3321 * Returns the namespace URI or NULL if not available, the string
3322 * will be deallocated with the reader
3323 */
3324const xmlChar *
3325xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3326 xmlNodePtr node;
3327 if ((reader == NULL) || (reader->node == NULL))
3328 return(NULL);
3329 if (reader->curnode != NULL)
3330 node = reader->curnode;
3331 else
3332 node = reader->node;
3333 if (node->type == XML_NAMESPACE_DECL)
3334 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3335 if ((node->type != XML_ELEMENT_NODE) &&
3336 (node->type != XML_ATTRIBUTE_NODE))
3337 return(NULL);
3338 if (node->ns != NULL)
3339 return(CONSTSTR(node->ns->href));
3340 return(NULL);
3341}
3342
3343/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003344 * xmlTextReaderBaseUri:
3345 * @reader: the xmlTextReaderPtr used
3346 *
3347 * The base URI of the node.
3348 *
3349 * Returns the base URI or NULL if not available
3350 */
3351xmlChar *
3352xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3353 if ((reader == NULL) || (reader->node == NULL))
3354 return(NULL);
3355 return(xmlNodeGetBase(NULL, reader->node));
3356}
3357
3358/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003359 * xmlTextReaderConstBaseUri:
3360 * @reader: the xmlTextReaderPtr used
3361 *
3362 * The base URI of the node.
3363 *
3364 * Returns the base URI or NULL if not available, the string
3365 * will be deallocated with the reader
3366 */
3367const xmlChar *
3368xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3369 xmlChar *tmp;
3370 const xmlChar *ret;
3371
3372 if ((reader == NULL) || (reader->node == NULL))
3373 return(NULL);
3374 tmp = xmlNodeGetBase(NULL, reader->node);
3375 if (tmp == NULL)
3376 return(NULL);
3377 ret = CONSTSTR(tmp);
3378 xmlFree(tmp);
3379 return(ret);
3380}
3381
3382/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003383 * xmlTextReaderDepth:
3384 * @reader: the xmlTextReaderPtr used
3385 *
3386 * The depth of the node in the tree.
3387 *
3388 * Returns the depth or -1 in case of error
3389 */
3390int
3391xmlTextReaderDepth(xmlTextReaderPtr reader) {
3392 if (reader == NULL)
3393 return(-1);
3394 if (reader->node == NULL)
3395 return(0);
3396
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003397 if (reader->curnode != NULL) {
3398 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3399 (reader->curnode->type == XML_NAMESPACE_DECL))
3400 return(reader->depth + 1);
3401 return(reader->depth + 2);
3402 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003403 return(reader->depth);
3404}
3405
3406/**
3407 * xmlTextReaderHasAttributes:
3408 * @reader: the xmlTextReaderPtr used
3409 *
3410 * Whether the node has attributes.
3411 *
3412 * Returns 1 if true, 0 if false, and -1 in case or error
3413 */
3414int
3415xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003416 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003417 if (reader == NULL)
3418 return(-1);
3419 if (reader->node == NULL)
3420 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003421 if (reader->curnode != NULL)
3422 node = reader->curnode;
3423 else
3424 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003425
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003426 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003427 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003428 return(1);
3429 /* TODO: handle the xmlDecl */
3430 return(0);
3431}
3432
3433/**
3434 * xmlTextReaderHasValue:
3435 * @reader: the xmlTextReaderPtr used
3436 *
3437 * Whether the node can have a text value.
3438 *
3439 * Returns 1 if true, 0 if false, and -1 in case or error
3440 */
3441int
3442xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003443 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003444 if (reader == NULL)
3445 return(-1);
3446 if (reader->node == NULL)
3447 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003448 if (reader->curnode != NULL)
3449 node = reader->curnode;
3450 else
3451 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003452
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003453 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003454 case XML_ATTRIBUTE_NODE:
3455 case XML_TEXT_NODE:
3456 case XML_CDATA_SECTION_NODE:
3457 case XML_PI_NODE:
3458 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003459 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003460 return(1);
3461 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003462 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003463 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003464 return(0);
3465}
3466
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003467/**
3468 * xmlTextReaderValue:
3469 * @reader: the xmlTextReaderPtr used
3470 *
3471 * Provides the text value of the node if present
3472 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003473 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003474 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003475 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003476xmlChar *
3477xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003478 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003479 if (reader == NULL)
3480 return(NULL);
3481 if (reader->node == NULL)
3482 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003483 if (reader->curnode != NULL)
3484 node = reader->curnode;
3485 else
3486 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003487
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003488 switch (node->type) {
3489 case XML_NAMESPACE_DECL:
3490 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003491 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003492 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003493
3494 if (attr->parent != NULL)
3495 return (xmlNodeListGetString
3496 (attr->parent->doc, attr->children, 1));
3497 else
3498 return (xmlNodeListGetString(NULL, attr->children, 1));
3499 break;
3500 }
3501 case XML_TEXT_NODE:
3502 case XML_CDATA_SECTION_NODE:
3503 case XML_PI_NODE:
3504 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003505 if (node->content != NULL)
3506 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003507 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003508 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003509 }
3510 return(NULL);
3511}
3512
3513/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003514 * xmlTextReaderConstValue:
3515 * @reader: the xmlTextReaderPtr used
3516 *
3517 * Provides the text value of the node if present
3518 *
3519 * Returns the string or NULL if not available. The result will be
3520 * deallocated on the next Read() operation.
3521 */
3522const xmlChar *
3523xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3524 xmlNodePtr node;
3525 if (reader == NULL)
3526 return(NULL);
3527 if (reader->node == NULL)
3528 return(NULL);
3529 if (reader->curnode != NULL)
3530 node = reader->curnode;
3531 else
3532 node = reader->node;
3533
3534 switch (node->type) {
3535 case XML_NAMESPACE_DECL:
3536 return(((xmlNsPtr) node)->href);
3537 case XML_ATTRIBUTE_NODE:{
3538 xmlAttrPtr attr = (xmlAttrPtr) node;
3539
3540 if ((attr->children != NULL) &&
3541 (attr->children->type == XML_TEXT_NODE) &&
3542 (attr->children->next == NULL))
3543 return(attr->children->content);
3544 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003545 if (reader->buffer == NULL)
3546 reader->buffer = xmlBufferCreateSize(100);
3547 if (reader->buffer == NULL) {
3548 xmlGenericError(xmlGenericErrorContext,
3549 "xmlTextReaderSetup : malloc failed\n");
3550 return (NULL);
3551 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003552 reader->buffer->use = 0;
3553 xmlNodeBufGetContent(reader->buffer, node);
3554 return(reader->buffer->content);
3555 }
3556 break;
3557 }
3558 case XML_TEXT_NODE:
3559 case XML_CDATA_SECTION_NODE:
3560 case XML_PI_NODE:
3561 case XML_COMMENT_NODE:
3562 return(node->content);
3563 default:
3564 break;
3565 }
3566 return(NULL);
3567}
3568
3569/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003570 * xmlTextReaderIsDefault:
3571 * @reader: the xmlTextReaderPtr used
3572 *
3573 * Whether an Attribute node was generated from the default value
3574 * defined in the DTD or schema.
3575 *
3576 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3577 */
3578int
3579xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3580 if (reader == NULL)
3581 return(-1);
3582 return(0);
3583}
3584
3585/**
3586 * xmlTextReaderQuoteChar:
3587 * @reader: the xmlTextReaderPtr used
3588 *
3589 * The quotation mark character used to enclose the value of an attribute.
3590 *
3591 * Returns " or ' and -1 in case of error
3592 */
3593int
3594xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3595 if (reader == NULL)
3596 return(-1);
3597 /* TODO maybe lookup the attribute value for " first */
3598 return((int) '"');
3599}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003600
3601/**
3602 * xmlTextReaderXmlLang:
3603 * @reader: the xmlTextReaderPtr used
3604 *
3605 * The xml:lang scope within which the node resides.
3606 *
3607 * Returns the xml:lang value or NULL if none exists.
3608 */
3609xmlChar *
3610xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3611 if (reader == NULL)
3612 return(NULL);
3613 if (reader->node == NULL)
3614 return(NULL);
3615 return(xmlNodeGetLang(reader->node));
3616}
3617
Daniel Veillard67df8092002-12-16 22:04:11 +00003618/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003619 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003620 * @reader: the xmlTextReaderPtr used
3621 *
3622 * The xml:lang scope within which the node resides.
3623 *
3624 * Returns the xml:lang value or NULL if none exists.
3625 */
3626const xmlChar *
3627xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3628 xmlChar *tmp;
3629 const xmlChar *ret;
3630
3631 if (reader == NULL)
3632 return(NULL);
3633 if (reader->node == NULL)
3634 return(NULL);
3635 tmp = xmlNodeGetLang(reader->node);
3636 if (tmp == NULL)
3637 return(NULL);
3638 ret = CONSTSTR(tmp);
3639 xmlFree(tmp);
3640 return(ret);
3641}
3642
3643/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003644 * xmlTextReaderConstString:
3645 * @reader: the xmlTextReaderPtr used
3646 * @str: the string to intern.
3647 *
3648 * Get an interned string from the reader, allows for example to
3649 * speedup string name comparisons
3650 *
3651 * Returns an interned copy of the string or NULL in case of error. The
3652 * string will be deallocated with the reader.
3653 */
3654const xmlChar *
3655xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3656 if (reader == NULL)
3657 return(NULL);
3658 return(CONSTSTR(str));
3659}
3660
3661/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003662 * xmlTextReaderNormalization:
3663 * @reader: the xmlTextReaderPtr used
3664 *
3665 * The value indicating whether to normalize white space and attribute values.
3666 * Since attribute value and end of line normalizations are a MUST in the XML
3667 * specification only the value true is accepted. The broken bahaviour of
3668 * accepting out of range character entities like &#0; is of course not
3669 * supported either.
3670 *
3671 * Returns 1 or -1 in case of error.
3672 */
3673int
3674xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3675 if (reader == NULL)
3676 return(-1);
3677 return(1);
3678}
3679
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003680/************************************************************************
3681 * *
3682 * Extensions to the base APIs *
3683 * *
3684 ************************************************************************/
3685
3686/**
3687 * xmlTextReaderSetParserProp:
3688 * @reader: the xmlTextReaderPtr used
3689 * @prop: the xmlParserProperties to set
3690 * @value: usually 0 or 1 to (de)activate it
3691 *
3692 * Change the parser processing behaviour by changing some of its internal
3693 * properties. Note that some properties can only be changed before any
3694 * read has been done.
3695 *
3696 * Returns 0 if the call was successful, or -1 in case of error
3697 */
3698int
3699xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3700 xmlParserProperties p = (xmlParserProperties) prop;
3701 xmlParserCtxtPtr ctxt;
3702
3703 if ((reader == NULL) || (reader->ctxt == NULL))
3704 return(-1);
3705 ctxt = reader->ctxt;
3706
3707 switch (p) {
3708 case XML_PARSER_LOADDTD:
3709 if (value != 0) {
3710 if (ctxt->loadsubset == 0) {
3711 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3712 return(-1);
3713 ctxt->loadsubset = XML_DETECT_IDS;
3714 }
3715 } else {
3716 ctxt->loadsubset = 0;
3717 }
3718 return(0);
3719 case XML_PARSER_DEFAULTATTRS:
3720 if (value != 0) {
3721 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3722 } else {
3723 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3724 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3725 }
3726 return(0);
3727 case XML_PARSER_VALIDATE:
3728 if (value != 0) {
3729 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003730 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003731 } else {
3732 ctxt->validate = 0;
3733 }
3734 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003735 case XML_PARSER_SUBST_ENTITIES:
3736 if (value != 0) {
3737 ctxt->replaceEntities = 1;
3738 } else {
3739 ctxt->replaceEntities = 0;
3740 }
3741 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003742 }
3743 return(-1);
3744}
3745
3746/**
3747 * xmlTextReaderGetParserProp:
3748 * @reader: the xmlTextReaderPtr used
3749 * @prop: the xmlParserProperties to get
3750 *
3751 * Read the parser internal property.
3752 *
3753 * Returns the value, usually 0 or 1, or -1 in case of error.
3754 */
3755int
3756xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3757 xmlParserProperties p = (xmlParserProperties) prop;
3758 xmlParserCtxtPtr ctxt;
3759
3760 if ((reader == NULL) || (reader->ctxt == NULL))
3761 return(-1);
3762 ctxt = reader->ctxt;
3763
3764 switch (p) {
3765 case XML_PARSER_LOADDTD:
3766 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3767 return(1);
3768 return(0);
3769 case XML_PARSER_DEFAULTATTRS:
3770 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3771 return(1);
3772 return(0);
3773 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003774 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003775 case XML_PARSER_SUBST_ENTITIES:
3776 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003777 }
3778 return(-1);
3779}
3780
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003781
Daniel Veillarde18fc182002-12-28 22:56:33 +00003782/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003783 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003784 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003785 *
3786 * Provide the line number of the current parsing point.
3787 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003788 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003789 */
3790int
3791xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3792{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003793 if ((reader == NULL) || (reader->ctxt == NULL) ||
3794 (reader->ctxt->input == NULL)) {
3795 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003796 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003797 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003798}
3799
3800/**
3801 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003802 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003803 *
3804 * Provide the column number of the current parsing point.
3805 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003806 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003807 */
3808int
3809xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3810{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003811 if ((reader == NULL) || (reader->ctxt == NULL) ||
3812 (reader->ctxt->input == NULL)) {
3813 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003814 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003815 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003816}
3817
3818/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003819 * xmlTextReaderCurrentNode:
3820 * @reader: the xmlTextReaderPtr used
3821 *
3822 * Hacking interface allowing to get the xmlNodePtr correponding to the
3823 * current node being accessed by the xmlTextReader. This is dangerous
3824 * because the underlying node may be destroyed on the next Reads.
3825 *
3826 * Returns the xmlNodePtr or NULL in case of error.
3827 */
3828xmlNodePtr
3829xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3830 if (reader == NULL)
3831 return(NULL);
3832
3833 if (reader->curnode != NULL)
3834 return(reader->curnode);
3835 return(reader->node);
3836}
3837
3838/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003839 * xmlTextReaderPreserve:
3840 * @reader: the xmlTextReaderPtr used
3841 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003842 * This tells the XML Reader to preserve the current node.
3843 * The caller must also use xmlTextReaderCurrentDoc() to
3844 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003845 *
3846 * Returns the xmlNodePtr or NULL in case of error.
3847 */
3848xmlNodePtr
3849xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3850 xmlNodePtr cur, parent;
3851
3852 if (reader == NULL)
3853 return(NULL);
3854
3855 if (reader->curnode != NULL)
3856 cur = reader->curnode;
3857 else
3858 cur = reader->node;
3859 if (cur == NULL)
3860 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003861
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003862 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003863 cur->extra |= NODE_IS_PRESERVED;
3864 cur->extra |= NODE_IS_SPRESERVED;
3865 }
3866 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003867
3868 parent = cur->parent;;
3869 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003870 if (parent->type == XML_ELEMENT_NODE)
3871 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003872 parent = parent->parent;
3873 }
3874 return(cur);
3875}
3876
Daniel Veillard1e906612003-12-05 14:57:46 +00003877#ifdef LIBXML_PATTERN_ENABLED
3878/**
3879 * xmlTextReaderPreservePattern:
3880 * @reader: the xmlTextReaderPtr used
3881 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003882 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003883 *
3884 * This tells the XML Reader to preserve all nodes matched by the
3885 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3886 * keep an handle on the resulting document once parsing has finished
3887 *
3888 * Returns a positive number in case of success and -1 in case of error
3889 */
3890int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003891xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3892 const xmlChar **namespaces)
3893{
Daniel Veillard1e906612003-12-05 14:57:46 +00003894 xmlPatternPtr comp;
3895
3896 if ((reader == NULL) || (pattern == NULL))
3897 return(-1);
3898
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003899 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003900 if (comp == NULL)
3901 return(-1);
3902
3903 if (reader->patternMax <= 0) {
3904 reader->patternMax = 4;
3905 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3906 sizeof(reader->patternTab[0]));
3907 if (reader->patternTab == NULL) {
3908 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3909 return (-1);
3910 }
3911 }
3912 if (reader->patternNr >= reader->patternMax) {
3913 xmlPatternPtr *tmp;
3914 reader->patternMax *= 2;
3915 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3916 reader->patternMax *
3917 sizeof(reader->patternTab[0]));
3918 if (tmp == NULL) {
3919 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3920 reader->patternMax /= 2;
3921 return (-1);
3922 }
3923 reader->patternTab = tmp;
3924 }
3925 reader->patternTab[reader->patternNr] = comp;
3926 return(reader->patternNr++);
3927}
3928#endif
3929
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003930/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003931 * xmlTextReaderCurrentDoc:
3932 * @reader: the xmlTextReaderPtr used
3933 *
3934 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003935 * current document being accessed by the xmlTextReader.
3936 * NOTE: as a result of this call, the reader will not destroy the
3937 * associated XML document and calling xmlFreeDoc() on the result
3938 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003939 *
3940 * Returns the xmlDocPtr or NULL in case of error.
3941 */
3942xmlDocPtr
3943xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003944 if (reader == NULL)
3945 return(NULL);
3946 if (reader->doc != NULL)
3947 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003948 if ((reader == NULL) || (reader->ctxt == NULL) ||
3949 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003950 return(NULL);
3951
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003952 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003953 return(reader->ctxt->myDoc);
3954}
3955
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003956#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003957
3958static char *
3959xmlTextReaderBuildMessage(const char *msg, va_list ap);
3960
Daniel Veillardffa3c742005-07-21 13:24:09 +00003961static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003962xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3963
Daniel Veillardffa3c742005-07-21 13:24:09 +00003964static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003965xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3966
Daniel Veillardffa3c742005-07-21 13:24:09 +00003967static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003968{
3969 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3970 char * str;
3971 va_list ap;
3972
3973 va_start(ap,msg);
3974 str = xmlTextReaderBuildMessage(msg,ap);
3975 if (!reader->errorFunc) {
3976 xmlTextReaderValidityError(ctx, "%s", str);
3977 } else {
3978 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3979 }
3980 if (str != NULL)
3981 xmlFree(str);
3982 va_end(ap);
3983}
3984
Daniel Veillardffa3c742005-07-21 13:24:09 +00003985static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003986{
3987 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3988 char * str;
3989 va_list ap;
3990
3991 va_start(ap,msg);
3992 str = xmlTextReaderBuildMessage(msg,ap);
3993 if (!reader->errorFunc) {
3994 xmlTextReaderValidityWarning(ctx, "%s", str);
3995 } else {
3996 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3997 }
3998 if (str != NULL)
3999 xmlFree(str);
4000 va_end(ap);
4001}
4002
4003static void
4004xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4005
4006static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4007{
4008 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4009
4010 if (reader->sErrorFunc) {
4011 reader->sErrorFunc(reader->errorFuncArg, error);
4012 } else {
4013 xmlTextReaderStructuredError(reader, error);
4014 }
4015}
4016
Daniel Veillardf4e55762003-04-15 23:32:22 +00004017/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004018 * xmlTextReaderRelaxNGSetSchema:
4019 * @reader: the xmlTextReaderPtr used
4020 * @schema: a precompiled RelaxNG schema
4021 *
4022 * Use RelaxNG to validate the document as it is processed.
4023 * Activation is only possible before the first Read().
4024 * if @schema is NULL, then RelaxNG validation is desactivated.
4025 @ The @schema should not be freed until the reader is deallocated
4026 * or its use has been deactivated.
4027 *
4028 * Returns 0 in case the RelaxNG validation could be (des)activated and
4029 * -1 in case of error.
4030 */
4031int
4032xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004033 if (reader == NULL)
4034 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004035 if (schema == NULL) {
4036 if (reader->rngSchemas != NULL) {
4037 xmlRelaxNGFree(reader->rngSchemas);
4038 reader->rngSchemas = NULL;
4039 }
4040 if (reader->rngValidCtxt != NULL) {
4041 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4042 reader->rngValidCtxt = NULL;
4043 }
4044 return(0);
4045 }
4046 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4047 return(-1);
4048 if (reader->rngSchemas != NULL) {
4049 xmlRelaxNGFree(reader->rngSchemas);
4050 reader->rngSchemas = NULL;
4051 }
4052 if (reader->rngValidCtxt != NULL) {
4053 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4054 reader->rngValidCtxt = NULL;
4055 }
4056 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4057 if (reader->rngValidCtxt == NULL)
4058 return(-1);
4059 if (reader->errorFunc != NULL) {
4060 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004061 xmlTextReaderValidityErrorRelay,
4062 xmlTextReaderValidityWarningRelay,
4063 reader);
4064 }
4065 if (reader->sErrorFunc != NULL) {
4066 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4067 xmlTextReaderValidityStructuredRelay,
4068 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004069 }
4070 reader->rngValidErrors = 0;
4071 reader->rngFullNode = NULL;
4072 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4073 return(0);
4074}
4075
4076/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004077 * xmlTextReaderSetSchema:
4078 * @reader: the xmlTextReaderPtr used
4079 * @schema: a precompiled Schema schema
4080 *
4081 * Use XSD Schema to validate the document as it is processed.
4082 * Activation is only possible before the first Read().
4083 * if @schema is NULL, then Schema validation is desactivated.
4084 @ The @schema should not be freed until the reader is deallocated
4085 * or its use has been deactivated.
4086 *
4087 * Returns 0 in case the Schema validation could be (des)activated and
4088 * -1 in case of error.
4089 */
4090int
4091xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4092 if (reader == NULL)
4093 return(-1);
4094 if (schema == NULL) {
4095 if (reader->xsdPlug != NULL) {
4096 xmlSchemaSAXUnplug(reader->xsdPlug);
4097 reader->xsdPlug = NULL;
4098 }
4099 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004100 if (! reader->xsdPreserveCtxt)
4101 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4102 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004103 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004104 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004105 if (reader->xsdSchemas != NULL) {
4106 xmlSchemaFree(reader->xsdSchemas);
4107 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004108 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004109 return(0);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004110 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004111 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4112 return(-1);
4113 if (reader->xsdPlug != NULL) {
4114 xmlSchemaSAXUnplug(reader->xsdPlug);
4115 reader->xsdPlug = NULL;
4116 }
4117 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004118 if (! reader->xsdPreserveCtxt)
4119 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004120 reader->xsdValidCtxt = NULL;
4121 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004122 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004123 if (reader->xsdSchemas != NULL) {
4124 xmlSchemaFree(reader->xsdSchemas);
4125 reader->xsdSchemas = NULL;
4126 }
4127 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4128 if (reader->xsdValidCtxt == NULL) {
4129 xmlSchemaFree(reader->xsdSchemas);
4130 reader->xsdSchemas = NULL;
4131 return(-1);
4132 }
4133 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4134 &(reader->ctxt->sax),
4135 &(reader->ctxt->userData));
4136 if (reader->xsdPlug == NULL) {
4137 xmlSchemaFree(reader->xsdSchemas);
4138 reader->xsdSchemas = NULL;
4139 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4140 reader->xsdValidCtxt = NULL;
4141 return(-1);
4142 }
4143 if (reader->errorFunc != NULL) {
4144 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004145 xmlTextReaderValidityErrorRelay,
4146 xmlTextReaderValidityWarningRelay,
4147 reader);
4148 }
4149 if (reader->sErrorFunc != NULL) {
4150 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4151 xmlTextReaderValidityStructuredRelay,
4152 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004153 }
4154 reader->xsdValidErrors = 0;
4155 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4156 return(0);
4157}
4158
4159/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004160 * xmlTextReaderRelaxNGValidate:
4161 * @reader: the xmlTextReaderPtr used
4162 * @rng: the path to a RelaxNG schema or NULL
4163 *
4164 * Use RelaxNG to validate the document as it is processed.
4165 * Activation is only possible before the first Read().
4166 * if @rng is NULL, then RelaxNG validation is desactivated.
4167 *
4168 * Returns 0 in case the RelaxNG validation could be (des)activated and
4169 * -1 in case of error.
4170 */
4171int
4172xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4173 xmlRelaxNGParserCtxtPtr ctxt;
4174
4175 if (reader == NULL)
4176 return(-1);
4177
4178 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004179 if (reader->rngValidCtxt != NULL) {
4180 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4181 reader->rngValidCtxt = NULL;
4182 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004183 if (reader->rngSchemas != NULL) {
4184 xmlRelaxNGFree(reader->rngSchemas);
4185 reader->rngSchemas = NULL;
4186 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004187 return(0);
4188 }
4189 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4190 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004191 if (reader->rngSchemas != NULL) {
4192 xmlRelaxNGFree(reader->rngSchemas);
4193 reader->rngSchemas = NULL;
4194 }
4195 if (reader->rngValidCtxt != NULL) {
4196 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4197 reader->rngValidCtxt = NULL;
4198 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004199 ctxt = xmlRelaxNGNewParserCtxt(rng);
4200 if (reader->errorFunc != NULL) {
4201 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004202 xmlTextReaderValidityErrorRelay,
4203 xmlTextReaderValidityWarningRelay,
4204 reader);
4205 }
4206 if (reader->sErrorFunc != NULL) {
4207 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4208 xmlTextReaderValidityStructuredRelay,
4209 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004210 }
4211 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4212 xmlRelaxNGFreeParserCtxt(ctxt);
4213 if (reader->rngSchemas == NULL)
4214 return(-1);
4215 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004216 if (reader->rngValidCtxt == NULL) {
4217 xmlRelaxNGFree(reader->rngSchemas);
4218 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004219 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004220 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004221 if (reader->errorFunc != NULL) {
4222 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004223 xmlTextReaderValidityErrorRelay,
4224 xmlTextReaderValidityWarningRelay,
4225 reader);
4226 }
4227 if (reader->sErrorFunc != NULL) {
4228 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4229 xmlTextReaderValidityStructuredRelay,
4230 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004231 }
4232 reader->rngValidErrors = 0;
4233 reader->rngFullNode = NULL;
4234 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4235 return(0);
4236}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004237
4238/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004239 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004240 * @reader: the xmlTextReaderPtr used
4241 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004242 * @ctxt: the XML Schema validation context or NULL
4243 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004244 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004245 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004246 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004247 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004248 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004249 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004250 * -1 in case of error.
4251 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004252static int
4253xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4254 const char *xsd,
4255 xmlSchemaValidCtxtPtr ctxt,
4256 int options ATTRIBUTE_UNUSED)
4257{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004258 if (reader == NULL)
4259 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004260
4261 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004262 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004263
4264 if (((xsd != NULL) || (ctxt != NULL)) &&
4265 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4266 (reader->ctxt == NULL)))
4267 return(-1);
4268
4269 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004270 if (reader->xsdPlug != NULL) {
4271 xmlSchemaSAXUnplug(reader->xsdPlug);
4272 reader->xsdPlug = NULL;
4273 }
4274 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004275 if (! reader->xsdPreserveCtxt)
4276 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004277 reader->xsdValidCtxt = NULL;
4278 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004279 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004280 if (reader->xsdSchemas != NULL) {
4281 xmlSchemaFree(reader->xsdSchemas);
4282 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004283 }
4284
4285 if ((xsd == NULL) && (ctxt == NULL)) {
4286 /* We just want to deactivate the validation, so get out. */
4287 return(0);
4288 }
4289
4290 if (xsd != NULL) {
4291 xmlSchemaParserCtxtPtr pctxt;
4292 /* Parse the schema and create validation environment. */
4293 pctxt = xmlSchemaNewParserCtxt(xsd);
4294 if (reader->errorFunc != NULL) {
4295 xmlSchemaSetParserErrors(pctxt,
4296 xmlTextReaderValidityErrorRelay,
4297 xmlTextReaderValidityWarningRelay,
4298 reader);
4299 }
4300 reader->xsdSchemas = xmlSchemaParse(pctxt);
4301 xmlSchemaFreeParserCtxt(pctxt);
4302 if (reader->xsdSchemas == NULL)
4303 return(-1);
4304 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4305 if (reader->xsdValidCtxt == NULL) {
4306 xmlSchemaFree(reader->xsdSchemas);
4307 reader->xsdSchemas = NULL;
4308 return(-1);
4309 }
4310 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4311 &(reader->ctxt->sax),
4312 &(reader->ctxt->userData));
4313 if (reader->xsdPlug == NULL) {
4314 xmlSchemaFree(reader->xsdSchemas);
4315 reader->xsdSchemas = NULL;
4316 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4317 reader->xsdValidCtxt = NULL;
4318 return(-1);
4319 }
4320 } else {
4321 /* Use the given validation context. */
4322 reader->xsdValidCtxt = ctxt;
4323 reader->xsdPreserveCtxt = 1;
4324 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4325 &(reader->ctxt->sax),
4326 &(reader->ctxt->userData));
4327 if (reader->xsdPlug == NULL) {
4328 reader->xsdValidCtxt = NULL;
4329 reader->xsdPreserveCtxt = 0;
4330 return(-1);
4331 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004332 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004333 /*
4334 * Redirect the validation context's error channels to use
4335 * the reader channels.
4336 * TODO: In case the user provides the validation context we
4337 * could make this redirection optional.
4338 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004339 if (reader->errorFunc != NULL) {
4340 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004341 xmlTextReaderValidityErrorRelay,
4342 xmlTextReaderValidityWarningRelay,
4343 reader);
4344 }
4345 if (reader->sErrorFunc != NULL) {
4346 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4347 xmlTextReaderValidityStructuredRelay,
4348 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004349 }
4350 reader->xsdValidErrors = 0;
4351 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4352 return(0);
4353}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004354
4355/**
4356 * xmlTextReaderSchemaValidateCtxt:
4357 * @reader: the xmlTextReaderPtr used
4358 * @ctxt: the XML Schema validation context or NULL
4359 * @options: options (not used yet)
4360 *
4361 * Use W3C XSD schema context to validate the document as it is processed.
4362 * Activation is only possible before the first Read().
4363 * If @ctxt is NULL, then XML Schema validation is deactivated.
4364 *
4365 * Returns 0 in case the schemas validation could be (de)activated and
4366 * -1 in case of error.
4367 */
4368int
4369xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4370 xmlSchemaValidCtxtPtr ctxt,
4371 int options)
4372{
4373 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4374}
4375
4376/**
4377 * xmlTextReaderSchemaValidate:
4378 * @reader: the xmlTextReaderPtr used
4379 * @xsd: the path to a W3C XSD schema or NULL
4380 *
4381 * Use W3C XSD schema to validate the document as it is processed.
4382 * Activation is only possible before the first Read().
4383 * If @xsd is NULL, then XML Schema validation is deactivated.
4384 *
4385 * Returns 0 in case the schemas validation could be (de)activated and
4386 * -1 in case of error.
4387 */
4388int
4389xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4390{
4391 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4392}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004393#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004394
Daniel Veillarde2811272004-10-19 09:04:23 +00004395/**
4396 * xmlTextReaderIsNamespaceDecl:
4397 * @reader: the xmlTextReaderPtr used
4398 *
4399 * Determine whether the current node is a namespace declaration
4400 * rather than a regular attribute.
4401 *
4402 * Returns 1 if the current node is a namespace declaration, 0 if it
4403 * is a regular attribute or other type of node, or -1 in case of
4404 * error.
4405 */
4406int
4407xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4408 xmlNodePtr node;
4409 if (reader == NULL)
4410 return(-1);
4411 if (reader->node == NULL)
4412 return(-1);
4413 if (reader->curnode != NULL)
4414 node = reader->curnode;
4415 else
4416 node = reader->node;
4417
4418 if (XML_NAMESPACE_DECL == node->type)
4419 return(1);
4420 else
4421 return(0);
4422}
4423
4424/**
4425 * xmlTextReaderConstXmlVersion:
4426 * @reader: the xmlTextReaderPtr used
4427 *
4428 * Determine the XML version of the document being read.
4429 *
4430 * Returns a string containing the XML version of the document or NULL
4431 * in case of error. The string is deallocated with the reader.
4432 */
4433const xmlChar *
4434xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4435 xmlDocPtr doc = NULL;
4436 if (reader == NULL)
4437 return(NULL);
4438 if (reader->doc != NULL)
4439 doc = reader->doc;
4440 else if (reader->ctxt != NULL)
4441 doc = reader->ctxt->myDoc;
4442 if (doc == NULL)
4443 return(NULL);
4444
4445 if (doc->version == NULL)
4446 return(NULL);
4447 else
4448 return(CONSTSTR(doc->version));
4449}
4450
4451/**
4452 * xmlTextReaderStandalone:
4453 * @reader: the xmlTextReaderPtr used
4454 *
4455 * Determine the standalone status of the document being read.
4456 *
4457 * Returns 1 if the document was declared to be standalone, 0 if it
4458 * was declared to be not standalone, or -1 if the document did not
4459 * specify its standalone status or in case of error.
4460 */
4461int
4462xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4463 xmlDocPtr doc = NULL;
4464 if (reader == NULL)
4465 return(-1);
4466 if (reader->doc != NULL)
4467 doc = reader->doc;
4468 else if (reader->ctxt != NULL)
4469 doc = reader->ctxt->myDoc;
4470 if (doc == NULL)
4471 return(-1);
4472
4473 return(doc->standalone);
4474}
4475
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004476/************************************************************************
4477 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004478 * Error Handling Extensions *
4479 * *
4480 ************************************************************************/
4481
4482/* helper to build a xmlMalloc'ed string from a format and va_list */
4483static char *
4484xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4485 int size;
4486 int chars;
4487 char *larger;
4488 char *str;
4489
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004490 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004491 if (str == NULL) {
4492 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4493 return NULL;
4494 }
4495
4496 size = 150;
4497
4498 while (1) {
4499 chars = vsnprintf(str, size, msg, ap);
4500 if ((chars > -1) && (chars < size))
4501 break;
4502 if (chars > -1)
4503 size += chars + 1;
4504 else
4505 size += 100;
4506 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4507 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4508 xmlFree(str);
4509 return NULL;
4510 }
4511 str = larger;
4512 }
4513
4514 return str;
4515}
4516
Daniel Veillard417be3a2003-01-20 21:26:34 +00004517/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004518 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004519 * @locator: the xmlTextReaderLocatorPtr used
4520 *
4521 * Obtain the line number for the given locator.
4522 *
4523 * Returns the line number or -1 in case of error.
4524 */
4525int
4526xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4527 /* we know that locator is a xmlParserCtxtPtr */
4528 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4529 int ret = -1;
4530
Daniel Veillardce682bc2004-11-05 17:22:25 +00004531 if (locator == NULL)
4532 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004533 if (ctx->node != NULL) {
4534 ret = xmlGetLineNo(ctx->node);
4535 }
4536 else {
4537 /* inspired from error.c */
4538 xmlParserInputPtr input;
4539 input = ctx->input;
4540 if ((input->filename == NULL) && (ctx->inputNr > 1))
4541 input = ctx->inputTab[ctx->inputNr - 2];
4542 if (input != NULL) {
4543 ret = input->line;
4544 }
4545 else {
4546 ret = -1;
4547 }
4548 }
4549
4550 return ret;
4551}
4552
4553/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004554 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004555 * @locator: the xmlTextReaderLocatorPtr used
4556 *
4557 * Obtain the base URI for the given locator.
4558 *
4559 * Returns the base URI or NULL in case of error.
4560 */
4561xmlChar *
4562xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4563 /* we know that locator is a xmlParserCtxtPtr */
4564 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4565 xmlChar *ret = NULL;
4566
Daniel Veillardce682bc2004-11-05 17:22:25 +00004567 if (locator == NULL)
4568 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004569 if (ctx->node != NULL) {
4570 ret = xmlNodeGetBase(NULL,ctx->node);
4571 }
4572 else {
4573 /* inspired from error.c */
4574 xmlParserInputPtr input;
4575 input = ctx->input;
4576 if ((input->filename == NULL) && (ctx->inputNr > 1))
4577 input = ctx->inputTab[ctx->inputNr - 2];
4578 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004579 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004580 }
4581 else {
4582 ret = NULL;
4583 }
4584 }
4585
4586 return ret;
4587}
4588
Daniel Veillard26f70262003-01-16 22:45:08 +00004589static void
William M. Brack899e64a2003-09-26 18:03:42 +00004590xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004591 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4592 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4593
William M. Bracka3215c72004-07-31 16:24:01 +00004594 if (str != NULL) {
4595 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004596 reader->errorFunc(reader->errorFuncArg,
4597 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004598 severity,
4599 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004600 xmlFree(str);
4601 }
4602}
4603
4604static void
William M. Brack93d004f2004-02-03 00:14:10 +00004605xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4606 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4607 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4608
4609 if (error && reader->sErrorFunc) {
4610 reader->sErrorFunc(reader->errorFuncArg,
4611 (xmlErrorPtr) error);
4612 }
4613}
4614
Daniel Veillardffa3c742005-07-21 13:24:09 +00004615static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004616xmlTextReaderError(void *ctxt, const char *msg, ...) {
4617 va_list ap;
4618
4619 va_start(ap,msg);
4620 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004621 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004622 xmlTextReaderBuildMessage(msg,ap));
4623 va_end(ap);
4624
4625}
4626
Daniel Veillardffa3c742005-07-21 13:24:09 +00004627static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004628xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4629 va_list ap;
4630
4631 va_start(ap,msg);
4632 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004633 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004634 xmlTextReaderBuildMessage(msg,ap));
4635 va_end(ap);
4636}
4637
Daniel Veillardffa3c742005-07-21 13:24:09 +00004638static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004639xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4640 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004641 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004642
Daniel Veillard417be3a2003-01-20 21:26:34 +00004643 if ((len > 1) && (msg[len - 2] != ':')) {
4644 /*
4645 * some callbacks only report locator information:
4646 * skip them (mimicking behaviour in error.c)
4647 */
4648 va_start(ap,msg);
4649 xmlTextReaderGenericError(ctxt,
4650 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4651 xmlTextReaderBuildMessage(msg,ap));
4652 va_end(ap);
4653 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004654}
4655
Daniel Veillardffa3c742005-07-21 13:24:09 +00004656static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004657xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4658 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004659 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004660
Daniel Veillard417be3a2003-01-20 21:26:34 +00004661 if ((len != 0) && (msg[len - 1] != ':')) {
4662 /*
4663 * some callbacks only report locator information:
4664 * skip them (mimicking behaviour in error.c)
4665 */
4666 va_start(ap,msg);
4667 xmlTextReaderGenericError(ctxt,
4668 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4669 xmlTextReaderBuildMessage(msg,ap));
4670 va_end(ap);
4671 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004672}
4673
4674/**
4675 * xmlTextReaderSetErrorHandler:
4676 * @reader: the xmlTextReaderPtr used
4677 * @f: the callback function to call on error and warnings
4678 * @arg: a user argument to pass to the callback function
4679 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004680 * Register a callback function that will be called on error and warnings.
4681 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004682 * If @f is NULL, the default error and warning handlers are restored.
4683 */
4684void
4685xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4686 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004687 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004688 if (f != NULL) {
4689 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004690 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004691 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4692 reader->ctxt->sax->warning = xmlTextReaderWarning;
4693 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4694 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004695 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004696 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004697#ifdef LIBXML_SCHEMAS_ENABLED
4698 if (reader->rngValidCtxt) {
4699 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4700 xmlTextReaderValidityErrorRelay,
4701 xmlTextReaderValidityWarningRelay,
4702 reader);
4703 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4704 }
4705 if (reader->xsdValidCtxt) {
4706 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4707 xmlTextReaderValidityErrorRelay,
4708 xmlTextReaderValidityWarningRelay,
4709 reader);
4710 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4711 }
4712#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004713 }
4714 else {
4715 /* restore defaults */
4716 reader->ctxt->sax->error = xmlParserError;
4717 reader->ctxt->vctxt.error = xmlParserValidityError;
4718 reader->ctxt->sax->warning = xmlParserWarning;
4719 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4720 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004721 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004722 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004723#ifdef LIBXML_SCHEMAS_ENABLED
4724 if (reader->rngValidCtxt) {
4725 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4726 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4727 }
4728 if (reader->xsdValidCtxt) {
4729 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4730 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4731 }
4732#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004733 }
4734}
4735
Daniel Veillard417be3a2003-01-20 21:26:34 +00004736/**
William M. Brack93d004f2004-02-03 00:14:10 +00004737* xmlTextReaderSetStructuredErrorHandler:
4738 * @reader: the xmlTextReaderPtr used
4739 * @f: the callback function to call on error and warnings
4740 * @arg: a user argument to pass to the callback function
4741 *
4742 * Register a callback function that will be called on error and warnings.
4743 *
4744 * If @f is NULL, the default error and warning handlers are restored.
4745 */
4746void
4747xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4748 xmlStructuredErrorFunc f,
4749 void *arg) {
4750 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004751 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004752 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4753 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4754 reader->ctxt->sax->warning = xmlTextReaderWarning;
4755 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4756 reader->sErrorFunc = f;
4757 reader->errorFunc = NULL;
4758 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004759#ifdef LIBXML_SCHEMAS_ENABLED
4760 if (reader->rngValidCtxt) {
4761 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4762 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4763 xmlTextReaderValidityStructuredRelay,
4764 reader);
4765 }
4766 if (reader->xsdValidCtxt) {
4767 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4768 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4769 xmlTextReaderValidityStructuredRelay,
4770 reader);
4771 }
4772#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004773 }
4774 else {
4775 /* restore defaults */
4776 reader->ctxt->sax->error = xmlParserError;
4777 reader->ctxt->sax->serror = NULL;
4778 reader->ctxt->vctxt.error = xmlParserValidityError;
4779 reader->ctxt->sax->warning = xmlParserWarning;
4780 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4781 reader->errorFunc = NULL;
4782 reader->sErrorFunc = NULL;
4783 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004784#ifdef LIBXML_SCHEMAS_ENABLED
4785 if (reader->rngValidCtxt) {
4786 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4787 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4788 }
4789 if (reader->xsdValidCtxt) {
4790 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4791 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4792 }
4793#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004794 }
4795}
4796
4797/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004798 * xmlTextReaderIsValid:
4799 * @reader: the xmlTextReaderPtr used
4800 *
4801 * Retrieve the validity status from the parser context
4802 *
4803 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4804 */
4805int
4806xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004807 if (reader == NULL) return(-1);
4808#ifdef LIBXML_SCHEMAS_ENABLED
4809 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4810 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004811 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4812 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004813#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004814 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004815 return(reader->ctxt->valid);
4816 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004817}
4818
4819/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004820 * xmlTextReaderGetErrorHandler:
4821 * @reader: the xmlTextReaderPtr used
4822 * @f: the callback function or NULL is no callback has been registered
4823 * @arg: a user argument
4824 *
4825 * Retrieve the error callback function and user argument.
4826 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004827void
4828xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4829 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004830 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004831 if (f != NULL) *f = reader->errorFunc;
4832 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004833}
4834
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004835
4836/************************************************************************
4837 * *
4838 * New set (2.6.0) of simpler and more flexible APIs *
4839 * *
4840 ************************************************************************/
4841
4842/**
4843 * xmlTextReaderSetup:
4844 * @reader: an XML reader
4845 * @URL: the base URL to use for the document
4846 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004847 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004848 * @reuse: keep the context for reuse
4849 *
4850 * Setup an XML reader with new options
4851 *
4852 * Returns 0 in case of success and -1 in case of error.
4853 */
4854static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004855xmlTextReaderSetup(xmlTextReaderPtr reader,
4856 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004857 const char *encoding, int options)
4858{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004859 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004860 return (-1);
4861
Daniel Veillard8874b942005-08-25 13:19:21 +00004862 /*
4863 * we force the generation of compact text nodes on the reader
4864 * since usr applications should never modify the tree
4865 */
4866 options |= XML_PARSE_COMPACT;
4867
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004868 reader->doc = NULL;
4869 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004870 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004871 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004872 if ((input != NULL) && (reader->input != NULL) &&
4873 (reader->allocs & XML_TEXTREADER_INPUT)) {
4874 xmlFreeParserInputBuffer(reader->input);
4875 reader->input = NULL;
4876 reader->allocs -= XML_TEXTREADER_INPUT;
4877 }
4878 if (input != NULL) {
4879 reader->input = input;
4880 reader->allocs |= XML_TEXTREADER_INPUT;
4881 }
4882 if (reader->buffer == NULL)
4883 reader->buffer = xmlBufferCreateSize(100);
4884 if (reader->buffer == NULL) {
4885 xmlGenericError(xmlGenericErrorContext,
4886 "xmlTextReaderSetup : malloc failed\n");
4887 return (-1);
4888 }
4889 if (reader->sax == NULL)
4890 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4891 if (reader->sax == NULL) {
4892 xmlGenericError(xmlGenericErrorContext,
4893 "xmlTextReaderSetup : malloc failed\n");
4894 return (-1);
4895 }
4896 xmlSAXVersion(reader->sax, 2);
4897 reader->startElement = reader->sax->startElement;
4898 reader->sax->startElement = xmlTextReaderStartElement;
4899 reader->endElement = reader->sax->endElement;
4900 reader->sax->endElement = xmlTextReaderEndElement;
4901#ifdef LIBXML_SAX1_ENABLED
4902 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4903#endif /* LIBXML_SAX1_ENABLED */
4904 reader->startElementNs = reader->sax->startElementNs;
4905 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4906 reader->endElementNs = reader->sax->endElementNs;
4907 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4908#ifdef LIBXML_SAX1_ENABLED
4909 } else {
4910 reader->startElementNs = NULL;
4911 reader->endElementNs = NULL;
4912 }
4913#endif /* LIBXML_SAX1_ENABLED */
4914 reader->characters = reader->sax->characters;
4915 reader->sax->characters = xmlTextReaderCharacters;
4916 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4917 reader->cdataBlock = reader->sax->cdataBlock;
4918 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4919
4920 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4921 reader->node = NULL;
4922 reader->curnode = NULL;
4923 if (input != NULL) {
4924 if (reader->input->buffer->use < 4) {
4925 xmlParserInputBufferRead(input, 4);
4926 }
4927 if (reader->ctxt == NULL) {
4928 if (reader->input->buffer->use >= 4) {
4929 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4930 (const char *) reader->input->buffer->content, 4, URL);
4931 reader->base = 0;
4932 reader->cur = 4;
4933 } else {
4934 reader->ctxt =
4935 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4936 reader->base = 0;
4937 reader->cur = 0;
4938 }
4939 } else {
4940 xmlParserInputPtr inputStream;
4941 xmlParserInputBufferPtr buf;
4942 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4943
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004944 xmlCtxtReset(reader->ctxt);
4945 buf = xmlAllocParserInputBuffer(enc);
4946 if (buf == NULL) return(-1);
4947 inputStream = xmlNewInputStream(reader->ctxt);
4948 if (inputStream == NULL) {
4949 xmlFreeParserInputBuffer(buf);
4950 return(-1);
4951 }
4952
4953 if (URL == NULL)
4954 inputStream->filename = NULL;
4955 else
4956 inputStream->filename = (char *)
4957 xmlCanonicPath((const xmlChar *) URL);
4958 inputStream->buf = buf;
4959 inputStream->base = inputStream->buf->buffer->content;
4960 inputStream->cur = inputStream->buf->buffer->content;
4961 inputStream->end =
4962 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4963
4964 inputPush(reader->ctxt, inputStream);
4965 reader->cur = 0;
4966 }
4967 if (reader->ctxt == NULL) {
4968 xmlGenericError(xmlGenericErrorContext,
4969 "xmlTextReaderSetup : malloc failed\n");
4970 return (-1);
4971 }
4972 }
4973 if (reader->dict != NULL) {
4974 if (reader->ctxt->dict != NULL) {
4975 if (reader->dict != reader->ctxt->dict) {
4976 xmlDictFree(reader->dict);
4977 reader->dict = reader->ctxt->dict;
4978 }
4979 } else {
4980 reader->ctxt->dict = reader->dict;
4981 }
4982 } else {
4983 if (reader->ctxt->dict == NULL)
4984 reader->ctxt->dict = xmlDictCreate();
4985 reader->dict = reader->ctxt->dict;
4986 }
4987 reader->ctxt->_private = reader;
4988 reader->ctxt->linenumbers = 1;
4989 reader->ctxt->dictNames = 1;
4990 /*
4991 * use the parser dictionnary to allocate all elements and attributes names
4992 */
4993 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004994 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004995
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004996#ifdef LIBXML_XINCLUDE_ENABLED
4997 if (reader->xincctxt != NULL) {
4998 xmlXIncludeFreeContext(reader->xincctxt);
4999 reader->xincctxt = NULL;
5000 }
5001 if (options & XML_PARSE_XINCLUDE) {
5002 reader->xinclude = 1;
5003 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5004 options -= XML_PARSE_XINCLUDE;
5005 } else
5006 reader->xinclude = 0;
5007 reader->in_xinclude = 0;
5008#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005009#ifdef LIBXML_PATTERN_ENABLED
5010 if (reader->patternTab == NULL) {
5011 reader->patternNr = 0;
5012 reader->patternMax = 0;
5013 }
5014 while (reader->patternNr > 0) {
5015 reader->patternNr--;
5016 if (reader->patternTab[reader->patternNr] != NULL) {
5017 xmlFreePattern(reader->patternTab[reader->patternNr]);
5018 reader->patternTab[reader->patternNr] = NULL;
5019 }
5020 }
5021#endif
5022
Daniel Veillardc36965d2003-12-02 10:28:48 +00005023 if (options & XML_PARSE_DTDVALID)
5024 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5025
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005026 xmlCtxtUseOptions(reader->ctxt, options);
5027 if (encoding != NULL) {
5028 xmlCharEncodingHandlerPtr hdlr;
5029
5030 hdlr = xmlFindCharEncodingHandler(encoding);
5031 if (hdlr != NULL)
5032 xmlSwitchToEncoding(reader->ctxt, hdlr);
5033 }
5034 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5035 (reader->ctxt->input->filename == NULL))
5036 reader->ctxt->input->filename = (char *)
5037 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005038
5039 reader->doc = NULL;
5040
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005041 return (0);
5042}
5043
5044/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005045 * xmlTextReaderByteConsumed:
5046 * @reader: an XML reader
5047 *
5048 * This function provides the current index of the parser used
5049 * by the reader, relative to the start of the current entity.
5050 * This function actually just wraps a call to xmlBytesConsumed()
5051 * for the parser context associated with the reader.
5052 * See xmlBytesConsumed() for more information.
5053 *
5054 * Returns the index in bytes from the beginning of the entity or -1
5055 * in case the index could not be computed.
5056 */
5057long
5058xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5059 if ((reader == NULL) || (reader->ctxt == NULL))
5060 return(-1);
5061 return(xmlByteConsumed(reader->ctxt));
5062}
5063
5064
5065/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005066 * xmlReaderWalker:
5067 * @doc: a preparsed document
5068 *
5069 * Create an xmltextReader for a preparsed document.
5070 *
5071 * Returns the new reader or NULL in case of error.
5072 */
5073xmlTextReaderPtr
5074xmlReaderWalker(xmlDocPtr doc)
5075{
5076 xmlTextReaderPtr ret;
5077
5078 if (doc == NULL)
5079 return(NULL);
5080
5081 ret = xmlMalloc(sizeof(xmlTextReader));
5082 if (ret == NULL) {
5083 xmlGenericError(xmlGenericErrorContext,
5084 "xmlNewTextReader : malloc failed\n");
5085 return(NULL);
5086 }
5087 memset(ret, 0, sizeof(xmlTextReader));
5088 ret->entNr = 0;
5089 ret->input = NULL;
5090 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5091 ret->node = NULL;
5092 ret->curnode = NULL;
5093 ret->base = 0;
5094 ret->cur = 0;
5095 ret->allocs = XML_TEXTREADER_CTXT;
5096 ret->doc = doc;
5097 ret->state = XML_TEXTREADER_START;
5098 ret->dict = xmlDictCreate();
5099 return(ret);
5100}
5101
5102/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005103 * xmlReaderForDoc:
5104 * @cur: a pointer to a zero terminated string
5105 * @URL: the base URL to use for the document
5106 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005107 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005108 *
5109 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005110 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005111 *
5112 * Returns the new reader or NULL in case of error.
5113 */
5114xmlTextReaderPtr
5115xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5116 int options)
5117{
5118 int len;
5119
5120 if (cur == NULL)
5121 return (NULL);
5122 len = xmlStrlen(cur);
5123
5124 return (xmlReaderForMemory
5125 ((const char *) cur, len, URL, encoding, options));
5126}
5127
5128/**
5129 * xmlReaderForFile:
5130 * @filename: a file or URL
5131 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005132 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005133 *
5134 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005135 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005136 *
5137 * Returns the new reader or NULL in case of error.
5138 */
5139xmlTextReaderPtr
5140xmlReaderForFile(const char *filename, const char *encoding, int options)
5141{
5142 xmlTextReaderPtr reader;
5143
5144 reader = xmlNewTextReaderFilename(filename);
5145 if (reader == NULL)
5146 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005147 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005148 return (reader);
5149}
5150
5151/**
5152 * xmlReaderForMemory:
5153 * @buffer: a pointer to a char array
5154 * @size: the size of the array
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 in-memory document.
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
5165xmlReaderForMemory(const char *buffer, int size, const char *URL,
5166 const char *encoding, int options)
5167{
5168 xmlTextReaderPtr reader;
5169 xmlParserInputBufferPtr buf;
5170
Daniel Veillard21924522004-02-19 16:37:07 +00005171 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005172 XML_CHAR_ENCODING_NONE);
5173 if (buf == NULL) {
5174 return (NULL);
5175 }
5176 reader = xmlNewTextReader(buf, URL);
5177 if (reader == NULL) {
5178 xmlFreeParserInputBuffer(buf);
5179 return (NULL);
5180 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005181 reader->allocs |= XML_TEXTREADER_INPUT;
5182 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005183 return (reader);
5184}
5185
5186/**
5187 * xmlReaderForFd:
5188 * @fd: an open file descriptor
5189 * @URL: the base URL to use for the document
5190 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005191 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005192 *
5193 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005194 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005195 * NOTE that the file descriptor will not be closed when the
5196 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005197 *
5198 * Returns the new reader or NULL in case of error.
5199 */
5200xmlTextReaderPtr
5201xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5202{
5203 xmlTextReaderPtr reader;
5204 xmlParserInputBufferPtr input;
5205
5206 if (fd < 0)
5207 return (NULL);
5208
5209 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5210 if (input == NULL)
5211 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005212 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005213 reader = xmlNewTextReader(input, URL);
5214 if (reader == NULL) {
5215 xmlFreeParserInputBuffer(input);
5216 return (NULL);
5217 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005218 reader->allocs |= XML_TEXTREADER_INPUT;
5219 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005220 return (reader);
5221}
5222
5223/**
5224 * xmlReaderForIO:
5225 * @ioread: an I/O read function
5226 * @ioclose: an I/O close function
5227 * @ioctx: an I/O handler
5228 * @URL: the base URL to use for the document
5229 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005230 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005231 *
5232 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005233 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005234 *
5235 * Returns the new reader or NULL in case of error.
5236 */
5237xmlTextReaderPtr
5238xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5239 void *ioctx, const char *URL, const char *encoding,
5240 int options)
5241{
5242 xmlTextReaderPtr reader;
5243 xmlParserInputBufferPtr input;
5244
5245 if (ioread == NULL)
5246 return (NULL);
5247
5248 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5249 XML_CHAR_ENCODING_NONE);
5250 if (input == NULL)
5251 return (NULL);
5252 reader = xmlNewTextReader(input, URL);
5253 if (reader == NULL) {
5254 xmlFreeParserInputBuffer(input);
5255 return (NULL);
5256 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005257 reader->allocs |= XML_TEXTREADER_INPUT;
5258 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005259 return (reader);
5260}
5261
5262/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005263 * xmlReaderNewWalker:
5264 * @reader: an XML reader
5265 * @doc: a preparsed document
5266 *
5267 * Setup an xmltextReader to parse a preparsed XML document.
5268 * This reuses the existing @reader xmlTextReader.
5269 *
5270 * Returns 0 in case of success and -1 in case of error
5271 */
5272int
5273xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5274{
5275 if (doc == NULL)
5276 return (-1);
5277 if (reader == NULL)
5278 return (-1);
5279
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005280 if (reader->input != NULL) {
5281 xmlFreeParserInputBuffer(reader->input);
5282 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005283 if (reader->ctxt != NULL) {
5284 xmlCtxtReset(reader->ctxt);
5285 }
5286
5287 reader->entNr = 0;
5288 reader->input = NULL;
5289 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5290 reader->node = NULL;
5291 reader->curnode = NULL;
5292 reader->base = 0;
5293 reader->cur = 0;
5294 reader->allocs = XML_TEXTREADER_CTXT;
5295 reader->doc = doc;
5296 reader->state = XML_TEXTREADER_START;
5297 if (reader->dict == NULL) {
5298 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5299 reader->dict = reader->ctxt->dict;
5300 else
5301 reader->dict = xmlDictCreate();
5302 }
5303 return(0);
5304}
5305
5306/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005307 * xmlReaderNewDoc:
5308 * @reader: an XML reader
5309 * @cur: a pointer to a zero terminated string
5310 * @URL: the base URL to use for the document
5311 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005312 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005313 *
5314 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005315 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005316 * This reuses the existing @reader xmlTextReader.
5317 *
5318 * Returns 0 in case of success and -1 in case of error
5319 */
5320int
5321xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5322 const char *URL, const char *encoding, int options)
5323{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005324
5325 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005326
5327 if (cur == NULL)
5328 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005329 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005330 return (-1);
5331
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005332 len = xmlStrlen(cur);
5333 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5334 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005335}
5336
5337/**
5338 * xmlReaderNewFile:
5339 * @reader: an XML reader
5340 * @filename: a file or URL
5341 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005342 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005343 *
5344 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005345 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005346 * This reuses the existing @reader xmlTextReader.
5347 *
5348 * Returns 0 in case of success and -1 in case of error
5349 */
5350int
5351xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5352 const char *encoding, int options)
5353{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005354 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005355
5356 if (filename == NULL)
5357 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005358 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005359 return (-1);
5360
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005361 input =
5362 xmlParserInputBufferCreateFilename(filename,
5363 XML_CHAR_ENCODING_NONE);
5364 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005365 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005366 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005367}
5368
5369/**
5370 * xmlReaderNewMemory:
5371 * @reader: an XML reader
5372 * @buffer: a pointer to a char array
5373 * @size: the size of the array
5374 * @URL: the base URL to use for the document
5375 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005376 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377 *
5378 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005379 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005380 * This reuses the existing @reader xmlTextReader.
5381 *
5382 * Returns 0 in case of success and -1 in case of error
5383 */
5384int
5385xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5386 const char *URL, const char *encoding, int options)
5387{
5388 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005389
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005390 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005391 return (-1);
5392 if (buffer == NULL)
5393 return (-1);
5394
Daniel Veillard21924522004-02-19 16:37:07 +00005395 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005396 XML_CHAR_ENCODING_NONE);
5397 if (input == NULL) {
5398 return (-1);
5399 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005400 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005401}
5402
5403/**
5404 * xmlReaderNewFd:
5405 * @reader: an XML reader
5406 * @fd: an open file descriptor
5407 * @URL: the base URL to use for the document
5408 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005409 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005410 *
5411 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005412 * NOTE that the file descriptor will not be closed when the
5413 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005414 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005415 * This reuses the existing @reader xmlTextReader.
5416 *
5417 * Returns 0 in case of success and -1 in case of error
5418 */
5419int
5420xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5421 const char *URL, const char *encoding, int options)
5422{
5423 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005424
5425 if (fd < 0)
5426 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005427 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005428 return (-1);
5429
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005430 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5431 if (input == NULL)
5432 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005433 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005434 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005435}
5436
5437/**
5438 * xmlReaderNewIO:
5439 * @reader: an XML reader
5440 * @ioread: an I/O read function
5441 * @ioclose: an I/O close function
5442 * @ioctx: an I/O handler
5443 * @URL: the base URL to use for the document
5444 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005445 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005446 *
5447 * Setup an xmltextReader to parse an XML document from I/O functions
5448 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005449 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005450 * This reuses the existing @reader xmlTextReader.
5451 *
5452 * Returns 0 in case of success and -1 in case of error
5453 */
5454int
5455xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5456 xmlInputCloseCallback ioclose, void *ioctx,
5457 const char *URL, const char *encoding, int options)
5458{
5459 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005460
5461 if (ioread == NULL)
5462 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005463 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005464 return (-1);
5465
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005466 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5467 XML_CHAR_ENCODING_NONE);
5468 if (input == NULL)
5469 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005470 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005471}
Daniel Veillard26f70262003-01-16 22:45:08 +00005472/************************************************************************
5473 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005474 * Utilities *
5475 * *
5476 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005477#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005478/**
5479 * xmlBase64Decode:
5480 * @in: the input buffer
5481 * @inlen: the size of the input (in), the size read from it (out)
5482 * @to: the output buffer
5483 * @tolen: the size of the output (in), the size written to (out)
5484 *
5485 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005486 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005487 *
5488 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5489 * 2 if there wasn't enough space on the output or -1 in case of error.
5490 */
5491static int
5492xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5493 unsigned char *to, unsigned long *tolen) {
5494 unsigned long incur; /* current index in in[] */
5495 unsigned long inblk; /* last block index in in[] */
5496 unsigned long outcur; /* current index in out[] */
5497 unsigned long inmax; /* size of in[] */
5498 unsigned long outmax; /* size of out[] */
5499 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005500 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005501 int nbintmp; /* number of byte in intmp[] */
5502 int is_ignore; /* cur should be ignored */
5503 int is_end = 0; /* the end of the base64 was found */
5504 int retval = 1;
5505 int i;
5506
5507 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5508 return(-1);
5509
5510 incur = 0;
5511 inblk = 0;
5512 outcur = 0;
5513 inmax = *inlen;
5514 outmax = *tolen;
5515 nbintmp = 0;
5516
5517 while (1) {
5518 if (incur >= inmax)
5519 break;
5520 cur = in[incur++];
5521 is_ignore = 0;
5522 if ((cur >= 'A') && (cur <= 'Z'))
5523 cur = cur - 'A';
5524 else if ((cur >= 'a') && (cur <= 'z'))
5525 cur = cur - 'a' + 26;
5526 else if ((cur >= '0') && (cur <= '9'))
5527 cur = cur - '0' + 52;
5528 else if (cur == '+')
5529 cur = 62;
5530 else if (cur == '/')
5531 cur = 63;
5532 else if (cur == '.')
5533 cur = 0;
5534 else if (cur == '=') /*no op , end of the base64 stream */
5535 is_end = 1;
5536 else {
5537 is_ignore = 1;
5538 if (nbintmp == 0)
5539 inblk = incur;
5540 }
5541
5542 if (!is_ignore) {
5543 int nbouttmp = 3;
5544 int is_break = 0;
5545
5546 if (is_end) {
5547 if (nbintmp == 0)
5548 break;
5549 if ((nbintmp == 1) || (nbintmp == 2))
5550 nbouttmp = 1;
5551 else
5552 nbouttmp = 2;
5553 nbintmp = 3;
5554 is_break = 1;
5555 }
5556 intmp[nbintmp++] = cur;
5557 /*
5558 * if intmp is full, push the 4byte sequence as a 3 byte
5559 * sequence out
5560 */
5561 if (nbintmp == 4) {
5562 nbintmp = 0;
5563 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5564 outtmp[1] =
5565 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5566 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5567 if (outcur + 3 >= outmax) {
5568 retval = 2;
5569 break;
5570 }
5571
5572 for (i = 0; i < nbouttmp; i++)
5573 to[outcur++] = outtmp[i];
5574 inblk = incur;
5575 }
5576
5577 if (is_break) {
5578 retval = 0;
5579 break;
5580 }
5581 }
5582 }
5583
5584 *tolen = outcur;
5585 *inlen = inblk;
5586 return (retval);
5587}
5588
5589/*
5590 * Test routine for the xmlBase64Decode function
5591 */
5592#if 0
5593int main(int argc, char **argv) {
5594 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5595 char output[100];
5596 char output2[100];
5597 char output3[100];
5598 unsigned long inlen = strlen(input);
5599 unsigned long outlen = 100;
5600 int ret;
5601 unsigned long cons, tmp, tmp2, prod;
5602
5603 /*
5604 * Direct
5605 */
5606 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5607
5608 output[outlen] = 0;
5609 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5610
5611 /*
5612 * output chunking
5613 */
5614 cons = 0;
5615 prod = 0;
5616 while (cons < inlen) {
5617 tmp = 5;
5618 tmp2 = inlen - cons;
5619
5620 printf("%ld %ld\n", cons, prod);
5621 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5622 cons += tmp2;
5623 prod += tmp;
5624 printf("%ld %ld\n", cons, prod);
5625 }
5626 output2[outlen] = 0;
5627 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5628
5629 /*
5630 * input chunking
5631 */
5632 cons = 0;
5633 prod = 0;
5634 while (cons < inlen) {
5635 tmp = 100 - prod;
5636 tmp2 = inlen - cons;
5637 if (tmp2 > 5)
5638 tmp2 = 5;
5639
5640 printf("%ld %ld\n", cons, prod);
5641 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5642 cons += tmp2;
5643 prod += tmp;
5644 printf("%ld %ld\n", cons, prod);
5645 }
5646 output3[outlen] = 0;
5647 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5648 return(0);
5649
5650}
5651#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005652#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005653#define bottom_xmlreader
5654#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005655#endif /* LIBXML_READER_ENABLED */