blob: 1dc5af1dbc97e48bf90b0172bbb5526d2ee6f7f5 [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;
Daniel Veillard11ce4002006-03-10 00:36:23 +00001139 if (cur == NULL) break;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001140 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 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001472 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001473 reader->in_xinclude++;
1474 goto get_next_node;
1475 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001476 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001477 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
Daniel Veillardd0271472006-01-02 10:22:02 +00001629#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001630/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001631 * xmlTextReaderReadInnerXml:
1632 * @reader: the xmlTextReaderPtr used
1633 *
1634 * Reads the contents of the current node, including child nodes and markup.
1635 *
1636 * Returns a string containing the XML content, or NULL if the current node
1637 * is neither an element nor attribute, or has no child nodes. The
1638 * string must be deallocated by the caller.
1639 */
1640xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001641xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1642{
1643 xmlChar *resbuf;
1644 xmlNodePtr node, cur_node;
1645 xmlBufferPtr buff, buff2;
1646 xmlDocPtr doc;
1647
1648 if (xmlTextReaderExpand(reader) == NULL) {
1649 return NULL;
1650 }
1651 doc = reader->doc;
1652 buff = xmlBufferCreate();
1653 for (cur_node = reader->node->children; cur_node != NULL;
1654 cur_node = cur_node->next) {
1655 node = xmlDocCopyNode(cur_node, doc, 1);
1656 buff2 = xmlBufferCreate();
1657 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1658 xmlFreeNode(node);
1659 xmlBufferFree(buff2);
1660 xmlBufferFree(buff);
1661 return NULL;
1662 }
1663 xmlBufferCat(buff, buff2->content);
1664 xmlFreeNode(node);
1665 xmlBufferFree(buff2);
1666 }
1667 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001668 buff->content = NULL;
1669
1670 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001671 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001672}
Daniel Veillardd0271472006-01-02 10:22:02 +00001673#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001674
Daniel Veillardd0271472006-01-02 10:22:02 +00001675#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001676/**
1677 * xmlTextReaderReadOuterXml:
1678 * @reader: the xmlTextReaderPtr used
1679 *
1680 * Reads the contents of the current node, including child nodes and markup.
1681 *
1682 * Returns a string containing the XML content, or NULL if the current node
1683 * is neither an element nor attribute, or has no child nodes. The
1684 * string must be deallocated by the caller.
1685 */
1686xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001687xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1688{
1689 xmlChar *resbuf;
1690 xmlNodePtr node;
1691 xmlBufferPtr buff;
1692 xmlDocPtr doc;
1693
1694 node = reader->node;
1695 doc = reader->doc;
1696 if (xmlTextReaderExpand(reader) == NULL) {
1697 return NULL;
1698 }
1699 node = xmlDocCopyNode(node, doc, 1);
1700 buff = xmlBufferCreate();
1701 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1702 xmlFreeNode(node);
1703 xmlBufferFree(buff);
1704 return NULL;
1705 }
1706
1707 resbuf = buff->content;
1708 buff->content = NULL;
1709
1710 xmlFreeNode(node);
1711 xmlBufferFree(buff);
1712 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001713}
Daniel Veillardd0271472006-01-02 10:22:02 +00001714#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001715
1716/**
1717 * xmlTextReaderReadString:
1718 * @reader: the xmlTextReaderPtr used
1719 *
1720 * Reads the contents of an element or a text node as a string.
1721 *
1722 * Returns a string containing the contents of the Element or Text node,
1723 * or NULL if the reader is positioned on any other type of node.
1724 * The string must be deallocated by the caller.
1725 */
1726xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001727xmlTextReaderReadString(xmlTextReaderPtr reader)
1728{
1729 xmlNodePtr node;
1730
1731 if ((reader == NULL) || (reader->node == NULL))
1732 return(NULL);
1733
1734 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1735 switch (node->type) {
1736 case XML_TEXT_NODE:
1737 if (node->content != NULL)
1738 return(xmlStrdup(node->content));
1739 break;
1740 case XML_ELEMENT_NODE:
1741 if (xmlTextReaderDoExpand(reader) != -1) {
1742 return xmlTextReaderCollectSiblings(node->children);
1743 }
1744 case XML_ATTRIBUTE_NODE:
1745 TODO
1746 break;
1747 default:
1748 break;
1749 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001750 return(NULL);
1751}
1752
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001753#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001754/**
1755 * xmlTextReaderReadBase64:
1756 * @reader: the xmlTextReaderPtr used
1757 * @array: a byte array to store the content.
1758 * @offset: the zero-based index into array where the method should
1759 * begin to write.
1760 * @len: the number of bytes to write.
1761 *
1762 * Reads and decodes the Base64 encoded contents of an element and
1763 * stores the result in a byte buffer.
1764 *
1765 * Returns the number of bytes written to array, or zero if the current
1766 * instance is not positioned on an element or -1 in case of error.
1767 */
1768int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001769xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1770 unsigned char *array ATTRIBUTE_UNUSED,
1771 int offset ATTRIBUTE_UNUSED,
1772 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001773 if ((reader == NULL) || (reader->ctxt == NULL))
1774 return(-1);
1775 if (reader->ctxt->wellFormed != 1)
1776 return(-1);
1777
1778 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1779 return(0);
1780 TODO
1781 return(0);
1782}
1783
1784/**
1785 * xmlTextReaderReadBinHex:
1786 * @reader: the xmlTextReaderPtr used
1787 * @array: a byte array to store the content.
1788 * @offset: the zero-based index into array where the method should
1789 * begin to write.
1790 * @len: the number of bytes to write.
1791 *
1792 * Reads and decodes the BinHex encoded contents of an element and
1793 * stores the result in a byte buffer.
1794 *
1795 * Returns the number of bytes written to array, or zero if the current
1796 * instance is not positioned on an element or -1 in case of error.
1797 */
1798int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001799xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1800 unsigned char *array ATTRIBUTE_UNUSED,
1801 int offset ATTRIBUTE_UNUSED,
1802 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001803 if ((reader == NULL) || (reader->ctxt == NULL))
1804 return(-1);
1805 if (reader->ctxt->wellFormed != 1)
1806 return(-1);
1807
1808 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1809 return(0);
1810 TODO
1811 return(0);
1812}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001813#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001814
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001815/************************************************************************
1816 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001817 * Operating on a preparsed tree *
1818 * *
1819 ************************************************************************/
1820static int
1821xmlTextReaderNextTree(xmlTextReaderPtr reader)
1822{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001823 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001824 return(-1);
1825
1826 if (reader->state == XML_TEXTREADER_END)
1827 return(0);
1828
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001829 if (reader->node == NULL) {
1830 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001831 reader->state = XML_TEXTREADER_END;
1832 return(0);
1833 }
1834
1835 reader->node = reader->doc->children;
1836 reader->state = XML_TEXTREADER_START;
1837 return(1);
1838 }
1839
1840 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1841 if (reader->node->children != 0) {
1842 reader->node = reader->node->children;
1843 reader->depth++;
1844 reader->state = XML_TEXTREADER_START;
1845 return(1);
1846 }
1847
1848 if ((reader->node->type == XML_ELEMENT_NODE) ||
1849 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1850 reader->state = XML_TEXTREADER_BACKTRACK;
1851 return(1);
1852 }
1853 }
1854
1855 if (reader->node->next != 0) {
1856 reader->node = reader->node->next;
1857 reader->state = XML_TEXTREADER_START;
1858 return(1);
1859 }
1860
1861 if (reader->node->parent != 0) {
1862 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1863 reader->state = XML_TEXTREADER_END;
1864 return(0);
1865 }
1866
1867 reader->node = reader->node->parent;
1868 reader->depth--;
1869 reader->state = XML_TEXTREADER_BACKTRACK;
1870 return(1);
1871 }
1872
1873 reader->state = XML_TEXTREADER_END;
1874
1875 return(1);
1876}
1877
1878/**
1879 * xmlTextReaderReadTree:
1880 * @reader: the xmlTextReaderPtr used
1881 *
1882 * Moves the position of the current instance to the next node in
1883 * the stream, exposing its properties.
1884 *
1885 * Returns 1 if the node was read successfully, 0 if there is no more
1886 * nodes to read, or -1 in case of error
1887 */
1888static int
1889xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1890 if (reader->state == XML_TEXTREADER_END)
1891 return(0);
1892
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001893next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001894 if (reader->node == NULL) {
1895 if (reader->doc->children == NULL) {
1896 reader->state = XML_TEXTREADER_END;
1897 return(0);
1898 }
1899
1900 reader->node = reader->doc->children;
1901 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001902 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 }
1904
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001905 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1906 (reader->node->type != XML_DTD_NODE) &&
1907 (reader->node->type != XML_XINCLUDE_START) &&
1908 (reader->node->type != XML_ENTITY_REF_NODE)) {
1909 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 reader->node = reader->node->children;
1911 reader->depth++;
1912 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001913 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001914 }
1915
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001916 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001917 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001918 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001919 }
1920 }
1921
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001922 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 reader->node = reader->node->next;
1924 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001925 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001926 }
1927
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001928 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001929 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1930 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1931 reader->state = XML_TEXTREADER_END;
1932 return(0);
1933 }
1934
1935 reader->node = reader->node->parent;
1936 reader->depth--;
1937 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001938 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001939 }
1940
1941 reader->state = XML_TEXTREADER_END;
1942
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001943found_node:
1944 if ((reader->node->type == XML_XINCLUDE_START) ||
1945 (reader->node->type == XML_XINCLUDE_END))
1946 goto next_node;
1947
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001948 return(1);
1949}
1950
1951/**
William M. Brackb1d53162003-11-18 06:54:40 +00001952 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001953 * @reader: the xmlTextReaderPtr used
1954 *
1955 * Skip to the node following the current one in document order while
1956 * avoiding the subtree if any.
1957 * Currently implemented only for Readers built on a document
1958 *
1959 * Returns 1 if the node was read successfully, 0 if there is no more
1960 * nodes to read, or -1 in case of error
1961 */
1962int
1963xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1964 if (reader == NULL)
1965 return(-1);
1966 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001967 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001968 return(-1);
1969 }
1970
1971 if (reader->state == XML_TEXTREADER_END)
1972 return(0);
1973
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001974 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001975 return(xmlTextReaderNextTree(reader));
1976
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001977 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001978 reader->node = reader->node->next;
1979 reader->state = XML_TEXTREADER_START;
1980 return(1);
1981 }
1982
1983 return(0);
1984}
1985
1986/************************************************************************
1987 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001988 * Constructor and destructors *
1989 * *
1990 ************************************************************************/
1991/**
1992 * xmlNewTextReader:
1993 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001994 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001995 *
1996 * Create an xmlTextReader structure fed with @input
1997 *
1998 * Returns the new xmlTextReaderPtr or NULL in case of error
1999 */
2000xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002001xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002002 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002003
2004 if (input == NULL)
2005 return(NULL);
2006 ret = xmlMalloc(sizeof(xmlTextReader));
2007 if (ret == NULL) {
2008 xmlGenericError(xmlGenericErrorContext,
2009 "xmlNewTextReader : malloc failed\n");
2010 return(NULL);
2011 }
2012 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002013 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002014 ret->entTab = NULL;
2015 ret->entMax = 0;
2016 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002017 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002018 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002019 if (ret->buffer == NULL) {
2020 xmlFree(ret);
2021 xmlGenericError(xmlGenericErrorContext,
2022 "xmlNewTextReader : malloc failed\n");
2023 return(NULL);
2024 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002025 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2026 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002027 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002028 xmlFree(ret);
2029 xmlGenericError(xmlGenericErrorContext,
2030 "xmlNewTextReader : malloc failed\n");
2031 return(NULL);
2032 }
Daniel Veillard81273902003-09-30 00:43:48 +00002033 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002034 ret->startElement = ret->sax->startElement;
2035 ret->sax->startElement = xmlTextReaderStartElement;
2036 ret->endElement = ret->sax->endElement;
2037 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002038#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002039 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002040#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002041 ret->startElementNs = ret->sax->startElementNs;
2042 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2043 ret->endElementNs = ret->sax->endElementNs;
2044 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002045#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002046 } else {
2047 ret->startElementNs = NULL;
2048 ret->endElementNs = NULL;
2049 }
Daniel Veillard81273902003-09-30 00:43:48 +00002050#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002051 ret->characters = ret->sax->characters;
2052 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002053 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002054 ret->cdataBlock = ret->sax->cdataBlock;
2055 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002056
Daniel Veillard67df8092002-12-16 22:04:11 +00002057 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002058 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002059 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002060 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002061 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002062 }
2063 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002064 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002065 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002066 ret->base = 0;
2067 ret->cur = 4;
2068 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002069 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002070 ret->base = 0;
2071 ret->cur = 0;
2072 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002073
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002074 if (ret->ctxt == NULL) {
2075 xmlGenericError(xmlGenericErrorContext,
2076 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002077 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002078 xmlFree(ret->sax);
2079 xmlFree(ret);
2080 return(NULL);
2081 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002082 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002083 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002084 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002085 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002086 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002087 /*
2088 * use the parser dictionnary to allocate all elements and attributes names
2089 */
2090 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002091 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002092#ifdef LIBXML_XINCLUDE_ENABLED
2093 ret->xinclude = 0;
2094#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002095#ifdef LIBXML_PATTERN_ENABLED
2096 ret->patternMax = 0;
2097 ret->patternTab = NULL;
2098#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002099 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002100}
2101
2102/**
2103 * xmlNewTextReaderFilename:
2104 * @URI: the URI of the resource to process
2105 *
2106 * Create an xmlTextReader structure fed with the resource at @URI
2107 *
2108 * Returns the new xmlTextReaderPtr or NULL in case of error
2109 */
2110xmlTextReaderPtr
2111xmlNewTextReaderFilename(const char *URI) {
2112 xmlParserInputBufferPtr input;
2113 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002114 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115
2116 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2117 if (input == NULL)
2118 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002119 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002120 if (ret == NULL) {
2121 xmlFreeParserInputBuffer(input);
2122 return(NULL);
2123 }
2124 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002125 if (ret->ctxt->directory == NULL)
2126 directory = xmlParserGetDirectory(URI);
2127 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2128 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2129 if (directory != NULL)
2130 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002131 return(ret);
2132}
2133
2134/**
2135 * xmlFreeTextReader:
2136 * @reader: the xmlTextReaderPtr
2137 *
2138 * Deallocate all the resources associated to the reader
2139 */
2140void
2141xmlFreeTextReader(xmlTextReaderPtr reader) {
2142 if (reader == NULL)
2143 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002144#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002145 if (reader->rngSchemas != NULL) {
2146 xmlRelaxNGFree(reader->rngSchemas);
2147 reader->rngSchemas = NULL;
2148 }
2149 if (reader->rngValidCtxt != NULL) {
2150 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2151 reader->rngValidCtxt = NULL;
2152 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002153 if (reader->xsdPlug != NULL) {
2154 xmlSchemaSAXUnplug(reader->xsdPlug);
2155 reader->xsdPlug = NULL;
2156 }
2157 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002158 if (! reader->xsdPreserveCtxt)
2159 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002160 reader->xsdValidCtxt = NULL;
2161 }
2162 if (reader->xsdSchemas != NULL) {
2163 xmlSchemaFree(reader->xsdSchemas);
2164 reader->xsdSchemas = NULL;
2165 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002166#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002167#ifdef LIBXML_XINCLUDE_ENABLED
2168 if (reader->xincctxt != NULL)
2169 xmlXIncludeFreeContext(reader->xincctxt);
2170#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002171#ifdef LIBXML_PATTERN_ENABLED
2172 if (reader->patternTab != NULL) {
2173 int i;
2174 for (i = 0;i < reader->patternNr;i++) {
2175 if (reader->patternTab[i] != NULL)
2176 xmlFreePattern(reader->patternTab[i]);
2177 }
2178 xmlFree(reader->patternTab);
2179 }
2180#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002181 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002182 if (reader->dict == reader->ctxt->dict)
2183 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002184 if (reader->ctxt->myDoc != NULL) {
2185 if (reader->preserve == 0)
2186 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2187 reader->ctxt->myDoc = NULL;
2188 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002189 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2190 (reader->ctxt->vctxt.vstateMax > 0)){
2191 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002192 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002193 reader->ctxt->vctxt.vstateMax = 0;
2194 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002195 if (reader->allocs & XML_TEXTREADER_CTXT)
2196 xmlFreeParserCtxt(reader->ctxt);
2197 }
2198 if (reader->sax != NULL)
2199 xmlFree(reader->sax);
2200 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2201 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002202 if (reader->faketext != NULL) {
2203 xmlFreeNode(reader->faketext);
2204 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002205 if (reader->buffer != NULL)
2206 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002207 if (reader->entTab != NULL)
2208 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002209 if (reader->dict != NULL)
2210 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002211 xmlFree(reader);
2212}
2213
2214/************************************************************************
2215 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002216 * Methods for XmlTextReader *
2217 * *
2218 ************************************************************************/
2219/**
2220 * xmlTextReaderClose:
2221 * @reader: the xmlTextReaderPtr used
2222 *
2223 * This method releases any resources allocated by the current instance
2224 * changes the state to Closed and close any underlying input.
2225 *
2226 * Returns 0 or -1 in case of error
2227 */
2228int
2229xmlTextReaderClose(xmlTextReaderPtr reader) {
2230 if (reader == NULL)
2231 return(-1);
2232 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002233 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002234 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2235 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002236 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002237 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002238 if (reader->preserve == 0)
2239 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002240 reader->ctxt->myDoc = NULL;
2241 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002242 }
2243 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2244 xmlFreeParserInputBuffer(reader->input);
2245 reader->allocs -= XML_TEXTREADER_INPUT;
2246 }
2247 return(0);
2248}
2249
2250/**
2251 * xmlTextReaderGetAttributeNo:
2252 * @reader: the xmlTextReaderPtr used
2253 * @no: the zero-based index of the attribute relative to the containing element
2254 *
2255 * Provides the value of the attribute with the specified index relative
2256 * to the containing element.
2257 *
2258 * Returns a string containing the value of the specified attribute, or NULL
2259 * in case of error. The string must be deallocated by the caller.
2260 */
2261xmlChar *
2262xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2263 xmlChar *ret;
2264 int i;
2265 xmlAttrPtr cur;
2266 xmlNsPtr ns;
2267
2268 if (reader == NULL)
2269 return(NULL);
2270 if (reader->node == NULL)
2271 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002272 if (reader->curnode != NULL)
2273 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002274 /* TODO: handle the xmlDecl */
2275 if (reader->node->type != XML_ELEMENT_NODE)
2276 return(NULL);
2277
2278 ns = reader->node->nsDef;
2279 for (i = 0;(i < no) && (ns != NULL);i++) {
2280 ns = ns->next;
2281 }
2282 if (ns != NULL)
2283 return(xmlStrdup(ns->href));
2284
2285 cur = reader->node->properties;
2286 if (cur == NULL)
2287 return(NULL);
2288 for (;i < no;i++) {
2289 cur = cur->next;
2290 if (cur == NULL)
2291 return(NULL);
2292 }
2293 /* TODO walk the DTD if present */
2294
2295 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2296 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2297 return(ret);
2298}
2299
2300/**
2301 * xmlTextReaderGetAttribute:
2302 * @reader: the xmlTextReaderPtr used
2303 * @name: the qualified name of the attribute.
2304 *
2305 * Provides the value of the attribute with the specified qualified name.
2306 *
2307 * Returns a string containing the value of the specified attribute, or NULL
2308 * in case of error. The string must be deallocated by the caller.
2309 */
2310xmlChar *
2311xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2312 xmlChar *prefix = NULL;
2313 xmlChar *localname;
2314 xmlNsPtr ns;
2315 xmlChar *ret = NULL;
2316
2317 if ((reader == NULL) || (name == NULL))
2318 return(NULL);
2319 if (reader->node == NULL)
2320 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002321 if (reader->curnode != NULL)
2322 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002323
2324 /* TODO: handle the xmlDecl */
2325 if (reader->node->type != XML_ELEMENT_NODE)
2326 return(NULL);
2327
2328 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002329 if (localname == NULL) {
2330 /*
2331 * Namespace default decl
2332 */
2333 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2334 ns = reader->node->nsDef;
2335 while (ns != NULL) {
2336 if (ns->prefix == NULL) {
2337 return(xmlStrdup(ns->href));
2338 }
2339 ns = ns->next;
2340 }
2341 return NULL;
2342 }
2343 return(xmlGetNoNsProp(reader->node, name));
2344 }
2345
2346 /*
2347 * Namespace default decl
2348 */
2349 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2350 ns = reader->node->nsDef;
2351 while (ns != NULL) {
2352 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2353 ret = xmlStrdup(ns->href);
2354 break;
2355 }
2356 ns = ns->next;
2357 }
2358 } else {
2359 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2360 if (ns != NULL)
2361 ret = xmlGetNsProp(reader->node, localname, ns->href);
2362 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002363
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002364 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002365 if (prefix != NULL)
2366 xmlFree(prefix);
2367 return(ret);
2368}
2369
2370
2371/**
2372 * xmlTextReaderGetAttributeNs:
2373 * @reader: the xmlTextReaderPtr used
2374 * @localName: the local name of the attribute.
2375 * @namespaceURI: the namespace URI of the attribute.
2376 *
2377 * Provides the value of the specified attribute
2378 *
2379 * Returns a string containing the value of the specified attribute, or NULL
2380 * in case of error. The string must be deallocated by the caller.
2381 */
2382xmlChar *
2383xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2384 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002385 xmlChar *prefix = NULL;
2386 xmlNsPtr ns;
2387
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002388 if ((reader == NULL) || (localName == NULL))
2389 return(NULL);
2390 if (reader->node == NULL)
2391 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002392 if (reader->curnode != NULL)
2393 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002394
2395 /* TODO: handle the xmlDecl */
2396 if (reader->node->type != XML_ELEMENT_NODE)
2397 return(NULL);
2398
Daniel Veillard45b97e72005-08-20 21:14:28 +00002399 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2400 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2401 prefix = BAD_CAST localName;
2402 }
2403 ns = reader->node->nsDef;
2404 while (ns != NULL) {
2405 if ((prefix == NULL && ns->prefix == NULL) ||
2406 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2407 return xmlStrdup(ns->href);
2408 }
2409 ns = ns->next;
2410 }
2411 return NULL;
2412 }
2413
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002414 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2415}
2416
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002417/**
2418 * xmlTextReaderGetRemainder:
2419 * @reader: the xmlTextReaderPtr used
2420 *
2421 * Method to get the remainder of the buffered XML. this method stops the
2422 * parser, set its state to End Of File and return the input stream with
2423 * what is left that the parser did not use.
2424 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002425 * The implementation is not good, the parser certainly procgressed past
2426 * what's left in reader->input, and there is an allocation problem. Best
2427 * would be to rewrite it differently.
2428 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002429 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2430 * in case of error.
2431 */
2432xmlParserInputBufferPtr
2433xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2434 xmlParserInputBufferPtr ret = NULL;
2435
2436 if (reader == NULL)
2437 return(NULL);
2438 if (reader->node == NULL)
2439 return(NULL);
2440
2441 reader->node = NULL;
2442 reader->curnode = NULL;
2443 reader->mode = XML_TEXTREADER_MODE_EOF;
2444 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002445 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002446 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002447 if (reader->preserve == 0)
2448 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002449 reader->ctxt->myDoc = NULL;
2450 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002451 }
2452 if (reader->allocs & XML_TEXTREADER_INPUT) {
2453 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002454 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002455 reader->allocs -= XML_TEXTREADER_INPUT;
2456 } else {
2457 /*
2458 * Hum, one may need to duplicate the data structure because
2459 * without reference counting the input may be freed twice:
2460 * - by the layer which allocated it.
2461 * - by the layer to which would have been returned to.
2462 */
2463 TODO
2464 return(NULL);
2465 }
2466 return(ret);
2467}
2468
2469/**
2470 * xmlTextReaderLookupNamespace:
2471 * @reader: the xmlTextReaderPtr used
2472 * @prefix: the prefix whose namespace URI is to be resolved. To return
2473 * the default namespace, specify NULL
2474 *
2475 * Resolves a namespace prefix in the scope of the current element.
2476 *
2477 * Returns a string containing the namespace URI to which the prefix maps
2478 * or NULL in case of error. The string must be deallocated by the caller.
2479 */
2480xmlChar *
2481xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2482 xmlNsPtr ns;
2483
2484 if (reader == NULL)
2485 return(NULL);
2486 if (reader->node == NULL)
2487 return(NULL);
2488
2489 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2490 if (ns == NULL)
2491 return(NULL);
2492 return(xmlStrdup(ns->href));
2493}
2494
2495/**
2496 * xmlTextReaderMoveToAttributeNo:
2497 * @reader: the xmlTextReaderPtr used
2498 * @no: the zero-based index of the attribute relative to the containing
2499 * element.
2500 *
2501 * Moves the position of the current instance to the attribute with
2502 * the specified index relative to the containing element.
2503 *
2504 * Returns 1 in case of success, -1 in case of error, 0 if not found
2505 */
2506int
2507xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2508 int i;
2509 xmlAttrPtr cur;
2510 xmlNsPtr ns;
2511
2512 if (reader == NULL)
2513 return(-1);
2514 if (reader->node == NULL)
2515 return(-1);
2516 /* TODO: handle the xmlDecl */
2517 if (reader->node->type != XML_ELEMENT_NODE)
2518 return(-1);
2519
2520 reader->curnode = NULL;
2521
2522 ns = reader->node->nsDef;
2523 for (i = 0;(i < no) && (ns != NULL);i++) {
2524 ns = ns->next;
2525 }
2526 if (ns != NULL) {
2527 reader->curnode = (xmlNodePtr) ns;
2528 return(1);
2529 }
2530
2531 cur = reader->node->properties;
2532 if (cur == NULL)
2533 return(0);
2534 for (;i < no;i++) {
2535 cur = cur->next;
2536 if (cur == NULL)
2537 return(0);
2538 }
2539 /* TODO walk the DTD if present */
2540
2541 reader->curnode = (xmlNodePtr) cur;
2542 return(1);
2543}
2544
2545/**
2546 * xmlTextReaderMoveToAttribute:
2547 * @reader: the xmlTextReaderPtr used
2548 * @name: the qualified name of the attribute.
2549 *
2550 * Moves the position of the current instance to the attribute with
2551 * the specified qualified name.
2552 *
2553 * Returns 1 in case of success, -1 in case of error, 0 if not found
2554 */
2555int
2556xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2557 xmlChar *prefix = NULL;
2558 xmlChar *localname;
2559 xmlNsPtr ns;
2560 xmlAttrPtr prop;
2561
2562 if ((reader == NULL) || (name == NULL))
2563 return(-1);
2564 if (reader->node == NULL)
2565 return(-1);
2566
2567 /* TODO: handle the xmlDecl */
2568 if (reader->node->type != XML_ELEMENT_NODE)
2569 return(0);
2570
2571 localname = xmlSplitQName2(name, &prefix);
2572 if (localname == NULL) {
2573 /*
2574 * Namespace default decl
2575 */
2576 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2577 ns = reader->node->nsDef;
2578 while (ns != NULL) {
2579 if (ns->prefix == NULL) {
2580 reader->curnode = (xmlNodePtr) ns;
2581 return(1);
2582 }
2583 ns = ns->next;
2584 }
2585 return(0);
2586 }
2587
2588 prop = reader->node->properties;
2589 while (prop != NULL) {
2590 /*
2591 * One need to have
2592 * - same attribute names
2593 * - and the attribute carrying that namespace
2594 */
2595 if ((xmlStrEqual(prop->name, name)) &&
2596 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2597 reader->curnode = (xmlNodePtr) prop;
2598 return(1);
2599 }
2600 prop = prop->next;
2601 }
2602 return(0);
2603 }
2604
2605 /*
2606 * Namespace default decl
2607 */
2608 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2609 ns = reader->node->nsDef;
2610 while (ns != NULL) {
2611 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2612 reader->curnode = (xmlNodePtr) ns;
2613 goto found;
2614 }
2615 ns = ns->next;
2616 }
2617 goto not_found;
2618 }
2619 prop = reader->node->properties;
2620 while (prop != NULL) {
2621 /*
2622 * One need to have
2623 * - same attribute names
2624 * - and the attribute carrying that namespace
2625 */
2626 if ((xmlStrEqual(prop->name, localname)) &&
2627 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2628 reader->curnode = (xmlNodePtr) prop;
2629 goto found;
2630 }
2631 prop = prop->next;
2632 }
2633not_found:
2634 if (localname != NULL)
2635 xmlFree(localname);
2636 if (prefix != NULL)
2637 xmlFree(prefix);
2638 return(0);
2639
2640found:
2641 if (localname != NULL)
2642 xmlFree(localname);
2643 if (prefix != NULL)
2644 xmlFree(prefix);
2645 return(1);
2646}
2647
2648/**
2649 * xmlTextReaderMoveToAttributeNs:
2650 * @reader: the xmlTextReaderPtr used
2651 * @localName: the local name of the attribute.
2652 * @namespaceURI: the namespace URI of the attribute.
2653 *
2654 * Moves the position of the current instance to the attribute with the
2655 * specified local name and namespace URI.
2656 *
2657 * Returns 1 in case of success, -1 in case of error, 0 if not found
2658 */
2659int
2660xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2661 const xmlChar *localName, const xmlChar *namespaceURI) {
2662 xmlAttrPtr prop;
2663 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002664 xmlNsPtr ns;
2665 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002666
2667 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2668 return(-1);
2669 if (reader->node == NULL)
2670 return(-1);
2671 if (reader->node->type != XML_ELEMENT_NODE)
2672 return(0);
2673 node = reader->node;
2674
Daniel Veillard45b97e72005-08-20 21:14:28 +00002675 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2676 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2677 prefix = BAD_CAST localName;
2678 }
2679 ns = reader->node->nsDef;
2680 while (ns != NULL) {
2681 if ((prefix == NULL && ns->prefix == NULL) ||
2682 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2683 reader->curnode = (xmlNodePtr) ns;
2684 return(1);
2685 }
2686 ns = ns->next;
2687 }
2688 return(0);
2689 }
2690
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002691 prop = node->properties;
2692 while (prop != NULL) {
2693 /*
2694 * One need to have
2695 * - same attribute names
2696 * - and the attribute carrying that namespace
2697 */
2698 if (xmlStrEqual(prop->name, localName) &&
2699 ((prop->ns != NULL) &&
2700 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2701 reader->curnode = (xmlNodePtr) prop;
2702 return(1);
2703 }
2704 prop = prop->next;
2705 }
2706 return(0);
2707}
2708
2709/**
2710 * xmlTextReaderMoveToFirstAttribute:
2711 * @reader: the xmlTextReaderPtr used
2712 *
2713 * Moves the position of the current instance to the first attribute
2714 * associated with the current node.
2715 *
2716 * Returns 1 in case of success, -1 in case of error, 0 if not found
2717 */
2718int
2719xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2720 if (reader == NULL)
2721 return(-1);
2722 if (reader->node == NULL)
2723 return(-1);
2724 if (reader->node->type != XML_ELEMENT_NODE)
2725 return(0);
2726
2727 if (reader->node->nsDef != NULL) {
2728 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2729 return(1);
2730 }
2731 if (reader->node->properties != NULL) {
2732 reader->curnode = (xmlNodePtr) reader->node->properties;
2733 return(1);
2734 }
2735 return(0);
2736}
2737
2738/**
2739 * xmlTextReaderMoveToNextAttribute:
2740 * @reader: the xmlTextReaderPtr used
2741 *
2742 * Moves the position of the current instance to the next attribute
2743 * associated with the current node.
2744 *
2745 * Returns 1 in case of success, -1 in case of error, 0 if not found
2746 */
2747int
2748xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2749 if (reader == NULL)
2750 return(-1);
2751 if (reader->node == NULL)
2752 return(-1);
2753 if (reader->node->type != XML_ELEMENT_NODE)
2754 return(0);
2755 if (reader->curnode == NULL)
2756 return(xmlTextReaderMoveToFirstAttribute(reader));
2757
2758 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2759 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2760 if (ns->next != NULL) {
2761 reader->curnode = (xmlNodePtr) ns->next;
2762 return(1);
2763 }
2764 if (reader->node->properties != NULL) {
2765 reader->curnode = (xmlNodePtr) reader->node->properties;
2766 return(1);
2767 }
2768 return(0);
2769 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2770 (reader->curnode->next != NULL)) {
2771 reader->curnode = reader->curnode->next;
2772 return(1);
2773 }
2774 return(0);
2775}
2776
2777/**
2778 * xmlTextReaderMoveToElement:
2779 * @reader: the xmlTextReaderPtr used
2780 *
2781 * Moves the position of the current instance to the node that
2782 * contains the current Attribute node.
2783 *
2784 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2785 */
2786int
2787xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2788 if (reader == NULL)
2789 return(-1);
2790 if (reader->node == NULL)
2791 return(-1);
2792 if (reader->node->type != XML_ELEMENT_NODE)
2793 return(0);
2794 if (reader->curnode != NULL) {
2795 reader->curnode = NULL;
2796 return(1);
2797 }
2798 return(0);
2799}
2800
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002801/**
2802 * xmlTextReaderReadAttributeValue:
2803 * @reader: the xmlTextReaderPtr used
2804 *
2805 * Parses an attribute value into one or more Text and EntityReference nodes.
2806 *
2807 * Returns 1 in case of success, 0 if the reader was not positionned on an
2808 * ttribute node or all the attribute values have been read, or -1
2809 * in case of error.
2810 */
2811int
2812xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2813 if (reader == NULL)
2814 return(-1);
2815 if (reader->node == NULL)
2816 return(-1);
2817 if (reader->curnode == NULL)
2818 return(0);
2819 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2820 if (reader->curnode->children == NULL)
2821 return(0);
2822 reader->curnode = reader->curnode->children;
2823 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2824 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2825
2826 if (reader->faketext == NULL) {
2827 reader->faketext = xmlNewDocText(reader->node->doc,
2828 ns->href);
2829 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002830 if ((reader->faketext->content != NULL) &&
2831 (reader->faketext->content !=
2832 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002833 xmlFree(reader->faketext->content);
2834 reader->faketext->content = xmlStrdup(ns->href);
2835 }
2836 reader->curnode = reader->faketext;
2837 } else {
2838 if (reader->curnode->next == NULL)
2839 return(0);
2840 reader->curnode = reader->curnode->next;
2841 }
2842 return(1);
2843}
2844
Daniel Veillarde2811272004-10-19 09:04:23 +00002845/**
2846 * xmlTextReaderConstEncoding:
2847 * @reader: the xmlTextReaderPtr used
2848 *
2849 * Determine the encoding of the document being read.
2850 *
2851 * Returns a string containing the encoding of the document or NULL in
2852 * case of error. The string is deallocated with the reader.
2853 */
2854const xmlChar *
2855xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2856 xmlDocPtr doc = NULL;
2857 if (reader == NULL)
2858 return(NULL);
2859 if (reader->doc != NULL)
2860 doc = reader->doc;
2861 else if (reader->ctxt != NULL)
2862 doc = reader->ctxt->myDoc;
2863 if (doc == NULL)
2864 return(NULL);
2865
2866 if (doc->encoding == NULL)
2867 return(NULL);
2868 else
2869 return(CONSTSTR(doc->encoding));
2870}
2871
2872
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002873/************************************************************************
2874 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002875 * Acces API to the current node *
2876 * *
2877 ************************************************************************/
2878/**
2879 * xmlTextReaderAttributeCount:
2880 * @reader: the xmlTextReaderPtr used
2881 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002882 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002883 *
2884 * Returns 0 i no attributes, -1 in case of error or the attribute count
2885 */
2886int
2887xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2888 int ret;
2889 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002890 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002891 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002892
2893 if (reader == NULL)
2894 return(-1);
2895 if (reader->node == NULL)
2896 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002897
2898 if (reader->curnode != NULL)
2899 node = reader->curnode;
2900 else
2901 node = reader->node;
2902
2903 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002904 return(0);
2905 if ((reader->state == XML_TEXTREADER_END) ||
2906 (reader->state == XML_TEXTREADER_BACKTRACK))
2907 return(0);
2908 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002909 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002910 while (attr != NULL) {
2911 ret++;
2912 attr = attr->next;
2913 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002914 ns = node->nsDef;
2915 while (ns != NULL) {
2916 ret++;
2917 ns = ns->next;
2918 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919 return(ret);
2920}
2921
2922/**
2923 * xmlTextReaderNodeType:
2924 * @reader: the xmlTextReaderPtr used
2925 *
2926 * Get the node type of the current node
2927 * Reference:
2928 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2929 *
2930 * Returns the xmlNodeType of the current node or -1 in case of error
2931 */
2932int
2933xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002934 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002935
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002936 if (reader == NULL)
2937 return(-1);
2938 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002939 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002940 if (reader->curnode != NULL)
2941 node = reader->curnode;
2942 else
2943 node = reader->node;
2944 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002945 case XML_ELEMENT_NODE:
2946 if ((reader->state == XML_TEXTREADER_END) ||
2947 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002948 return(XML_READER_TYPE_END_ELEMENT);
2949 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002950 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002951 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002952 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002953 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002954 if (xmlIsBlankNode(reader->node)) {
2955 if (xmlNodeGetSpacePreserve(reader->node))
2956 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2957 else
2958 return(XML_READER_TYPE_WHITESPACE);
2959 } else {
2960 return(XML_READER_TYPE_TEXT);
2961 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002962 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002963 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002964 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002965 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002966 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002967 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002968 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002969 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002970 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002971 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002972 case XML_DOCUMENT_NODE:
2973 case XML_HTML_DOCUMENT_NODE:
2974#ifdef LIBXML_DOCB_ENABLED
2975 case XML_DOCB_DOCUMENT_NODE:
2976#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002977 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002978 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002979 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002980 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002981 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002982 case XML_DOCUMENT_TYPE_NODE:
2983 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002984 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985
2986 case XML_ELEMENT_DECL:
2987 case XML_ATTRIBUTE_DECL:
2988 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002989 case XML_XINCLUDE_START:
2990 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002991 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002992 }
2993 return(-1);
2994}
2995
2996/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002997 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002998 * @reader: the xmlTextReaderPtr used
2999 *
3000 * Check if the current node is empty
3001 *
3002 * Returns 1 if empty, 0 if not and -1 in case of error
3003 */
3004int
3005xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3006 if ((reader == NULL) || (reader->node == NULL))
3007 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003008 if (reader->node->type != XML_ELEMENT_NODE)
3009 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003010 if (reader->curnode != NULL)
3011 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003012 if (reader->node->children != NULL)
3013 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003014 if (reader->state == XML_TEXTREADER_END)
3015 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003016 if (reader->doc != NULL)
3017 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003018#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003019 if (reader->in_xinclude > 0)
3020 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003021#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003022 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023}
3024
3025/**
3026 * xmlTextReaderLocalName:
3027 * @reader: the xmlTextReaderPtr used
3028 *
3029 * The local name of the node.
3030 *
3031 * Returns the local name or NULL if not available
3032 */
3033xmlChar *
3034xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003035 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003036 if ((reader == NULL) || (reader->node == NULL))
3037 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003038 if (reader->curnode != NULL)
3039 node = reader->curnode;
3040 else
3041 node = reader->node;
3042 if (node->type == XML_NAMESPACE_DECL) {
3043 xmlNsPtr ns = (xmlNsPtr) node;
3044 if (ns->prefix == NULL)
3045 return(xmlStrdup(BAD_CAST "xmlns"));
3046 else
3047 return(xmlStrdup(ns->prefix));
3048 }
3049 if ((node->type != XML_ELEMENT_NODE) &&
3050 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003051 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003052 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003053}
3054
3055/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003056 * xmlTextReaderConstLocalName:
3057 * @reader: the xmlTextReaderPtr used
3058 *
3059 * The local name of the node.
3060 *
3061 * Returns the local name or NULL if not available, the
3062 * string will be deallocated with the reader.
3063 */
3064const xmlChar *
3065xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3066 xmlNodePtr node;
3067 if ((reader == NULL) || (reader->node == NULL))
3068 return(NULL);
3069 if (reader->curnode != NULL)
3070 node = reader->curnode;
3071 else
3072 node = reader->node;
3073 if (node->type == XML_NAMESPACE_DECL) {
3074 xmlNsPtr ns = (xmlNsPtr) node;
3075 if (ns->prefix == NULL)
3076 return(CONSTSTR(BAD_CAST "xmlns"));
3077 else
3078 return(ns->prefix);
3079 }
3080 if ((node->type != XML_ELEMENT_NODE) &&
3081 (node->type != XML_ATTRIBUTE_NODE))
3082 return(xmlTextReaderConstName(reader));
3083 return(node->name);
3084}
3085
3086/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003087 * xmlTextReaderName:
3088 * @reader: the xmlTextReaderPtr used
3089 *
3090 * The qualified name of the node, equal to Prefix :LocalName.
3091 *
3092 * Returns the local name or NULL if not available
3093 */
3094xmlChar *
3095xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003096 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003097 xmlChar *ret;
3098
3099 if ((reader == NULL) || (reader->node == NULL))
3100 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003101 if (reader->curnode != NULL)
3102 node = reader->curnode;
3103 else
3104 node = reader->node;
3105 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003106 case XML_ELEMENT_NODE:
3107 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003108 if ((node->ns == NULL) ||
3109 (node->ns->prefix == NULL))
3110 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003111
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003112 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003113 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003114 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003115 return(ret);
3116 case XML_TEXT_NODE:
3117 return(xmlStrdup(BAD_CAST "#text"));
3118 case XML_CDATA_SECTION_NODE:
3119 return(xmlStrdup(BAD_CAST "#cdata-section"));
3120 case XML_ENTITY_NODE:
3121 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003122 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003123 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003124 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003125 case XML_COMMENT_NODE:
3126 return(xmlStrdup(BAD_CAST "#comment"));
3127 case XML_DOCUMENT_NODE:
3128 case XML_HTML_DOCUMENT_NODE:
3129#ifdef LIBXML_DOCB_ENABLED
3130 case XML_DOCB_DOCUMENT_NODE:
3131#endif
3132 return(xmlStrdup(BAD_CAST "#document"));
3133 case XML_DOCUMENT_FRAG_NODE:
3134 return(xmlStrdup(BAD_CAST "#document-fragment"));
3135 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003136 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003137 case XML_DOCUMENT_TYPE_NODE:
3138 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003139 return(xmlStrdup(node->name));
3140 case XML_NAMESPACE_DECL: {
3141 xmlNsPtr ns = (xmlNsPtr) node;
3142
3143 ret = xmlStrdup(BAD_CAST "xmlns");
3144 if (ns->prefix == NULL)
3145 return(ret);
3146 ret = xmlStrcat(ret, BAD_CAST ":");
3147 ret = xmlStrcat(ret, ns->prefix);
3148 return(ret);
3149 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003150
3151 case XML_ELEMENT_DECL:
3152 case XML_ATTRIBUTE_DECL:
3153 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003154 case XML_XINCLUDE_START:
3155 case XML_XINCLUDE_END:
3156 return(NULL);
3157 }
3158 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003159}
3160
3161/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003162 * xmlTextReaderConstName:
3163 * @reader: the xmlTextReaderPtr used
3164 *
3165 * The qualified name of the node, equal to Prefix :LocalName.
3166 *
3167 * Returns the local name or NULL if not available, the string is
3168 * deallocated with the reader.
3169 */
3170const xmlChar *
3171xmlTextReaderConstName(xmlTextReaderPtr reader) {
3172 xmlNodePtr node;
3173
3174 if ((reader == NULL) || (reader->node == NULL))
3175 return(NULL);
3176 if (reader->curnode != NULL)
3177 node = reader->curnode;
3178 else
3179 node = reader->node;
3180 switch (node->type) {
3181 case XML_ELEMENT_NODE:
3182 case XML_ATTRIBUTE_NODE:
3183 if ((node->ns == NULL) ||
3184 (node->ns->prefix == NULL))
3185 return(node->name);
3186 return(CONSTQSTR(node->ns->prefix, node->name));
3187 case XML_TEXT_NODE:
3188 return(CONSTSTR(BAD_CAST "#text"));
3189 case XML_CDATA_SECTION_NODE:
3190 return(CONSTSTR(BAD_CAST "#cdata-section"));
3191 case XML_ENTITY_NODE:
3192 case XML_ENTITY_REF_NODE:
3193 return(CONSTSTR(node->name));
3194 case XML_PI_NODE:
3195 return(CONSTSTR(node->name));
3196 case XML_COMMENT_NODE:
3197 return(CONSTSTR(BAD_CAST "#comment"));
3198 case XML_DOCUMENT_NODE:
3199 case XML_HTML_DOCUMENT_NODE:
3200#ifdef LIBXML_DOCB_ENABLED
3201 case XML_DOCB_DOCUMENT_NODE:
3202#endif
3203 return(CONSTSTR(BAD_CAST "#document"));
3204 case XML_DOCUMENT_FRAG_NODE:
3205 return(CONSTSTR(BAD_CAST "#document-fragment"));
3206 case XML_NOTATION_NODE:
3207 return(CONSTSTR(node->name));
3208 case XML_DOCUMENT_TYPE_NODE:
3209 case XML_DTD_NODE:
3210 return(CONSTSTR(node->name));
3211 case XML_NAMESPACE_DECL: {
3212 xmlNsPtr ns = (xmlNsPtr) node;
3213
3214 if (ns->prefix == NULL)
3215 return(CONSTSTR(BAD_CAST "xmlns"));
3216 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3217 }
3218
3219 case XML_ELEMENT_DECL:
3220 case XML_ATTRIBUTE_DECL:
3221 case XML_ENTITY_DECL:
3222 case XML_XINCLUDE_START:
3223 case XML_XINCLUDE_END:
3224 return(NULL);
3225 }
3226 return(NULL);
3227}
3228
3229/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003230 * xmlTextReaderPrefix:
3231 * @reader: the xmlTextReaderPtr used
3232 *
3233 * A shorthand reference to the namespace associated with the node.
3234 *
3235 * Returns the prefix or NULL if not available
3236 */
3237xmlChar *
3238xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003239 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003240 if ((reader == NULL) || (reader->node == NULL))
3241 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003242 if (reader->curnode != NULL)
3243 node = reader->curnode;
3244 else
3245 node = reader->node;
3246 if (node->type == XML_NAMESPACE_DECL) {
3247 xmlNsPtr ns = (xmlNsPtr) node;
3248 if (ns->prefix == NULL)
3249 return(NULL);
3250 return(xmlStrdup(BAD_CAST "xmlns"));
3251 }
3252 if ((node->type != XML_ELEMENT_NODE) &&
3253 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003254 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003255 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003256 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003257 return(NULL);
3258}
3259
3260/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003261 * xmlTextReaderConstPrefix:
3262 * @reader: the xmlTextReaderPtr used
3263 *
3264 * A shorthand reference to the namespace associated with the node.
3265 *
3266 * Returns the prefix or NULL if not available, the string is deallocated
3267 * with the reader.
3268 */
3269const xmlChar *
3270xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3271 xmlNodePtr node;
3272 if ((reader == NULL) || (reader->node == NULL))
3273 return(NULL);
3274 if (reader->curnode != NULL)
3275 node = reader->curnode;
3276 else
3277 node = reader->node;
3278 if (node->type == XML_NAMESPACE_DECL) {
3279 xmlNsPtr ns = (xmlNsPtr) node;
3280 if (ns->prefix == NULL)
3281 return(NULL);
3282 return(CONSTSTR(BAD_CAST "xmlns"));
3283 }
3284 if ((node->type != XML_ELEMENT_NODE) &&
3285 (node->type != XML_ATTRIBUTE_NODE))
3286 return(NULL);
3287 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3288 return(CONSTSTR(node->ns->prefix));
3289 return(NULL);
3290}
3291
3292/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003293 * xmlTextReaderNamespaceUri:
3294 * @reader: the xmlTextReaderPtr used
3295 *
3296 * The URI defining the namespace associated with the node.
3297 *
3298 * Returns the namespace URI or NULL if not available
3299 */
3300xmlChar *
3301xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003302 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003303 if ((reader == NULL) || (reader->node == NULL))
3304 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003305 if (reader->curnode != NULL)
3306 node = reader->curnode;
3307 else
3308 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003309 if (node->type == XML_NAMESPACE_DECL)
3310 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003311 if ((node->type != XML_ELEMENT_NODE) &&
3312 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003313 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003314 if (node->ns != NULL)
3315 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003316 return(NULL);
3317}
3318
3319/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003320 * xmlTextReaderConstNamespaceUri:
3321 * @reader: the xmlTextReaderPtr used
3322 *
3323 * The URI defining the namespace associated with the node.
3324 *
3325 * Returns the namespace URI or NULL if not available, the string
3326 * will be deallocated with the reader
3327 */
3328const xmlChar *
3329xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3330 xmlNodePtr node;
3331 if ((reader == NULL) || (reader->node == NULL))
3332 return(NULL);
3333 if (reader->curnode != NULL)
3334 node = reader->curnode;
3335 else
3336 node = reader->node;
3337 if (node->type == XML_NAMESPACE_DECL)
3338 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3339 if ((node->type != XML_ELEMENT_NODE) &&
3340 (node->type != XML_ATTRIBUTE_NODE))
3341 return(NULL);
3342 if (node->ns != NULL)
3343 return(CONSTSTR(node->ns->href));
3344 return(NULL);
3345}
3346
3347/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003348 * xmlTextReaderBaseUri:
3349 * @reader: the xmlTextReaderPtr used
3350 *
3351 * The base URI of the node.
3352 *
3353 * Returns the base URI or NULL if not available
3354 */
3355xmlChar *
3356xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3357 if ((reader == NULL) || (reader->node == NULL))
3358 return(NULL);
3359 return(xmlNodeGetBase(NULL, reader->node));
3360}
3361
3362/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003363 * xmlTextReaderConstBaseUri:
3364 * @reader: the xmlTextReaderPtr used
3365 *
3366 * The base URI of the node.
3367 *
3368 * Returns the base URI or NULL if not available, the string
3369 * will be deallocated with the reader
3370 */
3371const xmlChar *
3372xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3373 xmlChar *tmp;
3374 const xmlChar *ret;
3375
3376 if ((reader == NULL) || (reader->node == NULL))
3377 return(NULL);
3378 tmp = xmlNodeGetBase(NULL, reader->node);
3379 if (tmp == NULL)
3380 return(NULL);
3381 ret = CONSTSTR(tmp);
3382 xmlFree(tmp);
3383 return(ret);
3384}
3385
3386/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003387 * xmlTextReaderDepth:
3388 * @reader: the xmlTextReaderPtr used
3389 *
3390 * The depth of the node in the tree.
3391 *
3392 * Returns the depth or -1 in case of error
3393 */
3394int
3395xmlTextReaderDepth(xmlTextReaderPtr reader) {
3396 if (reader == NULL)
3397 return(-1);
3398 if (reader->node == NULL)
3399 return(0);
3400
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003401 if (reader->curnode != NULL) {
3402 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3403 (reader->curnode->type == XML_NAMESPACE_DECL))
3404 return(reader->depth + 1);
3405 return(reader->depth + 2);
3406 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003407 return(reader->depth);
3408}
3409
3410/**
3411 * xmlTextReaderHasAttributes:
3412 * @reader: the xmlTextReaderPtr used
3413 *
3414 * Whether the node has attributes.
3415 *
3416 * Returns 1 if true, 0 if false, and -1 in case or error
3417 */
3418int
3419xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003420 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003421 if (reader == NULL)
3422 return(-1);
3423 if (reader->node == NULL)
3424 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003425 if (reader->curnode != NULL)
3426 node = reader->curnode;
3427 else
3428 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003429
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003430 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003431 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003432 return(1);
3433 /* TODO: handle the xmlDecl */
3434 return(0);
3435}
3436
3437/**
3438 * xmlTextReaderHasValue:
3439 * @reader: the xmlTextReaderPtr used
3440 *
3441 * Whether the node can have a text value.
3442 *
3443 * Returns 1 if true, 0 if false, and -1 in case or error
3444 */
3445int
3446xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003447 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003448 if (reader == NULL)
3449 return(-1);
3450 if (reader->node == NULL)
3451 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003452 if (reader->curnode != NULL)
3453 node = reader->curnode;
3454 else
3455 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003456
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003457 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003458 case XML_ATTRIBUTE_NODE:
3459 case XML_TEXT_NODE:
3460 case XML_CDATA_SECTION_NODE:
3461 case XML_PI_NODE:
3462 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003463 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003464 return(1);
3465 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003466 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003467 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003468 return(0);
3469}
3470
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003471/**
3472 * xmlTextReaderValue:
3473 * @reader: the xmlTextReaderPtr used
3474 *
3475 * Provides the text value of the node if present
3476 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003477 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003478 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003479 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003480xmlChar *
3481xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003482 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003483 if (reader == NULL)
3484 return(NULL);
3485 if (reader->node == NULL)
3486 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003487 if (reader->curnode != NULL)
3488 node = reader->curnode;
3489 else
3490 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003491
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003492 switch (node->type) {
3493 case XML_NAMESPACE_DECL:
3494 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003495 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003496 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003497
3498 if (attr->parent != NULL)
3499 return (xmlNodeListGetString
3500 (attr->parent->doc, attr->children, 1));
3501 else
3502 return (xmlNodeListGetString(NULL, attr->children, 1));
3503 break;
3504 }
3505 case XML_TEXT_NODE:
3506 case XML_CDATA_SECTION_NODE:
3507 case XML_PI_NODE:
3508 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003509 if (node->content != NULL)
3510 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003511 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003512 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003513 }
3514 return(NULL);
3515}
3516
3517/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003518 * xmlTextReaderConstValue:
3519 * @reader: the xmlTextReaderPtr used
3520 *
3521 * Provides the text value of the node if present
3522 *
3523 * Returns the string or NULL if not available. The result will be
3524 * deallocated on the next Read() operation.
3525 */
3526const xmlChar *
3527xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3528 xmlNodePtr node;
3529 if (reader == NULL)
3530 return(NULL);
3531 if (reader->node == NULL)
3532 return(NULL);
3533 if (reader->curnode != NULL)
3534 node = reader->curnode;
3535 else
3536 node = reader->node;
3537
3538 switch (node->type) {
3539 case XML_NAMESPACE_DECL:
3540 return(((xmlNsPtr) node)->href);
3541 case XML_ATTRIBUTE_NODE:{
3542 xmlAttrPtr attr = (xmlAttrPtr) node;
3543
3544 if ((attr->children != NULL) &&
3545 (attr->children->type == XML_TEXT_NODE) &&
3546 (attr->children->next == NULL))
3547 return(attr->children->content);
3548 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003549 if (reader->buffer == NULL)
3550 reader->buffer = xmlBufferCreateSize(100);
3551 if (reader->buffer == NULL) {
3552 xmlGenericError(xmlGenericErrorContext,
3553 "xmlTextReaderSetup : malloc failed\n");
3554 return (NULL);
3555 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003556 reader->buffer->use = 0;
3557 xmlNodeBufGetContent(reader->buffer, node);
3558 return(reader->buffer->content);
3559 }
3560 break;
3561 }
3562 case XML_TEXT_NODE:
3563 case XML_CDATA_SECTION_NODE:
3564 case XML_PI_NODE:
3565 case XML_COMMENT_NODE:
3566 return(node->content);
3567 default:
3568 break;
3569 }
3570 return(NULL);
3571}
3572
3573/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003574 * xmlTextReaderIsDefault:
3575 * @reader: the xmlTextReaderPtr used
3576 *
3577 * Whether an Attribute node was generated from the default value
3578 * defined in the DTD or schema.
3579 *
3580 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3581 */
3582int
3583xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3584 if (reader == NULL)
3585 return(-1);
3586 return(0);
3587}
3588
3589/**
3590 * xmlTextReaderQuoteChar:
3591 * @reader: the xmlTextReaderPtr used
3592 *
3593 * The quotation mark character used to enclose the value of an attribute.
3594 *
3595 * Returns " or ' and -1 in case of error
3596 */
3597int
3598xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3599 if (reader == NULL)
3600 return(-1);
3601 /* TODO maybe lookup the attribute value for " first */
3602 return((int) '"');
3603}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003604
3605/**
3606 * xmlTextReaderXmlLang:
3607 * @reader: the xmlTextReaderPtr used
3608 *
3609 * The xml:lang scope within which the node resides.
3610 *
3611 * Returns the xml:lang value or NULL if none exists.
3612 */
3613xmlChar *
3614xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3615 if (reader == NULL)
3616 return(NULL);
3617 if (reader->node == NULL)
3618 return(NULL);
3619 return(xmlNodeGetLang(reader->node));
3620}
3621
Daniel Veillard67df8092002-12-16 22:04:11 +00003622/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003623 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003624 * @reader: the xmlTextReaderPtr used
3625 *
3626 * The xml:lang scope within which the node resides.
3627 *
3628 * Returns the xml:lang value or NULL if none exists.
3629 */
3630const xmlChar *
3631xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3632 xmlChar *tmp;
3633 const xmlChar *ret;
3634
3635 if (reader == NULL)
3636 return(NULL);
3637 if (reader->node == NULL)
3638 return(NULL);
3639 tmp = xmlNodeGetLang(reader->node);
3640 if (tmp == NULL)
3641 return(NULL);
3642 ret = CONSTSTR(tmp);
3643 xmlFree(tmp);
3644 return(ret);
3645}
3646
3647/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003648 * xmlTextReaderConstString:
3649 * @reader: the xmlTextReaderPtr used
3650 * @str: the string to intern.
3651 *
3652 * Get an interned string from the reader, allows for example to
3653 * speedup string name comparisons
3654 *
3655 * Returns an interned copy of the string or NULL in case of error. The
3656 * string will be deallocated with the reader.
3657 */
3658const xmlChar *
3659xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3660 if (reader == NULL)
3661 return(NULL);
3662 return(CONSTSTR(str));
3663}
3664
3665/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003666 * xmlTextReaderNormalization:
3667 * @reader: the xmlTextReaderPtr used
3668 *
3669 * The value indicating whether to normalize white space and attribute values.
3670 * Since attribute value and end of line normalizations are a MUST in the XML
3671 * specification only the value true is accepted. The broken bahaviour of
3672 * accepting out of range character entities like &#0; is of course not
3673 * supported either.
3674 *
3675 * Returns 1 or -1 in case of error.
3676 */
3677int
3678xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3679 if (reader == NULL)
3680 return(-1);
3681 return(1);
3682}
3683
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003684/************************************************************************
3685 * *
3686 * Extensions to the base APIs *
3687 * *
3688 ************************************************************************/
3689
3690/**
3691 * xmlTextReaderSetParserProp:
3692 * @reader: the xmlTextReaderPtr used
3693 * @prop: the xmlParserProperties to set
3694 * @value: usually 0 or 1 to (de)activate it
3695 *
3696 * Change the parser processing behaviour by changing some of its internal
3697 * properties. Note that some properties can only be changed before any
3698 * read has been done.
3699 *
3700 * Returns 0 if the call was successful, or -1 in case of error
3701 */
3702int
3703xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3704 xmlParserProperties p = (xmlParserProperties) prop;
3705 xmlParserCtxtPtr ctxt;
3706
3707 if ((reader == NULL) || (reader->ctxt == NULL))
3708 return(-1);
3709 ctxt = reader->ctxt;
3710
3711 switch (p) {
3712 case XML_PARSER_LOADDTD:
3713 if (value != 0) {
3714 if (ctxt->loadsubset == 0) {
3715 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3716 return(-1);
3717 ctxt->loadsubset = XML_DETECT_IDS;
3718 }
3719 } else {
3720 ctxt->loadsubset = 0;
3721 }
3722 return(0);
3723 case XML_PARSER_DEFAULTATTRS:
3724 if (value != 0) {
3725 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3726 } else {
3727 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3728 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3729 }
3730 return(0);
3731 case XML_PARSER_VALIDATE:
3732 if (value != 0) {
3733 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003734 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003735 } else {
3736 ctxt->validate = 0;
3737 }
3738 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003739 case XML_PARSER_SUBST_ENTITIES:
3740 if (value != 0) {
3741 ctxt->replaceEntities = 1;
3742 } else {
3743 ctxt->replaceEntities = 0;
3744 }
3745 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003746 }
3747 return(-1);
3748}
3749
3750/**
3751 * xmlTextReaderGetParserProp:
3752 * @reader: the xmlTextReaderPtr used
3753 * @prop: the xmlParserProperties to get
3754 *
3755 * Read the parser internal property.
3756 *
3757 * Returns the value, usually 0 or 1, or -1 in case of error.
3758 */
3759int
3760xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3761 xmlParserProperties p = (xmlParserProperties) prop;
3762 xmlParserCtxtPtr ctxt;
3763
3764 if ((reader == NULL) || (reader->ctxt == NULL))
3765 return(-1);
3766 ctxt = reader->ctxt;
3767
3768 switch (p) {
3769 case XML_PARSER_LOADDTD:
3770 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3771 return(1);
3772 return(0);
3773 case XML_PARSER_DEFAULTATTRS:
3774 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3775 return(1);
3776 return(0);
3777 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003778 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003779 case XML_PARSER_SUBST_ENTITIES:
3780 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003781 }
3782 return(-1);
3783}
3784
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003785
Daniel Veillarde18fc182002-12-28 22:56:33 +00003786/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003787 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003788 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003789 *
3790 * Provide the line number of the current parsing point.
3791 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003792 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003793 */
3794int
3795xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3796{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003797 if ((reader == NULL) || (reader->ctxt == NULL) ||
3798 (reader->ctxt->input == NULL)) {
3799 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003800 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003801 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003802}
3803
3804/**
3805 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003806 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003807 *
3808 * Provide the column number of the current parsing point.
3809 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003810 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003811 */
3812int
3813xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3814{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003815 if ((reader == NULL) || (reader->ctxt == NULL) ||
3816 (reader->ctxt->input == NULL)) {
3817 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003818 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003819 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003820}
3821
3822/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003823 * xmlTextReaderCurrentNode:
3824 * @reader: the xmlTextReaderPtr used
3825 *
3826 * Hacking interface allowing to get the xmlNodePtr correponding to the
3827 * current node being accessed by the xmlTextReader. This is dangerous
3828 * because the underlying node may be destroyed on the next Reads.
3829 *
3830 * Returns the xmlNodePtr or NULL in case of error.
3831 */
3832xmlNodePtr
3833xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3834 if (reader == NULL)
3835 return(NULL);
3836
3837 if (reader->curnode != NULL)
3838 return(reader->curnode);
3839 return(reader->node);
3840}
3841
3842/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003843 * xmlTextReaderPreserve:
3844 * @reader: the xmlTextReaderPtr used
3845 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003846 * This tells the XML Reader to preserve the current node.
3847 * The caller must also use xmlTextReaderCurrentDoc() to
3848 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003849 *
3850 * Returns the xmlNodePtr or NULL in case of error.
3851 */
3852xmlNodePtr
3853xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3854 xmlNodePtr cur, parent;
3855
3856 if (reader == NULL)
3857 return(NULL);
3858
3859 if (reader->curnode != NULL)
3860 cur = reader->curnode;
3861 else
3862 cur = reader->node;
3863 if (cur == NULL)
3864 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003865
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003866 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003867 cur->extra |= NODE_IS_PRESERVED;
3868 cur->extra |= NODE_IS_SPRESERVED;
3869 }
3870 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003871
3872 parent = cur->parent;;
3873 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003874 if (parent->type == XML_ELEMENT_NODE)
3875 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003876 parent = parent->parent;
3877 }
3878 return(cur);
3879}
3880
Daniel Veillard1e906612003-12-05 14:57:46 +00003881#ifdef LIBXML_PATTERN_ENABLED
3882/**
3883 * xmlTextReaderPreservePattern:
3884 * @reader: the xmlTextReaderPtr used
3885 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003886 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003887 *
3888 * This tells the XML Reader to preserve all nodes matched by the
3889 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3890 * keep an handle on the resulting document once parsing has finished
3891 *
3892 * Returns a positive number in case of success and -1 in case of error
3893 */
3894int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003895xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3896 const xmlChar **namespaces)
3897{
Daniel Veillard1e906612003-12-05 14:57:46 +00003898 xmlPatternPtr comp;
3899
3900 if ((reader == NULL) || (pattern == NULL))
3901 return(-1);
3902
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003903 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003904 if (comp == NULL)
3905 return(-1);
3906
3907 if (reader->patternMax <= 0) {
3908 reader->patternMax = 4;
3909 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3910 sizeof(reader->patternTab[0]));
3911 if (reader->patternTab == NULL) {
3912 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3913 return (-1);
3914 }
3915 }
3916 if (reader->patternNr >= reader->patternMax) {
3917 xmlPatternPtr *tmp;
3918 reader->patternMax *= 2;
3919 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3920 reader->patternMax *
3921 sizeof(reader->patternTab[0]));
3922 if (tmp == NULL) {
3923 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3924 reader->patternMax /= 2;
3925 return (-1);
3926 }
3927 reader->patternTab = tmp;
3928 }
3929 reader->patternTab[reader->patternNr] = comp;
3930 return(reader->patternNr++);
3931}
3932#endif
3933
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003934/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003935 * xmlTextReaderCurrentDoc:
3936 * @reader: the xmlTextReaderPtr used
3937 *
3938 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003939 * current document being accessed by the xmlTextReader.
3940 * NOTE: as a result of this call, the reader will not destroy the
3941 * associated XML document and calling xmlFreeDoc() on the result
3942 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003943 *
3944 * Returns the xmlDocPtr or NULL in case of error.
3945 */
3946xmlDocPtr
3947xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003948 if (reader == NULL)
3949 return(NULL);
3950 if (reader->doc != NULL)
3951 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003952 if ((reader == NULL) || (reader->ctxt == NULL) ||
3953 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003954 return(NULL);
3955
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003956 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003957 return(reader->ctxt->myDoc);
3958}
3959
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003960#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003961
3962static char *
3963xmlTextReaderBuildMessage(const char *msg, va_list ap);
3964
Daniel Veillardffa3c742005-07-21 13:24:09 +00003965static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003966xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3967
Daniel Veillardffa3c742005-07-21 13:24:09 +00003968static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003969xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3970
Daniel Veillardffa3c742005-07-21 13:24:09 +00003971static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003972{
3973 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3974 char * str;
3975 va_list ap;
3976
3977 va_start(ap,msg);
3978 str = xmlTextReaderBuildMessage(msg,ap);
3979 if (!reader->errorFunc) {
3980 xmlTextReaderValidityError(ctx, "%s", str);
3981 } else {
3982 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3983 }
3984 if (str != NULL)
3985 xmlFree(str);
3986 va_end(ap);
3987}
3988
Daniel Veillardffa3c742005-07-21 13:24:09 +00003989static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003990{
3991 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3992 char * str;
3993 va_list ap;
3994
3995 va_start(ap,msg);
3996 str = xmlTextReaderBuildMessage(msg,ap);
3997 if (!reader->errorFunc) {
3998 xmlTextReaderValidityWarning(ctx, "%s", str);
3999 } else {
4000 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
4001 }
4002 if (str != NULL)
4003 xmlFree(str);
4004 va_end(ap);
4005}
4006
4007static void
4008xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4009
4010static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4011{
4012 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4013
4014 if (reader->sErrorFunc) {
4015 reader->sErrorFunc(reader->errorFuncArg, error);
4016 } else {
4017 xmlTextReaderStructuredError(reader, error);
4018 }
4019}
4020
Daniel Veillardf4e55762003-04-15 23:32:22 +00004021/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004022 * xmlTextReaderRelaxNGSetSchema:
4023 * @reader: the xmlTextReaderPtr used
4024 * @schema: a precompiled RelaxNG schema
4025 *
4026 * Use RelaxNG to validate the document as it is processed.
4027 * Activation is only possible before the first Read().
4028 * if @schema is NULL, then RelaxNG validation is desactivated.
4029 @ The @schema should not be freed until the reader is deallocated
4030 * or its use has been deactivated.
4031 *
4032 * Returns 0 in case the RelaxNG validation could be (des)activated and
4033 * -1 in case of error.
4034 */
4035int
4036xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004037 if (reader == NULL)
4038 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004039 if (schema == NULL) {
4040 if (reader->rngSchemas != NULL) {
4041 xmlRelaxNGFree(reader->rngSchemas);
4042 reader->rngSchemas = NULL;
4043 }
4044 if (reader->rngValidCtxt != NULL) {
4045 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4046 reader->rngValidCtxt = NULL;
4047 }
4048 return(0);
4049 }
4050 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4051 return(-1);
4052 if (reader->rngSchemas != NULL) {
4053 xmlRelaxNGFree(reader->rngSchemas);
4054 reader->rngSchemas = NULL;
4055 }
4056 if (reader->rngValidCtxt != NULL) {
4057 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4058 reader->rngValidCtxt = NULL;
4059 }
4060 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4061 if (reader->rngValidCtxt == NULL)
4062 return(-1);
4063 if (reader->errorFunc != NULL) {
4064 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004065 xmlTextReaderValidityErrorRelay,
4066 xmlTextReaderValidityWarningRelay,
4067 reader);
4068 }
4069 if (reader->sErrorFunc != NULL) {
4070 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4071 xmlTextReaderValidityStructuredRelay,
4072 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004073 }
4074 reader->rngValidErrors = 0;
4075 reader->rngFullNode = NULL;
4076 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4077 return(0);
4078}
4079
4080/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004081 * xmlTextReaderSetSchema:
4082 * @reader: the xmlTextReaderPtr used
4083 * @schema: a precompiled Schema schema
4084 *
4085 * Use XSD Schema to validate the document as it is processed.
4086 * Activation is only possible before the first Read().
4087 * if @schema is NULL, then Schema validation is desactivated.
4088 @ The @schema should not be freed until the reader is deallocated
4089 * or its use has been deactivated.
4090 *
4091 * Returns 0 in case the Schema validation could be (des)activated and
4092 * -1 in case of error.
4093 */
4094int
4095xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4096 if (reader == NULL)
4097 return(-1);
4098 if (schema == NULL) {
4099 if (reader->xsdPlug != NULL) {
4100 xmlSchemaSAXUnplug(reader->xsdPlug);
4101 reader->xsdPlug = NULL;
4102 }
4103 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004104 if (! reader->xsdPreserveCtxt)
4105 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4106 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004107 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004108 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004109 if (reader->xsdSchemas != NULL) {
4110 xmlSchemaFree(reader->xsdSchemas);
4111 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004112 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004113 return(0);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004114 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004115 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4116 return(-1);
4117 if (reader->xsdPlug != NULL) {
4118 xmlSchemaSAXUnplug(reader->xsdPlug);
4119 reader->xsdPlug = NULL;
4120 }
4121 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004122 if (! reader->xsdPreserveCtxt)
4123 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004124 reader->xsdValidCtxt = NULL;
4125 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004126 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004127 if (reader->xsdSchemas != NULL) {
4128 xmlSchemaFree(reader->xsdSchemas);
4129 reader->xsdSchemas = NULL;
4130 }
4131 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4132 if (reader->xsdValidCtxt == NULL) {
4133 xmlSchemaFree(reader->xsdSchemas);
4134 reader->xsdSchemas = NULL;
4135 return(-1);
4136 }
4137 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4138 &(reader->ctxt->sax),
4139 &(reader->ctxt->userData));
4140 if (reader->xsdPlug == NULL) {
4141 xmlSchemaFree(reader->xsdSchemas);
4142 reader->xsdSchemas = NULL;
4143 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4144 reader->xsdValidCtxt = NULL;
4145 return(-1);
4146 }
4147 if (reader->errorFunc != NULL) {
4148 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004149 xmlTextReaderValidityErrorRelay,
4150 xmlTextReaderValidityWarningRelay,
4151 reader);
4152 }
4153 if (reader->sErrorFunc != NULL) {
4154 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4155 xmlTextReaderValidityStructuredRelay,
4156 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004157 }
4158 reader->xsdValidErrors = 0;
4159 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4160 return(0);
4161}
4162
4163/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004164 * xmlTextReaderRelaxNGValidate:
4165 * @reader: the xmlTextReaderPtr used
4166 * @rng: the path to a RelaxNG schema or NULL
4167 *
4168 * Use RelaxNG to validate the document as it is processed.
4169 * Activation is only possible before the first Read().
4170 * if @rng is NULL, then RelaxNG validation is desactivated.
4171 *
4172 * Returns 0 in case the RelaxNG validation could be (des)activated and
4173 * -1 in case of error.
4174 */
4175int
4176xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4177 xmlRelaxNGParserCtxtPtr ctxt;
4178
4179 if (reader == NULL)
4180 return(-1);
4181
4182 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004183 if (reader->rngValidCtxt != NULL) {
4184 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4185 reader->rngValidCtxt = NULL;
4186 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004187 if (reader->rngSchemas != NULL) {
4188 xmlRelaxNGFree(reader->rngSchemas);
4189 reader->rngSchemas = NULL;
4190 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004191 return(0);
4192 }
4193 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4194 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004195 if (reader->rngSchemas != NULL) {
4196 xmlRelaxNGFree(reader->rngSchemas);
4197 reader->rngSchemas = NULL;
4198 }
4199 if (reader->rngValidCtxt != NULL) {
4200 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4201 reader->rngValidCtxt = NULL;
4202 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004203 ctxt = xmlRelaxNGNewParserCtxt(rng);
4204 if (reader->errorFunc != NULL) {
4205 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004206 xmlTextReaderValidityErrorRelay,
4207 xmlTextReaderValidityWarningRelay,
4208 reader);
4209 }
4210 if (reader->sErrorFunc != NULL) {
4211 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4212 xmlTextReaderValidityStructuredRelay,
4213 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004214 }
4215 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4216 xmlRelaxNGFreeParserCtxt(ctxt);
4217 if (reader->rngSchemas == NULL)
4218 return(-1);
4219 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004220 if (reader->rngValidCtxt == NULL) {
4221 xmlRelaxNGFree(reader->rngSchemas);
4222 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004223 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004224 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004225 if (reader->errorFunc != NULL) {
4226 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004227 xmlTextReaderValidityErrorRelay,
4228 xmlTextReaderValidityWarningRelay,
4229 reader);
4230 }
4231 if (reader->sErrorFunc != NULL) {
4232 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4233 xmlTextReaderValidityStructuredRelay,
4234 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004235 }
4236 reader->rngValidErrors = 0;
4237 reader->rngFullNode = NULL;
4238 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4239 return(0);
4240}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004241
4242/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004243 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004244 * @reader: the xmlTextReaderPtr used
4245 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004246 * @ctxt: the XML Schema validation context or NULL
4247 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004248 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004249 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004250 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004251 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004252 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004253 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004254 * -1 in case of error.
4255 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004256static int
4257xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4258 const char *xsd,
4259 xmlSchemaValidCtxtPtr ctxt,
4260 int options ATTRIBUTE_UNUSED)
4261{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004262 if (reader == NULL)
4263 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004264
4265 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004266 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004267
4268 if (((xsd != NULL) || (ctxt != NULL)) &&
4269 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4270 (reader->ctxt == NULL)))
4271 return(-1);
4272
4273 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004274 if (reader->xsdPlug != NULL) {
4275 xmlSchemaSAXUnplug(reader->xsdPlug);
4276 reader->xsdPlug = NULL;
4277 }
4278 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004279 if (! reader->xsdPreserveCtxt)
4280 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004281 reader->xsdValidCtxt = NULL;
4282 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004283 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004284 if (reader->xsdSchemas != NULL) {
4285 xmlSchemaFree(reader->xsdSchemas);
4286 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004287 }
4288
4289 if ((xsd == NULL) && (ctxt == NULL)) {
4290 /* We just want to deactivate the validation, so get out. */
4291 return(0);
4292 }
4293
4294 if (xsd != NULL) {
4295 xmlSchemaParserCtxtPtr pctxt;
4296 /* Parse the schema and create validation environment. */
4297 pctxt = xmlSchemaNewParserCtxt(xsd);
4298 if (reader->errorFunc != NULL) {
4299 xmlSchemaSetParserErrors(pctxt,
4300 xmlTextReaderValidityErrorRelay,
4301 xmlTextReaderValidityWarningRelay,
4302 reader);
4303 }
4304 reader->xsdSchemas = xmlSchemaParse(pctxt);
4305 xmlSchemaFreeParserCtxt(pctxt);
4306 if (reader->xsdSchemas == NULL)
4307 return(-1);
4308 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4309 if (reader->xsdValidCtxt == NULL) {
4310 xmlSchemaFree(reader->xsdSchemas);
4311 reader->xsdSchemas = NULL;
4312 return(-1);
4313 }
4314 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4315 &(reader->ctxt->sax),
4316 &(reader->ctxt->userData));
4317 if (reader->xsdPlug == NULL) {
4318 xmlSchemaFree(reader->xsdSchemas);
4319 reader->xsdSchemas = NULL;
4320 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4321 reader->xsdValidCtxt = NULL;
4322 return(-1);
4323 }
4324 } else {
4325 /* Use the given validation context. */
4326 reader->xsdValidCtxt = ctxt;
4327 reader->xsdPreserveCtxt = 1;
4328 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4329 &(reader->ctxt->sax),
4330 &(reader->ctxt->userData));
4331 if (reader->xsdPlug == NULL) {
4332 reader->xsdValidCtxt = NULL;
4333 reader->xsdPreserveCtxt = 0;
4334 return(-1);
4335 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004336 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004337 /*
4338 * Redirect the validation context's error channels to use
4339 * the reader channels.
4340 * TODO: In case the user provides the validation context we
4341 * could make this redirection optional.
4342 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004343 if (reader->errorFunc != NULL) {
4344 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004345 xmlTextReaderValidityErrorRelay,
4346 xmlTextReaderValidityWarningRelay,
4347 reader);
4348 }
4349 if (reader->sErrorFunc != NULL) {
4350 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4351 xmlTextReaderValidityStructuredRelay,
4352 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004353 }
4354 reader->xsdValidErrors = 0;
4355 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4356 return(0);
4357}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004358
4359/**
4360 * xmlTextReaderSchemaValidateCtxt:
4361 * @reader: the xmlTextReaderPtr used
4362 * @ctxt: the XML Schema validation context or NULL
4363 * @options: options (not used yet)
4364 *
4365 * Use W3C XSD schema context to validate the document as it is processed.
4366 * Activation is only possible before the first Read().
4367 * If @ctxt is NULL, then XML Schema validation is deactivated.
4368 *
4369 * Returns 0 in case the schemas validation could be (de)activated and
4370 * -1 in case of error.
4371 */
4372int
4373xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4374 xmlSchemaValidCtxtPtr ctxt,
4375 int options)
4376{
4377 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4378}
4379
4380/**
4381 * xmlTextReaderSchemaValidate:
4382 * @reader: the xmlTextReaderPtr used
4383 * @xsd: the path to a W3C XSD schema or NULL
4384 *
4385 * Use W3C XSD schema to validate the document as it is processed.
4386 * Activation is only possible before the first Read().
4387 * If @xsd is NULL, then XML Schema validation is deactivated.
4388 *
4389 * Returns 0 in case the schemas validation could be (de)activated and
4390 * -1 in case of error.
4391 */
4392int
4393xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4394{
4395 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4396}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004397#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004398
Daniel Veillarde2811272004-10-19 09:04:23 +00004399/**
4400 * xmlTextReaderIsNamespaceDecl:
4401 * @reader: the xmlTextReaderPtr used
4402 *
4403 * Determine whether the current node is a namespace declaration
4404 * rather than a regular attribute.
4405 *
4406 * Returns 1 if the current node is a namespace declaration, 0 if it
4407 * is a regular attribute or other type of node, or -1 in case of
4408 * error.
4409 */
4410int
4411xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4412 xmlNodePtr node;
4413 if (reader == NULL)
4414 return(-1);
4415 if (reader->node == NULL)
4416 return(-1);
4417 if (reader->curnode != NULL)
4418 node = reader->curnode;
4419 else
4420 node = reader->node;
4421
4422 if (XML_NAMESPACE_DECL == node->type)
4423 return(1);
4424 else
4425 return(0);
4426}
4427
4428/**
4429 * xmlTextReaderConstXmlVersion:
4430 * @reader: the xmlTextReaderPtr used
4431 *
4432 * Determine the XML version of the document being read.
4433 *
4434 * Returns a string containing the XML version of the document or NULL
4435 * in case of error. The string is deallocated with the reader.
4436 */
4437const xmlChar *
4438xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4439 xmlDocPtr doc = NULL;
4440 if (reader == NULL)
4441 return(NULL);
4442 if (reader->doc != NULL)
4443 doc = reader->doc;
4444 else if (reader->ctxt != NULL)
4445 doc = reader->ctxt->myDoc;
4446 if (doc == NULL)
4447 return(NULL);
4448
4449 if (doc->version == NULL)
4450 return(NULL);
4451 else
4452 return(CONSTSTR(doc->version));
4453}
4454
4455/**
4456 * xmlTextReaderStandalone:
4457 * @reader: the xmlTextReaderPtr used
4458 *
4459 * Determine the standalone status of the document being read.
4460 *
4461 * Returns 1 if the document was declared to be standalone, 0 if it
4462 * was declared to be not standalone, or -1 if the document did not
4463 * specify its standalone status or in case of error.
4464 */
4465int
4466xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4467 xmlDocPtr doc = NULL;
4468 if (reader == NULL)
4469 return(-1);
4470 if (reader->doc != NULL)
4471 doc = reader->doc;
4472 else if (reader->ctxt != NULL)
4473 doc = reader->ctxt->myDoc;
4474 if (doc == NULL)
4475 return(-1);
4476
4477 return(doc->standalone);
4478}
4479
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004480/************************************************************************
4481 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004482 * Error Handling Extensions *
4483 * *
4484 ************************************************************************/
4485
4486/* helper to build a xmlMalloc'ed string from a format and va_list */
4487static char *
4488xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4489 int size;
4490 int chars;
4491 char *larger;
4492 char *str;
4493
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004494 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004495 if (str == NULL) {
4496 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4497 return NULL;
4498 }
4499
4500 size = 150;
4501
4502 while (1) {
4503 chars = vsnprintf(str, size, msg, ap);
4504 if ((chars > -1) && (chars < size))
4505 break;
4506 if (chars > -1)
4507 size += chars + 1;
4508 else
4509 size += 100;
4510 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4511 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4512 xmlFree(str);
4513 return NULL;
4514 }
4515 str = larger;
4516 }
4517
4518 return str;
4519}
4520
Daniel Veillard417be3a2003-01-20 21:26:34 +00004521/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004522 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004523 * @locator: the xmlTextReaderLocatorPtr used
4524 *
4525 * Obtain the line number for the given locator.
4526 *
4527 * Returns the line number or -1 in case of error.
4528 */
4529int
4530xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4531 /* we know that locator is a xmlParserCtxtPtr */
4532 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4533 int ret = -1;
4534
Daniel Veillardce682bc2004-11-05 17:22:25 +00004535 if (locator == NULL)
4536 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004537 if (ctx->node != NULL) {
4538 ret = xmlGetLineNo(ctx->node);
4539 }
4540 else {
4541 /* inspired from error.c */
4542 xmlParserInputPtr input;
4543 input = ctx->input;
4544 if ((input->filename == NULL) && (ctx->inputNr > 1))
4545 input = ctx->inputTab[ctx->inputNr - 2];
4546 if (input != NULL) {
4547 ret = input->line;
4548 }
4549 else {
4550 ret = -1;
4551 }
4552 }
4553
4554 return ret;
4555}
4556
4557/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004558 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004559 * @locator: the xmlTextReaderLocatorPtr used
4560 *
4561 * Obtain the base URI for the given locator.
4562 *
4563 * Returns the base URI or NULL in case of error.
4564 */
4565xmlChar *
4566xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4567 /* we know that locator is a xmlParserCtxtPtr */
4568 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4569 xmlChar *ret = NULL;
4570
Daniel Veillardce682bc2004-11-05 17:22:25 +00004571 if (locator == NULL)
4572 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004573 if (ctx->node != NULL) {
4574 ret = xmlNodeGetBase(NULL,ctx->node);
4575 }
4576 else {
4577 /* inspired from error.c */
4578 xmlParserInputPtr input;
4579 input = ctx->input;
4580 if ((input->filename == NULL) && (ctx->inputNr > 1))
4581 input = ctx->inputTab[ctx->inputNr - 2];
4582 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004583 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004584 }
4585 else {
4586 ret = NULL;
4587 }
4588 }
4589
4590 return ret;
4591}
4592
Daniel Veillard26f70262003-01-16 22:45:08 +00004593static void
William M. Brack899e64a2003-09-26 18:03:42 +00004594xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004595 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4596 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4597
William M. Bracka3215c72004-07-31 16:24:01 +00004598 if (str != NULL) {
4599 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004600 reader->errorFunc(reader->errorFuncArg,
4601 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004602 severity,
4603 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004604 xmlFree(str);
4605 }
4606}
4607
4608static void
William M. Brack93d004f2004-02-03 00:14:10 +00004609xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4610 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4611 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4612
4613 if (error && reader->sErrorFunc) {
4614 reader->sErrorFunc(reader->errorFuncArg,
4615 (xmlErrorPtr) error);
4616 }
4617}
4618
Daniel Veillardffa3c742005-07-21 13:24:09 +00004619static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004620xmlTextReaderError(void *ctxt, const char *msg, ...) {
4621 va_list ap;
4622
4623 va_start(ap,msg);
4624 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004625 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004626 xmlTextReaderBuildMessage(msg,ap));
4627 va_end(ap);
4628
4629}
4630
Daniel Veillardffa3c742005-07-21 13:24:09 +00004631static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004632xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4633 va_list ap;
4634
4635 va_start(ap,msg);
4636 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004637 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004638 xmlTextReaderBuildMessage(msg,ap));
4639 va_end(ap);
4640}
4641
Daniel Veillardffa3c742005-07-21 13:24:09 +00004642static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004643xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4644 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004645 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004646
Daniel Veillard417be3a2003-01-20 21:26:34 +00004647 if ((len > 1) && (msg[len - 2] != ':')) {
4648 /*
4649 * some callbacks only report locator information:
4650 * skip them (mimicking behaviour in error.c)
4651 */
4652 va_start(ap,msg);
4653 xmlTextReaderGenericError(ctxt,
4654 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4655 xmlTextReaderBuildMessage(msg,ap));
4656 va_end(ap);
4657 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004658}
4659
Daniel Veillardffa3c742005-07-21 13:24:09 +00004660static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004661xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4662 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004663 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004664
Daniel Veillard417be3a2003-01-20 21:26:34 +00004665 if ((len != 0) && (msg[len - 1] != ':')) {
4666 /*
4667 * some callbacks only report locator information:
4668 * skip them (mimicking behaviour in error.c)
4669 */
4670 va_start(ap,msg);
4671 xmlTextReaderGenericError(ctxt,
4672 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4673 xmlTextReaderBuildMessage(msg,ap));
4674 va_end(ap);
4675 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004676}
4677
4678/**
4679 * xmlTextReaderSetErrorHandler:
4680 * @reader: the xmlTextReaderPtr used
4681 * @f: the callback function to call on error and warnings
4682 * @arg: a user argument to pass to the callback function
4683 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004684 * Register a callback function that will be called on error and warnings.
4685 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004686 * If @f is NULL, the default error and warning handlers are restored.
4687 */
4688void
4689xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4690 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004691 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004692 if (f != NULL) {
4693 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004694 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004695 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4696 reader->ctxt->sax->warning = xmlTextReaderWarning;
4697 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4698 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004699 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004700 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004701#ifdef LIBXML_SCHEMAS_ENABLED
4702 if (reader->rngValidCtxt) {
4703 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4704 xmlTextReaderValidityErrorRelay,
4705 xmlTextReaderValidityWarningRelay,
4706 reader);
4707 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4708 }
4709 if (reader->xsdValidCtxt) {
4710 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4711 xmlTextReaderValidityErrorRelay,
4712 xmlTextReaderValidityWarningRelay,
4713 reader);
4714 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4715 }
4716#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004717 }
4718 else {
4719 /* restore defaults */
4720 reader->ctxt->sax->error = xmlParserError;
4721 reader->ctxt->vctxt.error = xmlParserValidityError;
4722 reader->ctxt->sax->warning = xmlParserWarning;
4723 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4724 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004725 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004726 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004727#ifdef LIBXML_SCHEMAS_ENABLED
4728 if (reader->rngValidCtxt) {
4729 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4730 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4731 }
4732 if (reader->xsdValidCtxt) {
4733 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4734 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4735 }
4736#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004737 }
4738}
4739
Daniel Veillard417be3a2003-01-20 21:26:34 +00004740/**
William M. Brack93d004f2004-02-03 00:14:10 +00004741* xmlTextReaderSetStructuredErrorHandler:
4742 * @reader: the xmlTextReaderPtr used
4743 * @f: the callback function to call on error and warnings
4744 * @arg: a user argument to pass to the callback function
4745 *
4746 * Register a callback function that will be called on error and warnings.
4747 *
4748 * If @f is NULL, the default error and warning handlers are restored.
4749 */
4750void
4751xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4752 xmlStructuredErrorFunc f,
4753 void *arg) {
4754 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004755 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004756 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4757 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4758 reader->ctxt->sax->warning = xmlTextReaderWarning;
4759 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4760 reader->sErrorFunc = f;
4761 reader->errorFunc = NULL;
4762 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004763#ifdef LIBXML_SCHEMAS_ENABLED
4764 if (reader->rngValidCtxt) {
4765 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4766 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4767 xmlTextReaderValidityStructuredRelay,
4768 reader);
4769 }
4770 if (reader->xsdValidCtxt) {
4771 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4772 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4773 xmlTextReaderValidityStructuredRelay,
4774 reader);
4775 }
4776#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004777 }
4778 else {
4779 /* restore defaults */
4780 reader->ctxt->sax->error = xmlParserError;
4781 reader->ctxt->sax->serror = NULL;
4782 reader->ctxt->vctxt.error = xmlParserValidityError;
4783 reader->ctxt->sax->warning = xmlParserWarning;
4784 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4785 reader->errorFunc = NULL;
4786 reader->sErrorFunc = NULL;
4787 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004788#ifdef LIBXML_SCHEMAS_ENABLED
4789 if (reader->rngValidCtxt) {
4790 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4791 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4792 }
4793 if (reader->xsdValidCtxt) {
4794 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4795 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4796 }
4797#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004798 }
4799}
4800
4801/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004802 * xmlTextReaderIsValid:
4803 * @reader: the xmlTextReaderPtr used
4804 *
4805 * Retrieve the validity status from the parser context
4806 *
4807 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4808 */
4809int
4810xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004811 if (reader == NULL) return(-1);
4812#ifdef LIBXML_SCHEMAS_ENABLED
4813 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4814 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004815 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4816 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004817#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004818 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004819 return(reader->ctxt->valid);
4820 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004821}
4822
4823/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004824 * xmlTextReaderGetErrorHandler:
4825 * @reader: the xmlTextReaderPtr used
4826 * @f: the callback function or NULL is no callback has been registered
4827 * @arg: a user argument
4828 *
4829 * Retrieve the error callback function and user argument.
4830 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004831void
4832xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4833 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004834 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004835 if (f != NULL) *f = reader->errorFunc;
4836 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004837}
4838
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004839
4840/************************************************************************
4841 * *
4842 * New set (2.6.0) of simpler and more flexible APIs *
4843 * *
4844 ************************************************************************/
4845
4846/**
4847 * xmlTextReaderSetup:
4848 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00004849 * @input: xmlParserInputBufferPtr used to feed the reader, will
4850 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004851 * @URL: the base URL to use for the document
4852 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004853 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004854 *
4855 * Setup an XML reader with new options
4856 *
4857 * Returns 0 in case of success and -1 in case of error.
4858 */
Aleksey Sanind8377642007-01-03 23:13:12 +00004859int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004860xmlTextReaderSetup(xmlTextReaderPtr reader,
4861 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004862 const char *encoding, int options)
4863{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004864 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004865 return (-1);
4866
Daniel Veillard8874b942005-08-25 13:19:21 +00004867 /*
4868 * we force the generation of compact text nodes on the reader
4869 * since usr applications should never modify the tree
4870 */
4871 options |= XML_PARSE_COMPACT;
4872
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004873 reader->doc = NULL;
4874 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004875 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004876 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004877 if ((input != NULL) && (reader->input != NULL) &&
4878 (reader->allocs & XML_TEXTREADER_INPUT)) {
4879 xmlFreeParserInputBuffer(reader->input);
4880 reader->input = NULL;
4881 reader->allocs -= XML_TEXTREADER_INPUT;
4882 }
4883 if (input != NULL) {
4884 reader->input = input;
4885 reader->allocs |= XML_TEXTREADER_INPUT;
4886 }
4887 if (reader->buffer == NULL)
4888 reader->buffer = xmlBufferCreateSize(100);
4889 if (reader->buffer == NULL) {
4890 xmlGenericError(xmlGenericErrorContext,
4891 "xmlTextReaderSetup : malloc failed\n");
4892 return (-1);
4893 }
4894 if (reader->sax == NULL)
4895 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4896 if (reader->sax == NULL) {
4897 xmlGenericError(xmlGenericErrorContext,
4898 "xmlTextReaderSetup : malloc failed\n");
4899 return (-1);
4900 }
4901 xmlSAXVersion(reader->sax, 2);
4902 reader->startElement = reader->sax->startElement;
4903 reader->sax->startElement = xmlTextReaderStartElement;
4904 reader->endElement = reader->sax->endElement;
4905 reader->sax->endElement = xmlTextReaderEndElement;
4906#ifdef LIBXML_SAX1_ENABLED
4907 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4908#endif /* LIBXML_SAX1_ENABLED */
4909 reader->startElementNs = reader->sax->startElementNs;
4910 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4911 reader->endElementNs = reader->sax->endElementNs;
4912 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4913#ifdef LIBXML_SAX1_ENABLED
4914 } else {
4915 reader->startElementNs = NULL;
4916 reader->endElementNs = NULL;
4917 }
4918#endif /* LIBXML_SAX1_ENABLED */
4919 reader->characters = reader->sax->characters;
4920 reader->sax->characters = xmlTextReaderCharacters;
4921 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4922 reader->cdataBlock = reader->sax->cdataBlock;
4923 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4924
4925 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4926 reader->node = NULL;
4927 reader->curnode = NULL;
4928 if (input != NULL) {
4929 if (reader->input->buffer->use < 4) {
4930 xmlParserInputBufferRead(input, 4);
4931 }
4932 if (reader->ctxt == NULL) {
4933 if (reader->input->buffer->use >= 4) {
4934 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4935 (const char *) reader->input->buffer->content, 4, URL);
4936 reader->base = 0;
4937 reader->cur = 4;
4938 } else {
4939 reader->ctxt =
4940 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4941 reader->base = 0;
4942 reader->cur = 0;
4943 }
4944 } else {
4945 xmlParserInputPtr inputStream;
4946 xmlParserInputBufferPtr buf;
4947 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4948
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004949 xmlCtxtReset(reader->ctxt);
4950 buf = xmlAllocParserInputBuffer(enc);
4951 if (buf == NULL) return(-1);
4952 inputStream = xmlNewInputStream(reader->ctxt);
4953 if (inputStream == NULL) {
4954 xmlFreeParserInputBuffer(buf);
4955 return(-1);
4956 }
4957
4958 if (URL == NULL)
4959 inputStream->filename = NULL;
4960 else
4961 inputStream->filename = (char *)
4962 xmlCanonicPath((const xmlChar *) URL);
4963 inputStream->buf = buf;
4964 inputStream->base = inputStream->buf->buffer->content;
4965 inputStream->cur = inputStream->buf->buffer->content;
4966 inputStream->end =
4967 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4968
4969 inputPush(reader->ctxt, inputStream);
4970 reader->cur = 0;
4971 }
4972 if (reader->ctxt == NULL) {
4973 xmlGenericError(xmlGenericErrorContext,
4974 "xmlTextReaderSetup : malloc failed\n");
4975 return (-1);
4976 }
4977 }
4978 if (reader->dict != NULL) {
4979 if (reader->ctxt->dict != NULL) {
4980 if (reader->dict != reader->ctxt->dict) {
4981 xmlDictFree(reader->dict);
4982 reader->dict = reader->ctxt->dict;
4983 }
4984 } else {
4985 reader->ctxt->dict = reader->dict;
4986 }
4987 } else {
4988 if (reader->ctxt->dict == NULL)
4989 reader->ctxt->dict = xmlDictCreate();
4990 reader->dict = reader->ctxt->dict;
4991 }
4992 reader->ctxt->_private = reader;
4993 reader->ctxt->linenumbers = 1;
4994 reader->ctxt->dictNames = 1;
4995 /*
4996 * use the parser dictionnary to allocate all elements and attributes names
4997 */
4998 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004999 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005000
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005001#ifdef LIBXML_XINCLUDE_ENABLED
5002 if (reader->xincctxt != NULL) {
5003 xmlXIncludeFreeContext(reader->xincctxt);
5004 reader->xincctxt = NULL;
5005 }
5006 if (options & XML_PARSE_XINCLUDE) {
5007 reader->xinclude = 1;
5008 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5009 options -= XML_PARSE_XINCLUDE;
5010 } else
5011 reader->xinclude = 0;
5012 reader->in_xinclude = 0;
5013#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005014#ifdef LIBXML_PATTERN_ENABLED
5015 if (reader->patternTab == NULL) {
5016 reader->patternNr = 0;
5017 reader->patternMax = 0;
5018 }
5019 while (reader->patternNr > 0) {
5020 reader->patternNr--;
5021 if (reader->patternTab[reader->patternNr] != NULL) {
5022 xmlFreePattern(reader->patternTab[reader->patternNr]);
5023 reader->patternTab[reader->patternNr] = NULL;
5024 }
5025 }
5026#endif
5027
Daniel Veillardc36965d2003-12-02 10:28:48 +00005028 if (options & XML_PARSE_DTDVALID)
5029 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5030
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005031 xmlCtxtUseOptions(reader->ctxt, options);
5032 if (encoding != NULL) {
5033 xmlCharEncodingHandlerPtr hdlr;
5034
5035 hdlr = xmlFindCharEncodingHandler(encoding);
5036 if (hdlr != NULL)
5037 xmlSwitchToEncoding(reader->ctxt, hdlr);
5038 }
5039 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5040 (reader->ctxt->input->filename == NULL))
5041 reader->ctxt->input->filename = (char *)
5042 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005043
5044 reader->doc = NULL;
5045
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005046 return (0);
5047}
5048
5049/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005050 * xmlTextReaderByteConsumed:
5051 * @reader: an XML reader
5052 *
5053 * This function provides the current index of the parser used
5054 * by the reader, relative to the start of the current entity.
5055 * This function actually just wraps a call to xmlBytesConsumed()
5056 * for the parser context associated with the reader.
5057 * See xmlBytesConsumed() for more information.
5058 *
5059 * Returns the index in bytes from the beginning of the entity or -1
5060 * in case the index could not be computed.
5061 */
5062long
5063xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5064 if ((reader == NULL) || (reader->ctxt == NULL))
5065 return(-1);
5066 return(xmlByteConsumed(reader->ctxt));
5067}
5068
5069
5070/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005071 * xmlReaderWalker:
5072 * @doc: a preparsed document
5073 *
5074 * Create an xmltextReader for a preparsed document.
5075 *
5076 * Returns the new reader or NULL in case of error.
5077 */
5078xmlTextReaderPtr
5079xmlReaderWalker(xmlDocPtr doc)
5080{
5081 xmlTextReaderPtr ret;
5082
5083 if (doc == NULL)
5084 return(NULL);
5085
5086 ret = xmlMalloc(sizeof(xmlTextReader));
5087 if (ret == NULL) {
5088 xmlGenericError(xmlGenericErrorContext,
5089 "xmlNewTextReader : malloc failed\n");
5090 return(NULL);
5091 }
5092 memset(ret, 0, sizeof(xmlTextReader));
5093 ret->entNr = 0;
5094 ret->input = NULL;
5095 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5096 ret->node = NULL;
5097 ret->curnode = NULL;
5098 ret->base = 0;
5099 ret->cur = 0;
5100 ret->allocs = XML_TEXTREADER_CTXT;
5101 ret->doc = doc;
5102 ret->state = XML_TEXTREADER_START;
5103 ret->dict = xmlDictCreate();
5104 return(ret);
5105}
5106
5107/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005108 * xmlReaderForDoc:
5109 * @cur: a pointer to a zero terminated string
5110 * @URL: the base URL to use for the document
5111 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005112 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005113 *
5114 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005115 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005116 *
5117 * Returns the new reader or NULL in case of error.
5118 */
5119xmlTextReaderPtr
5120xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5121 int options)
5122{
5123 int len;
5124
5125 if (cur == NULL)
5126 return (NULL);
5127 len = xmlStrlen(cur);
5128
5129 return (xmlReaderForMemory
5130 ((const char *) cur, len, URL, encoding, options));
5131}
5132
5133/**
5134 * xmlReaderForFile:
5135 * @filename: a file or URL
5136 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005137 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005138 *
5139 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005140 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005141 *
5142 * Returns the new reader or NULL in case of error.
5143 */
5144xmlTextReaderPtr
5145xmlReaderForFile(const char *filename, const char *encoding, int options)
5146{
5147 xmlTextReaderPtr reader;
5148
5149 reader = xmlNewTextReaderFilename(filename);
5150 if (reader == NULL)
5151 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005152 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005153 return (reader);
5154}
5155
5156/**
5157 * xmlReaderForMemory:
5158 * @buffer: a pointer to a char array
5159 * @size: the size of the array
5160 * @URL: the base URL to use for the document
5161 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005162 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005163 *
5164 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005165 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005166 *
5167 * Returns the new reader or NULL in case of error.
5168 */
5169xmlTextReaderPtr
5170xmlReaderForMemory(const char *buffer, int size, const char *URL,
5171 const char *encoding, int options)
5172{
5173 xmlTextReaderPtr reader;
5174 xmlParserInputBufferPtr buf;
5175
Daniel Veillard21924522004-02-19 16:37:07 +00005176 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005177 XML_CHAR_ENCODING_NONE);
5178 if (buf == NULL) {
5179 return (NULL);
5180 }
5181 reader = xmlNewTextReader(buf, URL);
5182 if (reader == NULL) {
5183 xmlFreeParserInputBuffer(buf);
5184 return (NULL);
5185 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005186 reader->allocs |= XML_TEXTREADER_INPUT;
5187 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005188 return (reader);
5189}
5190
5191/**
5192 * xmlReaderForFd:
5193 * @fd: an open file descriptor
5194 * @URL: the base URL to use for the document
5195 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005196 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005197 *
5198 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005199 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005200 * NOTE that the file descriptor will not be closed when the
5201 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005202 *
5203 * Returns the new reader or NULL in case of error.
5204 */
5205xmlTextReaderPtr
5206xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5207{
5208 xmlTextReaderPtr reader;
5209 xmlParserInputBufferPtr input;
5210
5211 if (fd < 0)
5212 return (NULL);
5213
5214 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5215 if (input == NULL)
5216 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005217 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005218 reader = xmlNewTextReader(input, URL);
5219 if (reader == NULL) {
5220 xmlFreeParserInputBuffer(input);
5221 return (NULL);
5222 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005223 reader->allocs |= XML_TEXTREADER_INPUT;
5224 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005225 return (reader);
5226}
5227
5228/**
5229 * xmlReaderForIO:
5230 * @ioread: an I/O read function
5231 * @ioclose: an I/O close function
5232 * @ioctx: an I/O handler
5233 * @URL: the base URL to use for the document
5234 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005235 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005236 *
5237 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005238 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005239 *
5240 * Returns the new reader or NULL in case of error.
5241 */
5242xmlTextReaderPtr
5243xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5244 void *ioctx, const char *URL, const char *encoding,
5245 int options)
5246{
5247 xmlTextReaderPtr reader;
5248 xmlParserInputBufferPtr input;
5249
5250 if (ioread == NULL)
5251 return (NULL);
5252
5253 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5254 XML_CHAR_ENCODING_NONE);
5255 if (input == NULL)
5256 return (NULL);
5257 reader = xmlNewTextReader(input, URL);
5258 if (reader == NULL) {
5259 xmlFreeParserInputBuffer(input);
5260 return (NULL);
5261 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005262 reader->allocs |= XML_TEXTREADER_INPUT;
5263 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005264 return (reader);
5265}
5266
5267/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005268 * xmlReaderNewWalker:
5269 * @reader: an XML reader
5270 * @doc: a preparsed document
5271 *
5272 * Setup an xmltextReader to parse a preparsed XML document.
5273 * This reuses the existing @reader xmlTextReader.
5274 *
5275 * Returns 0 in case of success and -1 in case of error
5276 */
5277int
5278xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5279{
5280 if (doc == NULL)
5281 return (-1);
5282 if (reader == NULL)
5283 return (-1);
5284
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005285 if (reader->input != NULL) {
5286 xmlFreeParserInputBuffer(reader->input);
5287 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005288 if (reader->ctxt != NULL) {
5289 xmlCtxtReset(reader->ctxt);
5290 }
5291
5292 reader->entNr = 0;
5293 reader->input = NULL;
5294 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5295 reader->node = NULL;
5296 reader->curnode = NULL;
5297 reader->base = 0;
5298 reader->cur = 0;
5299 reader->allocs = XML_TEXTREADER_CTXT;
5300 reader->doc = doc;
5301 reader->state = XML_TEXTREADER_START;
5302 if (reader->dict == NULL) {
5303 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5304 reader->dict = reader->ctxt->dict;
5305 else
5306 reader->dict = xmlDictCreate();
5307 }
5308 return(0);
5309}
5310
5311/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005312 * xmlReaderNewDoc:
5313 * @reader: an XML reader
5314 * @cur: a pointer to a zero terminated string
5315 * @URL: the base URL to use for the document
5316 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005317 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005318 *
5319 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005320 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005321 * This reuses the existing @reader xmlTextReader.
5322 *
5323 * Returns 0 in case of success and -1 in case of error
5324 */
5325int
5326xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5327 const char *URL, const char *encoding, int options)
5328{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005329
5330 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005331
5332 if (cur == NULL)
5333 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005334 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005335 return (-1);
5336
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005337 len = xmlStrlen(cur);
5338 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5339 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005340}
5341
5342/**
5343 * xmlReaderNewFile:
5344 * @reader: an XML reader
5345 * @filename: a file or URL
5346 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005347 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005348 *
5349 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005350 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005351 * This reuses the existing @reader xmlTextReader.
5352 *
5353 * Returns 0 in case of success and -1 in case of error
5354 */
5355int
5356xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5357 const char *encoding, int options)
5358{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005359 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005360
5361 if (filename == NULL)
5362 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005363 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005364 return (-1);
5365
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005366 input =
5367 xmlParserInputBufferCreateFilename(filename,
5368 XML_CHAR_ENCODING_NONE);
5369 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005370 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005371 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005372}
5373
5374/**
5375 * xmlReaderNewMemory:
5376 * @reader: an XML reader
5377 * @buffer: a pointer to a char array
5378 * @size: the size of the array
5379 * @URL: the base URL to use for the document
5380 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005381 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005382 *
5383 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005384 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005385 * This reuses the existing @reader xmlTextReader.
5386 *
5387 * Returns 0 in case of success and -1 in case of error
5388 */
5389int
5390xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5391 const char *URL, const char *encoding, int options)
5392{
5393 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005394
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005395 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005396 return (-1);
5397 if (buffer == NULL)
5398 return (-1);
5399
Daniel Veillard21924522004-02-19 16:37:07 +00005400 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005401 XML_CHAR_ENCODING_NONE);
5402 if (input == NULL) {
5403 return (-1);
5404 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005405 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005406}
5407
5408/**
5409 * xmlReaderNewFd:
5410 * @reader: an XML reader
5411 * @fd: an open file descriptor
5412 * @URL: the base URL to use for the document
5413 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005414 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005415 *
5416 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005417 * NOTE that the file descriptor will not be closed when the
5418 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005419 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005420 * This reuses the existing @reader xmlTextReader.
5421 *
5422 * Returns 0 in case of success and -1 in case of error
5423 */
5424int
5425xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5426 const char *URL, const char *encoding, int options)
5427{
5428 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005429
5430 if (fd < 0)
5431 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005432 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005433 return (-1);
5434
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005435 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5436 if (input == NULL)
5437 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005438 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005439 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005440}
5441
5442/**
5443 * xmlReaderNewIO:
5444 * @reader: an XML reader
5445 * @ioread: an I/O read function
5446 * @ioclose: an I/O close function
5447 * @ioctx: an I/O handler
5448 * @URL: the base URL to use for the document
5449 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005450 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005451 *
5452 * Setup an xmltextReader to parse an XML document from I/O functions
5453 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005454 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005455 * This reuses the existing @reader xmlTextReader.
5456 *
5457 * Returns 0 in case of success and -1 in case of error
5458 */
5459int
5460xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5461 xmlInputCloseCallback ioclose, void *ioctx,
5462 const char *URL, const char *encoding, int options)
5463{
5464 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005465
5466 if (ioread == NULL)
5467 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005468 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005469 return (-1);
5470
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005471 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5472 XML_CHAR_ENCODING_NONE);
5473 if (input == NULL)
5474 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005475 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005476}
Daniel Veillard26f70262003-01-16 22:45:08 +00005477/************************************************************************
5478 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005479 * Utilities *
5480 * *
5481 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005482#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005483/**
5484 * xmlBase64Decode:
5485 * @in: the input buffer
5486 * @inlen: the size of the input (in), the size read from it (out)
5487 * @to: the output buffer
5488 * @tolen: the size of the output (in), the size written to (out)
5489 *
5490 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005491 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005492 *
5493 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5494 * 2 if there wasn't enough space on the output or -1 in case of error.
5495 */
5496static int
5497xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5498 unsigned char *to, unsigned long *tolen) {
5499 unsigned long incur; /* current index in in[] */
5500 unsigned long inblk; /* last block index in in[] */
5501 unsigned long outcur; /* current index in out[] */
5502 unsigned long inmax; /* size of in[] */
5503 unsigned long outmax; /* size of out[] */
5504 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005505 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005506 int nbintmp; /* number of byte in intmp[] */
5507 int is_ignore; /* cur should be ignored */
5508 int is_end = 0; /* the end of the base64 was found */
5509 int retval = 1;
5510 int i;
5511
5512 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5513 return(-1);
5514
5515 incur = 0;
5516 inblk = 0;
5517 outcur = 0;
5518 inmax = *inlen;
5519 outmax = *tolen;
5520 nbintmp = 0;
5521
5522 while (1) {
5523 if (incur >= inmax)
5524 break;
5525 cur = in[incur++];
5526 is_ignore = 0;
5527 if ((cur >= 'A') && (cur <= 'Z'))
5528 cur = cur - 'A';
5529 else if ((cur >= 'a') && (cur <= 'z'))
5530 cur = cur - 'a' + 26;
5531 else if ((cur >= '0') && (cur <= '9'))
5532 cur = cur - '0' + 52;
5533 else if (cur == '+')
5534 cur = 62;
5535 else if (cur == '/')
5536 cur = 63;
5537 else if (cur == '.')
5538 cur = 0;
5539 else if (cur == '=') /*no op , end of the base64 stream */
5540 is_end = 1;
5541 else {
5542 is_ignore = 1;
5543 if (nbintmp == 0)
5544 inblk = incur;
5545 }
5546
5547 if (!is_ignore) {
5548 int nbouttmp = 3;
5549 int is_break = 0;
5550
5551 if (is_end) {
5552 if (nbintmp == 0)
5553 break;
5554 if ((nbintmp == 1) || (nbintmp == 2))
5555 nbouttmp = 1;
5556 else
5557 nbouttmp = 2;
5558 nbintmp = 3;
5559 is_break = 1;
5560 }
5561 intmp[nbintmp++] = cur;
5562 /*
5563 * if intmp is full, push the 4byte sequence as a 3 byte
5564 * sequence out
5565 */
5566 if (nbintmp == 4) {
5567 nbintmp = 0;
5568 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5569 outtmp[1] =
5570 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5571 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5572 if (outcur + 3 >= outmax) {
5573 retval = 2;
5574 break;
5575 }
5576
5577 for (i = 0; i < nbouttmp; i++)
5578 to[outcur++] = outtmp[i];
5579 inblk = incur;
5580 }
5581
5582 if (is_break) {
5583 retval = 0;
5584 break;
5585 }
5586 }
5587 }
5588
5589 *tolen = outcur;
5590 *inlen = inblk;
5591 return (retval);
5592}
5593
5594/*
5595 * Test routine for the xmlBase64Decode function
5596 */
5597#if 0
5598int main(int argc, char **argv) {
5599 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5600 char output[100];
5601 char output2[100];
5602 char output3[100];
5603 unsigned long inlen = strlen(input);
5604 unsigned long outlen = 100;
5605 int ret;
5606 unsigned long cons, tmp, tmp2, prod;
5607
5608 /*
5609 * Direct
5610 */
5611 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5612
5613 output[outlen] = 0;
5614 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5615
5616 /*
5617 * output chunking
5618 */
5619 cons = 0;
5620 prod = 0;
5621 while (cons < inlen) {
5622 tmp = 5;
5623 tmp2 = inlen - cons;
5624
5625 printf("%ld %ld\n", cons, prod);
5626 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5627 cons += tmp2;
5628 prod += tmp;
5629 printf("%ld %ld\n", cons, prod);
5630 }
5631 output2[outlen] = 0;
5632 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5633
5634 /*
5635 * input chunking
5636 */
5637 cons = 0;
5638 prod = 0;
5639 while (cons < inlen) {
5640 tmp = 100 - prod;
5641 tmp2 = inlen - cons;
5642 if (tmp2 > 5)
5643 tmp2 = 5;
5644
5645 printf("%ld %ld\n", cons, prod);
5646 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5647 cons += tmp2;
5648 prod += tmp;
5649 printf("%ld %ld\n", cons, prod);
5650 }
5651 output3[outlen] = 0;
5652 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5653 return(0);
5654
5655}
5656#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005657#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005658#define bottom_xmlreader
5659#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005660#endif /* LIBXML_READER_ENABLED */