blob: 737fdbced6d7112c0c70acc0b7786a743e591a10 [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
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000237 ID = xmlNodeListGetString(doc, attr->children, 1);
238 if (ID == NULL)
239 return(-1);
240 id = xmlHashLookup(table, ID);
241 xmlFree(ID);
242 if (id == NULL || id->attr != attr) {
243 return(-1);
244 }
245 id->name = attr->name;
246 id->attr = NULL;
247 return(0);
248}
249
250/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000251 * xmlTextReaderFreeProp:
252 * @reader: the xmlTextReaderPtr used
253 * @cur: the node
254 *
255 * Free a node.
256 */
257static void
258xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
259 xmlDictPtr dict;
260
261 dict = reader->ctxt->dict;
262 if (cur == NULL) return;
263
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000264 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
265 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
266
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000267 /* Check for ID removal -> leading to invalid references ! */
268 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
269 ((cur->parent->doc->intSubset != NULL) ||
270 (cur->parent->doc->extSubset != NULL))) {
271 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000272 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000273 }
274 if (cur->children != NULL)
275 xmlTextReaderFreeNodeList(reader, cur->children);
276
277 DICT_FREE(cur->name);
278 if ((reader != NULL) && (reader->ctxt != NULL) &&
279 (reader->ctxt->freeAttrsNr < 100)) {
280 cur->next = reader->ctxt->freeAttrs;
281 reader->ctxt->freeAttrs = cur;
282 reader->ctxt->freeAttrsNr++;
283 } else {
284 xmlFree(cur);
285 }
286}
287
288/**
289 * xmlTextReaderFreePropList:
290 * @reader: the xmlTextReaderPtr used
291 * @cur: the first property in the list
292 *
293 * Free a property and all its siblings, all the children are freed too.
294 */
295static void
296xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
297 xmlAttrPtr next;
298 if (cur == NULL) return;
299 while (cur != NULL) {
300 next = cur->next;
301 xmlTextReaderFreeProp(reader, cur);
302 cur = next;
303 }
304}
305
306/**
307 * xmlTextReaderFreeNodeList:
308 * @reader: the xmlTextReaderPtr used
309 * @cur: the first node in the list
310 *
311 * Free a node and all its siblings, this is a recursive behaviour, all
312 * the children are freed too.
313 */
314static void
315xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
316 xmlNodePtr next;
317 xmlDictPtr dict;
318
319 dict = reader->ctxt->dict;
320 if (cur == NULL) return;
321 if (cur->type == XML_NAMESPACE_DECL) {
322 xmlFreeNsList((xmlNsPtr) cur);
323 return;
324 }
325 if ((cur->type == XML_DOCUMENT_NODE) ||
326 (cur->type == XML_HTML_DOCUMENT_NODE)) {
327 xmlFreeDoc((xmlDocPtr) cur);
328 return;
329 }
330 while (cur != NULL) {
331 next = cur->next;
332 /* unroll to speed up freeing the document */
333 if (cur->type != XML_DTD_NODE) {
334
335 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000336 (cur->type != XML_ENTITY_REF_NODE)) {
337 if (cur->children->parent == cur)
338 xmlTextReaderFreeNodeList(reader, cur->children);
339 cur->children = NULL;
340 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000341
342 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
343 xmlDeregisterNodeDefaultValue(cur);
344
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000345 if (((cur->type == XML_ELEMENT_NODE) ||
346 (cur->type == XML_XINCLUDE_START) ||
347 (cur->type == XML_XINCLUDE_END)) &&
348 (cur->properties != NULL))
349 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000350 if ((cur->content != (xmlChar *) &(cur->properties)) &&
351 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000352 (cur->type != XML_XINCLUDE_START) &&
353 (cur->type != XML_XINCLUDE_END) &&
354 (cur->type != XML_ENTITY_REF_NODE)) {
355 DICT_FREE(cur->content);
356 }
357 if (((cur->type == XML_ELEMENT_NODE) ||
358 (cur->type == XML_XINCLUDE_START) ||
359 (cur->type == XML_XINCLUDE_END)) &&
360 (cur->nsDef != NULL))
361 xmlFreeNsList(cur->nsDef);
362
363 /*
364 * we don't free element names here they are interned now
365 */
366 if ((cur->type != XML_TEXT_NODE) &&
367 (cur->type != XML_COMMENT_NODE))
368 DICT_FREE(cur->name);
369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_TEXT_NODE)) &&
371 (reader != NULL) && (reader->ctxt != NULL) &&
372 (reader->ctxt->freeElemsNr < 100)) {
373 cur->next = reader->ctxt->freeElems;
374 reader->ctxt->freeElems = cur;
375 reader->ctxt->freeElemsNr++;
376 } else {
377 xmlFree(cur);
378 }
379 }
380 cur = next;
381 }
382}
383
384/**
385 * xmlTextReaderFreeNode:
386 * @reader: the xmlTextReaderPtr used
387 * @cur: the node
388 *
389 * Free a node, this is a recursive behaviour, all the children are freed too.
390 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
391 */
392static void
393xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
394 xmlDictPtr dict;
395
396 dict = reader->ctxt->dict;
397 if (cur->type == XML_DTD_NODE) {
398 xmlFreeDtd((xmlDtdPtr) cur);
399 return;
400 }
401 if (cur->type == XML_NAMESPACE_DECL) {
402 xmlFreeNs((xmlNsPtr) cur);
403 return;
404 }
405 if (cur->type == XML_ATTRIBUTE_NODE) {
406 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
407 return;
408 }
409
410 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000411 (cur->type != XML_ENTITY_REF_NODE)) {
412 if (cur->children->parent == cur)
413 xmlTextReaderFreeNodeList(reader, cur->children);
414 cur->children = NULL;
415 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000416
417 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
418 xmlDeregisterNodeDefaultValue(cur);
419
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000420 if (((cur->type == XML_ELEMENT_NODE) ||
421 (cur->type == XML_XINCLUDE_START) ||
422 (cur->type == XML_XINCLUDE_END)) &&
423 (cur->properties != NULL))
424 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000425 if ((cur->content != (xmlChar *) &(cur->properties)) &&
426 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000427 (cur->type != XML_XINCLUDE_START) &&
428 (cur->type != XML_XINCLUDE_END) &&
429 (cur->type != XML_ENTITY_REF_NODE)) {
430 DICT_FREE(cur->content);
431 }
432 if (((cur->type == XML_ELEMENT_NODE) ||
433 (cur->type == XML_XINCLUDE_START) ||
434 (cur->type == XML_XINCLUDE_END)) &&
435 (cur->nsDef != NULL))
436 xmlFreeNsList(cur->nsDef);
437
438 /*
439 * we don't free names here they are interned now
440 */
441 if ((cur->type != XML_TEXT_NODE) &&
442 (cur->type != XML_COMMENT_NODE))
443 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000444
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000445 if (((cur->type == XML_ELEMENT_NODE) ||
446 (cur->type == XML_TEXT_NODE)) &&
447 (reader != NULL) && (reader->ctxt != NULL) &&
448 (reader->ctxt->freeElemsNr < 100)) {
449 cur->next = reader->ctxt->freeElems;
450 reader->ctxt->freeElems = cur;
451 reader->ctxt->freeElemsNr++;
452 } else {
453 xmlFree(cur);
454 }
455}
456
457/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000458 * xmlTextReaderFreeIDTable:
459 * @table: An id table
460 *
461 * Deallocate the memory used by an ID hash table.
462 */
William M. Brack60f394e2003-11-16 06:25:42 +0000463static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000464xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
465 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
466}
467
468/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000469 * xmlTextReaderFreeDoc:
470 * @reader: the xmlTextReaderPtr used
471 * @cur: pointer to the document
472 *
473 * Free up all the structures used by a document, tree included.
474 */
475static void
476xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
477 xmlDtdPtr extSubset, intSubset;
478
479 if (cur == NULL) return;
480
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000481 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
482 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
483
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000484 /*
485 * Do this before freeing the children list to avoid ID lookups
486 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000487 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000488 cur->ids = NULL;
489 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
490 cur->refs = NULL;
491 extSubset = cur->extSubset;
492 intSubset = cur->intSubset;
493 if (intSubset == extSubset)
494 extSubset = NULL;
495 if (extSubset != NULL) {
496 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
497 cur->extSubset = NULL;
498 xmlFreeDtd(extSubset);
499 }
500 if (intSubset != NULL) {
501 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
502 cur->intSubset = NULL;
503 xmlFreeDtd(intSubset);
504 }
505
506 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
507
508 if (cur->version != NULL) xmlFree((char *) cur->version);
509 if (cur->name != NULL) xmlFree((char *) cur->name);
510 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
511 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
512 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000513 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000514
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000515 xmlFree(cur);
516}
517
518/************************************************************************
519 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000520 * The reader core parser *
521 * *
522 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000523#ifdef DEBUG_READER
524static void
525xmlTextReaderDebug(xmlTextReaderPtr reader) {
526 if ((reader == NULL) || (reader->ctxt == NULL)) {
527 fprintf(stderr, "xmlTextReader NULL\n");
528 return;
529 }
530 fprintf(stderr, "xmlTextReader: state %d depth %d ",
531 reader->state, reader->depth);
532 if (reader->node == NULL) {
533 fprintf(stderr, "node = NULL\n");
534 } else {
535 fprintf(stderr, "node %s\n", reader->node->name);
536 }
537 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
538 reader->base, reader->cur, reader->ctxt->nodeNr);
539 if (reader->input->buffer == NULL) {
540 fprintf(stderr, "buffer is NULL\n");
541 } else {
542#ifdef LIBXML_DEBUG_ENABLED
543 xmlDebugDumpString(stderr,
544 &reader->input->buffer->content[reader->cur]);
545#endif
546 fprintf(stderr, "\n");
547 }
548}
549#endif
550
551/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000552 * xmlTextReaderEntPush:
553 * @reader: the xmlTextReaderPtr used
554 * @value: the entity reference node
555 *
556 * Pushes a new entity reference node on top of the entities stack
557 *
558 * Returns 0 in case of error, the index in the stack otherwise
559 */
560static int
561xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
562{
563 if (reader->entMax <= 0) {
564 reader->entMax = 10;
565 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
566 sizeof(reader->entTab[0]));
567 if (reader->entTab == NULL) {
568 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
569 return (0);
570 }
571 }
572 if (reader->entNr >= reader->entMax) {
573 reader->entMax *= 2;
574 reader->entTab =
575 (xmlNodePtr *) xmlRealloc(reader->entTab,
576 reader->entMax *
577 sizeof(reader->entTab[0]));
578 if (reader->entTab == NULL) {
579 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
580 return (0);
581 }
582 }
583 reader->entTab[reader->entNr] = value;
584 reader->ent = value;
585 return (reader->entNr++);
586}
587
588/**
589 * xmlTextReaderEntPop:
590 * @reader: the xmlTextReaderPtr used
591 *
592 * Pops the top element entity from the entities stack
593 *
594 * Returns the entity just removed
595 */
596static xmlNodePtr
597xmlTextReaderEntPop(xmlTextReaderPtr reader)
598{
599 xmlNodePtr ret;
600
601 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000602 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000603 reader->entNr--;
604 if (reader->entNr > 0)
605 reader->ent = reader->entTab[reader->entNr - 1];
606 else
607 reader->ent = NULL;
608 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000609 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000610 return (ret);
611}
612
613/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000614 * xmlTextReaderStartElement:
615 * @ctx: the user data (XML parser context)
616 * @fullname: The element name, including namespace prefix
617 * @atts: An array of name/value attributes pairs, NULL terminated
618 *
619 * called when an opening tag has been processed.
620 */
621static void
622xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
623 const xmlChar **atts) {
624 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
625 xmlTextReaderPtr reader = ctxt->_private;
626
627#ifdef DEBUG_CALLBACKS
628 printf("xmlTextReaderStartElement(%s)\n", fullname);
629#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000630 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000631 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000632 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
633 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
634 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000635 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000636 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000637 if (reader != NULL)
638 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000639}
640
641/**
642 * xmlTextReaderEndElement:
643 * @ctx: the user data (XML parser context)
644 * @fullname: The element name, including namespace prefix
645 *
646 * called when an ending tag has been processed.
647 */
648static void
649xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
650 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
651 xmlTextReaderPtr reader = ctxt->_private;
652
653#ifdef DEBUG_CALLBACKS
654 printf("xmlTextReaderEndElement(%s)\n", fullname);
655#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000656 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000657 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000659}
660
661/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000662 * xmlTextReaderStartElementNs:
663 * @ctx: the user data (XML parser context)
664 * @localname: the local name of the element
665 * @prefix: the element namespace prefix if available
666 * @URI: the element namespace name if available
667 * @nb_namespaces: number of namespace definitions on that node
668 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
669 * @nb_attributes: the number of attributes on that node
670 * nb_defaulted: the number of defaulted attributes.
671 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
672 * attribute values.
673 *
674 * called when an opening tag has been processed.
675 */
676static void
677xmlTextReaderStartElementNs(void *ctx,
678 const xmlChar *localname,
679 const xmlChar *prefix,
680 const xmlChar *URI,
681 int nb_namespaces,
682 const xmlChar **namespaces,
683 int nb_attributes,
684 int nb_defaulted,
685 const xmlChar **attributes)
686{
687 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
688 xmlTextReaderPtr reader = ctxt->_private;
689
690#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000691 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000692#endif
693 if ((reader != NULL) && (reader->startElementNs != NULL)) {
694 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
695 namespaces, nb_attributes, nb_defaulted,
696 attributes);
697 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
698 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
699 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000700 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000701 }
702 if (reader != NULL)
703 reader->state = XML_TEXTREADER_ELEMENT;
704}
705
706/**
707 * xmlTextReaderEndElementNs:
708 * @ctx: the user data (XML parser context)
709 * @localname: the local name of the element
710 * @prefix: the element namespace prefix if available
711 * @URI: the element namespace name if available
712 *
713 * called when an ending tag has been processed.
714 */
715static void
716xmlTextReaderEndElementNs(void *ctx,
717 const xmlChar * localname,
718 const xmlChar * prefix,
719 const xmlChar * URI)
720{
721 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
722 xmlTextReaderPtr reader = ctxt->_private;
723
724#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000725 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000726#endif
727 if ((reader != NULL) && (reader->endElementNs != NULL)) {
728 reader->endElementNs(ctx, localname, prefix, URI);
729 }
730}
731
732
733/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000734 * xmlTextReaderCharacters:
735 * @ctx: the user data (XML parser context)
736 * @ch: a xmlChar string
737 * @len: the number of xmlChar
738 *
739 * receiving some chars from the parser.
740 */
741static void
742xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
743{
744 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
745 xmlTextReaderPtr reader = ctxt->_private;
746
747#ifdef DEBUG_CALLBACKS
748 printf("xmlTextReaderCharacters()\n");
749#endif
750 if ((reader != NULL) && (reader->characters != NULL)) {
751 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000752 }
753}
754
755/**
756 * xmlTextReaderCDataBlock:
757 * @ctx: the user data (XML parser context)
758 * @value: The pcdata content
759 * @len: the block length
760 *
761 * called when a pcdata block has been parsed
762 */
763static void
764xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
765{
766 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
767 xmlTextReaderPtr reader = ctxt->_private;
768
769#ifdef DEBUG_CALLBACKS
770 printf("xmlTextReaderCDataBlock()\n");
771#endif
772 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
773 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000774 }
775}
776
777/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000778 * xmlTextReaderPushData:
779 * @reader: the xmlTextReaderPtr used
780 *
781 * Push data down the progressive parser until a significant callback
782 * got raised.
783 *
784 * Returns -1 in case of failure, 0 otherwise
785 */
786static int
787xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000788 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000789 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000790 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000791
792 if ((reader->input == NULL) || (reader->input->buffer == NULL))
793 return(-1);
794
Daniel Veillardea7751d2002-12-20 00:16:24 +0000795 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000796 reader->state = XML_TEXTREADER_NONE;
797 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000798
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000799 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000800 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000801 /*
802 * Refill the buffer unless we are at the end of the stream
803 */
804 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
805 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000806 if ((val == 0) &&
807 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
808 if (inbuf->use == reader->cur) {
809 reader->mode = XML_TEXTREADER_MODE_EOF;
810 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000811 }
812 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000813 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000814 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000815 if ((oldstate != XML_TEXTREADER_START) ||
816 (reader->ctxt->myDoc != NULL))
817 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000818 } else if (val == 0) {
819 /* mark the end of the stream and process the remains */
820 reader->mode = XML_TEXTREADER_MODE_EOF;
821 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000822 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000823
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000824 } else
825 break;
826 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000827 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000828 * parse by block of CHUNK_SIZE bytes, various tests show that
829 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000830 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000831 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000832 val = xmlParseChunk(reader->ctxt,
833 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000834 CHUNK_SIZE, 0);
835 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000836 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000837 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000838 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000839 s = inbuf->use - reader->cur;
840 val = xmlParseChunk(reader->ctxt,
841 (const char *) &inbuf->content[reader->cur],
842 s, 0);
843 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000844 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000845 return(-1);
846 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000847 }
848 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000849
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000850 /*
851 * Discard the consumed input when needed and possible
852 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000853 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000854 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
855 if ((reader->cur >= 4096) &&
856 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
857 val = xmlBufferShrink(inbuf, reader->cur);
858 if (val >= 0) {
859 reader->cur -= val;
860 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000861 }
862 }
863 }
864
865 /*
866 * At the end of the stream signal that the work is done to the Push
867 * parser.
868 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000869 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillarda9c56772007-03-09 16:59:05 +0000870 if (reader->state != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000871 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000872 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000873 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000874 s, 1);
875 reader->cur = inbuf->use;
Daniel Veillarda9c56772007-03-09 16:59:05 +0000876 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000877 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000878 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000879 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000880 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000881 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000882 return(0);
883}
884
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000885#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000886/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000887 * xmlTextReaderValidatePush:
888 * @reader: the xmlTextReaderPtr used
889 *
890 * Push the current node for validation
891 */
892static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000893xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000894 xmlNodePtr node = reader->node;
895
Daniel Veillardf54cd532004-02-25 11:52:31 +0000896#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000897 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
898 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
899 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
900 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
901 reader->ctxt->myDoc, node, node->name);
902 } else {
903 /* TODO use the BuildQName interface */
904 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000905
Daniel Veillardf4e55762003-04-15 23:32:22 +0000906 qname = xmlStrdup(node->ns->prefix);
907 qname = xmlStrcat(qname, BAD_CAST ":");
908 qname = xmlStrcat(qname, node->name);
909 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
910 reader->ctxt->myDoc, node, qname);
911 if (qname != NULL)
912 xmlFree(qname);
913 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000914 }
915#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000916#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000917 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000918 (reader->rngValidCtxt != NULL)) {
919 int ret;
920
921 if (reader->rngFullNode != NULL) return;
922 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
923 reader->ctxt->myDoc,
924 node);
925 if (ret == 0) {
926 /*
927 * this element requires a full tree
928 */
929 node = xmlTextReaderExpand(reader);
930 if (node == NULL) {
931printf("Expand failed !\n");
932 ret = -1;
933 } else {
934 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
935 reader->ctxt->myDoc,
936 node);
937 reader->rngFullNode = node;
938 }
939 }
940 if (ret != 1)
941 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000942 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000943#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000944}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000945
946/**
947 * xmlTextReaderValidateCData:
948 * @reader: the xmlTextReaderPtr used
949 * @data: pointer to the CData
950 * @len: lenght of the CData block in bytes.
951 *
952 * Push some CData for validation
953 */
954static void
955xmlTextReaderValidateCData(xmlTextReaderPtr reader,
956 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000957#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000958 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
959 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
960 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
961 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000962 }
963#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000964#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000965 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000966 (reader->rngValidCtxt != NULL)) {
967 int ret;
968
969 if (reader->rngFullNode != NULL) return;
970 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
971 if (ret != 1)
972 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000973 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000974#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000975}
976
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000977/**
978 * xmlTextReaderValidatePop:
979 * @reader: the xmlTextReaderPtr used
980 *
981 * Pop the current node from validation
982 */
983static void
984xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
985 xmlNodePtr node = reader->node;
986
Daniel Veillardf54cd532004-02-25 11:52:31 +0000987#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000988 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
989 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
990 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
991 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
992 reader->ctxt->myDoc, node, node->name);
993 } else {
994 /* TODO use the BuildQName interface */
995 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000996
Daniel Veillardf4e55762003-04-15 23:32:22 +0000997 qname = xmlStrdup(node->ns->prefix);
998 qname = xmlStrcat(qname, BAD_CAST ":");
999 qname = xmlStrcat(qname, node->name);
1000 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1001 reader->ctxt->myDoc, node, qname);
1002 if (qname != NULL)
1003 xmlFree(qname);
1004 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001005 }
1006#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001007#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001008 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001009 (reader->rngValidCtxt != NULL)) {
1010 int ret;
1011
1012 if (reader->rngFullNode != NULL) {
1013 if (node == reader->rngFullNode)
1014 reader->rngFullNode = NULL;
1015 return;
1016 }
1017 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1018 reader->ctxt->myDoc,
1019 node);
1020 if (ret != 1)
1021 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001022 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001023#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001024}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001025
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001026/**
1027 * xmlTextReaderValidateEntity:
1028 * @reader: the xmlTextReaderPtr used
1029 *
1030 * Handle the validation when an entity reference is encountered and
1031 * entity substitution is not activated. As a result the parser interface
1032 * must walk through the entity and do the validation calls
1033 */
1034static void
1035xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1036 xmlNodePtr oldnode = reader->node;
1037 xmlNodePtr node = reader->node;
1038 xmlParserCtxtPtr ctxt = reader->ctxt;
1039
1040 do {
1041 if (node->type == XML_ENTITY_REF_NODE) {
1042 /*
1043 * Case where the underlying tree is not availble, lookup the entity
1044 * and walk it.
1045 */
1046 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1047 (ctxt->sax->getEntity != NULL)) {
1048 node->children = (xmlNodePtr)
1049 ctxt->sax->getEntity(ctxt, node->name);
1050 }
1051
1052 if ((node->children != NULL) &&
1053 (node->children->type == XML_ENTITY_DECL) &&
1054 (node->children->children != NULL)) {
1055 xmlTextReaderEntPush(reader, node);
1056 node = node->children->children;
1057 continue;
1058 } else {
1059 /*
1060 * The error has probably be raised already.
1061 */
1062 if (node == oldnode)
1063 break;
1064 node = node->next;
1065 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001066#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001067 } else if (node->type == XML_ELEMENT_NODE) {
1068 reader->node = node;
1069 xmlTextReaderValidatePush(reader);
1070 } else if ((node->type == XML_TEXT_NODE) ||
1071 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001072 xmlTextReaderValidateCData(reader, node->content,
1073 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001074#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001075 }
1076
1077 /*
1078 * go to next node
1079 */
1080 if (node->children != NULL) {
1081 node = node->children;
1082 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001083 } else if (node->type == XML_ELEMENT_NODE) {
1084 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001085 }
1086 if (node->next != NULL) {
1087 node = node->next;
1088 continue;
1089 }
1090 do {
1091 node = node->parent;
1092 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001093 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001094 if (reader->entNr == 0) {
1095 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001096 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001097 xmlUnlinkNode(tmp);
1098 xmlTextReaderFreeNode(reader, tmp);
1099 } else
1100 break;
1101 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001102 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001103 reader->node = node;
1104 xmlTextReaderValidatePop(reader);
1105 }
1106 if ((node->type == XML_ENTITY_DECL) &&
1107 (reader->ent != NULL) && (reader->ent->children == node)) {
1108 node = xmlTextReaderEntPop(reader);
1109 }
1110 if (node == oldnode)
1111 break;
1112 if (node->next != NULL) {
1113 node = node->next;
1114 break;
1115 }
1116 } while ((node != NULL) && (node != oldnode));
1117 } while ((node != NULL) && (node != oldnode));
1118 reader->node = oldnode;
1119}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001120#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001121
1122
1123/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001124 * xmlTextReaderGetSuccessor:
1125 * @cur: the current node
1126 *
1127 * Get the successor of a node if available.
1128 *
1129 * Returns the successor node or NULL
1130 */
1131static xmlNodePtr
1132xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1133 if (cur == NULL) return(NULL) ; /* ERROR */
1134 if (cur->next != NULL) return(cur->next) ;
1135 do {
1136 cur = cur->parent;
Daniel Veillard11ce4002006-03-10 00:36:23 +00001137 if (cur == NULL) break;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001138 if (cur->next != NULL) return(cur->next);
1139 } while (cur != NULL);
1140 return(cur);
1141}
1142
1143/**
1144 * xmlTextReaderDoExpand:
1145 * @reader: the xmlTextReaderPtr used
1146 *
1147 * Makes sure that the current node is fully read as well as all its
1148 * descendant. It means the full DOM subtree must be available at the
1149 * end of the call.
1150 *
1151 * Returns 1 if the node was expanded successfully, 0 if there is no more
1152 * nodes to read, or -1 in case of error
1153 */
1154static int
1155xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1156 int val;
1157
1158 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1159 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001160 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001161 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1162
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001163 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1164 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001165 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001166 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001167 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1168 return(1);
1169 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001170 if (val < 0){
William M. Brack0c1e3012007-03-14 12:40:21 +00001171 reader->mode = XML_TEXTREADER_MODE_ERROR;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001172 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001173 }
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001174 } 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);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001260 if (val < 0){
1261 reader->mode = XML_TEXTREADER_MODE_ERROR;
1262 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001264 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001265 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001266 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
Daniel Veillarda9c56772007-03-09 16:59:05 +00001267 (reader->state != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001269 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001270 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001271 }
Daniel Veillarda9c56772007-03-09 16:59:05 +00001272 if (reader->node == NULL){
1273 reader->mode = XML_TEXTREADER_MODE_ERROR;
1274 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001275 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001276 }
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001277 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001278 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001279 if (reader->ctxt->myDoc != NULL) {
1280 reader->node = reader->ctxt->myDoc->children;
1281 }
1282 if (reader->node == NULL)
1283 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001284 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001285 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001286 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001287 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001289 }
1290 oldstate = reader->state;
1291 olddepth = reader->ctxt->nodeNr;
1292 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001293
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001294get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001295 if (reader->node == NULL) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001296 if (reader->mode == XML_TEXTREADER_MODE_EOF)
Daniel Veillard6f379a72004-04-29 18:45:42 +00001297 return(0);
1298 else
1299 return(-1);
1300 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001301
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001302 /*
1303 * If we are not backtracking on ancestors or examined nodes,
1304 * that the parser didn't finished or that we arent at the end
1305 * of stream, continue processing.
1306 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001307 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001308 (reader->ctxt->nodeNr == olddepth) &&
1309 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001310 (reader->node->children == NULL) ||
1311 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001312 ((reader->node->children != NULL) &&
1313 (reader->node->children->type == XML_TEXT_NODE) &&
1314 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001315 (reader->node->type == XML_DTD_NODE) ||
1316 (reader->node->type == XML_DOCUMENT_NODE) ||
1317 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001318 ((reader->ctxt->node == NULL) ||
1319 (reader->ctxt->node == reader->node) ||
1320 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001321 (reader->ctxt->instate != XML_PARSER_EOF)) {
1322 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001323 if (val < 0){
1324 reader->mode = XML_TEXTREADER_MODE_ERROR;
1325 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001326 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001327 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001328 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001329 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001330 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001332 if ((reader->node->children != NULL) &&
1333 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001334 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 (reader->node->type != XML_DTD_NODE)) {
1336 reader->node = reader->node->children;
1337 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001338 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001339 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001340 }
1341 }
1342 if (reader->node->next != NULL) {
1343 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001344 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001345 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001346 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1347#ifdef LIBXML_XINCLUDE_ENABLED
1348 && (reader->in_xinclude <= 0)
1349#endif
1350 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001351 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001352 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001353 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001354#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001355 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001356 (reader->node->type == XML_ELEMENT_NODE))
1357 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001358#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001359 if ((reader->preserves > 0) &&
1360 (reader->node->extra & NODE_IS_SPRESERVED))
1361 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001362 reader->node = reader->node->next;
1363 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001364
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001365 /*
1366 * Cleanup of the old node
1367 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001368 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001369#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001370 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001371#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001372 (reader->entNr == 0) &&
1373 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001374 (reader->node->prev->type != XML_DTD_NODE) &&
1375 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001376 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001377 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001378 xmlUnlinkNode(tmp);
1379 xmlTextReaderFreeNode(reader, tmp);
1380 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001381 }
1382
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001383 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001384 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001385 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001386 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001387 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001388 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001389 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001390 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001391 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001392#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001393 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001394 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001395#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001396 if ((reader->preserves > 0) &&
1397 (reader->node->extra & NODE_IS_SPRESERVED))
1398 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001399 reader->node = reader->node->parent;
1400 if ((reader->node == NULL) ||
1401 (reader->node->type == XML_DOCUMENT_NODE) ||
1402#ifdef LIBXML_DOCB_ENABLED
1403 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1404#endif
1405 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001406 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001407 val = xmlParseChunk(reader->ctxt, "", 0, 1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001408 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001409 if (val != 0)
1410 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001411 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001412 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001413 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001414
1415 /*
1416 * Cleanup of the old node
1417 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001418 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001419#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001420 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001421#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001422 (reader->entNr == 0) &&
1423 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001424 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001425 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001426 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001427 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001428 }
1429
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001430 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001431 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001432 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001433#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001434 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001435#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001436 (reader->entNr == 0) &&
1437 (reader->node->last != NULL) &&
1438 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1439 xmlNodePtr tmp = reader->node->last;
1440 xmlUnlinkNode(tmp);
1441 xmlTextReaderFreeNode(reader, tmp);
1442 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001443 reader->depth--;
1444 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001445
1446node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001447 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001448
1449 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001450 * If we are in the middle of a piece of CDATA make sure it's finished
1451 */
1452 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001453 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001454 ((reader->node->type == XML_TEXT_NODE) ||
1455 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001456 if (xmlTextReaderExpand(reader) == NULL)
1457 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001458 }
1459
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001460#ifdef LIBXML_XINCLUDE_ENABLED
1461 /*
1462 * Handle XInclude if asked for
1463 */
1464 if ((reader->xinclude) && (reader->node != NULL) &&
1465 (reader->node->type == XML_ELEMENT_NODE) &&
1466 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001467 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1468 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001469 if (reader->xincctxt == NULL) {
1470 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001471 xmlXIncludeSetFlags(reader->xincctxt,
1472 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001473 }
1474 /*
1475 * expand that node and process it
1476 */
William M. Brack42331a92004-07-29 07:07:16 +00001477 if (xmlTextReaderExpand(reader) == NULL)
1478 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001479 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1480 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001481 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001482 reader->in_xinclude++;
1483 goto get_next_node;
1484 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001485 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001486 reader->in_xinclude--;
1487 goto get_next_node;
1488 }
1489#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001490 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001491 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001492 */
1493 if ((reader->node != NULL) &&
1494 (reader->node->type == XML_ENTITY_REF_NODE) &&
1495 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1496 /*
1497 * Case where the underlying tree is not availble, lookup the entity
1498 * and walk it.
1499 */
1500 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1501 (reader->ctxt->sax->getEntity != NULL)) {
1502 reader->node->children = (xmlNodePtr)
1503 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1504 }
1505
1506 if ((reader->node->children != NULL) &&
1507 (reader->node->children->type == XML_ENTITY_DECL) &&
1508 (reader->node->children->children != NULL)) {
1509 xmlTextReaderEntPush(reader, reader->node);
1510 reader->node = reader->node->children->children;
1511 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001512#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001513 } else if ((reader->node != NULL) &&
1514 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001515 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001516 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001517#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001518 }
1519 if ((reader->node != NULL) &&
1520 (reader->node->type == XML_ENTITY_DECL) &&
1521 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1522 reader->node = xmlTextReaderEntPop(reader);
1523 reader->depth++;
1524 goto get_next_node;
1525 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001526#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001527 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001528 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001529
1530 if ((node->type == XML_ELEMENT_NODE) &&
1531 ((reader->state != XML_TEXTREADER_END) &&
1532 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1533 xmlTextReaderValidatePush(reader);
1534 } else if ((node->type == XML_TEXT_NODE) ||
1535 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001536 xmlTextReaderValidateCData(reader, node->content,
1537 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001538 }
1539 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001540#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001541#ifdef LIBXML_PATTERN_ENABLED
1542 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1543 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1544 int i;
1545 for (i = 0;i < reader->patternNr;i++) {
1546 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1547 xmlTextReaderPreserve(reader);
1548 break;
1549 }
1550 }
1551 }
1552#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001553#ifdef LIBXML_SCHEMAS_ENABLED
1554 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1555 (reader->xsdValidErrors == 0) &&
1556 (reader->xsdValidCtxt != NULL)) {
1557 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1558 }
1559#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001560 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001561node_end:
Daniel Veillarda9c56772007-03-09 16:59:05 +00001562 reader->state = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001563 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001564}
1565
Daniel Veillard67df8092002-12-16 22:04:11 +00001566/**
1567 * xmlTextReaderReadState:
1568 * @reader: the xmlTextReaderPtr used
1569 *
1570 * Gets the read state of the reader.
1571 *
1572 * Returns the state value, or -1 in case of error
1573 */
1574int
1575xmlTextReaderReadState(xmlTextReaderPtr reader) {
1576 if (reader == NULL)
1577 return(-1);
1578 return(reader->mode);
1579}
1580
1581/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001582 * xmlTextReaderExpand:
1583 * @reader: the xmlTextReaderPtr used
1584 *
1585 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001586 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001587 *
1588 * Returns a node pointer valid until the next xmlTextReaderRead() call
1589 * or NULL in case of error.
1590 */
1591xmlNodePtr
1592xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001593 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001594 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001595 if (reader->doc != NULL)
1596 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001597 if (reader->ctxt == NULL)
1598 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001599 if (xmlTextReaderDoExpand(reader) < 0)
1600 return(NULL);
1601 return(reader->node);
1602}
1603
1604/**
1605 * xmlTextReaderNext:
1606 * @reader: the xmlTextReaderPtr used
1607 *
1608 * Skip to the node following the current one in document order while
1609 * avoiding the subtree if any.
1610 *
1611 * Returns 1 if the node was read successfully, 0 if there is no more
1612 * nodes to read, or -1 in case of error
1613 */
1614int
1615xmlTextReaderNext(xmlTextReaderPtr reader) {
1616 int ret;
1617 xmlNodePtr cur;
1618
1619 if (reader == NULL)
1620 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001621 if (reader->doc != NULL)
1622 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001623 cur = reader->node;
1624 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1625 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001626 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001627 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001628 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001629 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001630 do {
1631 ret = xmlTextReaderRead(reader);
1632 if (ret != 1)
1633 return(ret);
1634 } while (reader->node != cur);
1635 return(xmlTextReaderRead(reader));
1636}
1637
Daniel Veillardd0271472006-01-02 10:22:02 +00001638#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001639/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001640 * xmlTextReaderReadInnerXml:
1641 * @reader: the xmlTextReaderPtr used
1642 *
1643 * Reads the contents of the current node, including child nodes and markup.
1644 *
1645 * Returns a string containing the XML content, or NULL if the current node
1646 * is neither an element nor attribute, or has no child nodes. The
1647 * string must be deallocated by the caller.
1648 */
1649xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001650xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1651{
1652 xmlChar *resbuf;
1653 xmlNodePtr node, cur_node;
1654 xmlBufferPtr buff, buff2;
1655 xmlDocPtr doc;
1656
1657 if (xmlTextReaderExpand(reader) == NULL) {
1658 return NULL;
1659 }
1660 doc = reader->doc;
1661 buff = xmlBufferCreate();
1662 for (cur_node = reader->node->children; cur_node != NULL;
1663 cur_node = cur_node->next) {
1664 node = xmlDocCopyNode(cur_node, doc, 1);
1665 buff2 = xmlBufferCreate();
1666 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1667 xmlFreeNode(node);
1668 xmlBufferFree(buff2);
1669 xmlBufferFree(buff);
1670 return NULL;
1671 }
1672 xmlBufferCat(buff, buff2->content);
1673 xmlFreeNode(node);
1674 xmlBufferFree(buff2);
1675 }
1676 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001677 buff->content = NULL;
1678
1679 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001680 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001681}
Daniel Veillardd0271472006-01-02 10:22:02 +00001682#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001683
Daniel Veillardd0271472006-01-02 10:22:02 +00001684#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001685/**
1686 * xmlTextReaderReadOuterXml:
1687 * @reader: the xmlTextReaderPtr used
1688 *
1689 * Reads the contents of the current node, including child nodes and markup.
1690 *
1691 * Returns a string containing the XML content, or NULL if the current node
1692 * is neither an element nor attribute, or has no child nodes. The
1693 * string must be deallocated by the caller.
1694 */
1695xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001696xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1697{
1698 xmlChar *resbuf;
1699 xmlNodePtr node;
1700 xmlBufferPtr buff;
1701 xmlDocPtr doc;
1702
1703 node = reader->node;
1704 doc = reader->doc;
1705 if (xmlTextReaderExpand(reader) == NULL) {
1706 return NULL;
1707 }
1708 node = xmlDocCopyNode(node, doc, 1);
1709 buff = xmlBufferCreate();
1710 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1711 xmlFreeNode(node);
1712 xmlBufferFree(buff);
1713 return NULL;
1714 }
1715
1716 resbuf = buff->content;
1717 buff->content = NULL;
1718
1719 xmlFreeNode(node);
1720 xmlBufferFree(buff);
1721 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001722}
Daniel Veillardd0271472006-01-02 10:22:02 +00001723#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001724
1725/**
1726 * xmlTextReaderReadString:
1727 * @reader: the xmlTextReaderPtr used
1728 *
1729 * Reads the contents of an element or a text node as a string.
1730 *
1731 * Returns a string containing the contents of the Element or Text node,
1732 * or NULL if the reader is positioned on any other type of node.
1733 * The string must be deallocated by the caller.
1734 */
1735xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001736xmlTextReaderReadString(xmlTextReaderPtr reader)
1737{
1738 xmlNodePtr node;
1739
1740 if ((reader == NULL) || (reader->node == NULL))
1741 return(NULL);
1742
1743 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1744 switch (node->type) {
1745 case XML_TEXT_NODE:
1746 if (node->content != NULL)
1747 return(xmlStrdup(node->content));
1748 break;
1749 case XML_ELEMENT_NODE:
1750 if (xmlTextReaderDoExpand(reader) != -1) {
1751 return xmlTextReaderCollectSiblings(node->children);
1752 }
1753 case XML_ATTRIBUTE_NODE:
1754 TODO
1755 break;
1756 default:
1757 break;
1758 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001759 return(NULL);
1760}
1761
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001762#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001763/**
1764 * xmlTextReaderReadBase64:
1765 * @reader: the xmlTextReaderPtr used
1766 * @array: a byte array to store the content.
1767 * @offset: the zero-based index into array where the method should
1768 * begin to write.
1769 * @len: the number of bytes to write.
1770 *
1771 * Reads and decodes the Base64 encoded contents of an element and
1772 * stores the result in a byte buffer.
1773 *
1774 * Returns the number of bytes written to array, or zero if the current
1775 * instance is not positioned on an element or -1 in case of error.
1776 */
1777int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001778xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1779 unsigned char *array ATTRIBUTE_UNUSED,
1780 int offset ATTRIBUTE_UNUSED,
1781 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001782 if ((reader == NULL) || (reader->ctxt == NULL))
1783 return(-1);
1784 if (reader->ctxt->wellFormed != 1)
1785 return(-1);
1786
1787 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1788 return(0);
1789 TODO
1790 return(0);
1791}
1792
1793/**
1794 * xmlTextReaderReadBinHex:
1795 * @reader: the xmlTextReaderPtr used
1796 * @array: a byte array to store the content.
1797 * @offset: the zero-based index into array where the method should
1798 * begin to write.
1799 * @len: the number of bytes to write.
1800 *
1801 * Reads and decodes the BinHex encoded contents of an element and
1802 * stores the result in a byte buffer.
1803 *
1804 * Returns the number of bytes written to array, or zero if the current
1805 * instance is not positioned on an element or -1 in case of error.
1806 */
1807int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001808xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1809 unsigned char *array ATTRIBUTE_UNUSED,
1810 int offset ATTRIBUTE_UNUSED,
1811 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001812 if ((reader == NULL) || (reader->ctxt == NULL))
1813 return(-1);
1814 if (reader->ctxt->wellFormed != 1)
1815 return(-1);
1816
1817 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1818 return(0);
1819 TODO
1820 return(0);
1821}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001822#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001823
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001824/************************************************************************
1825 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001826 * Operating on a preparsed tree *
1827 * *
1828 ************************************************************************/
1829static int
1830xmlTextReaderNextTree(xmlTextReaderPtr reader)
1831{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001832 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001833 return(-1);
1834
1835 if (reader->state == XML_TEXTREADER_END)
1836 return(0);
1837
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001838 if (reader->node == NULL) {
1839 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001840 reader->state = XML_TEXTREADER_END;
1841 return(0);
1842 }
1843
1844 reader->node = reader->doc->children;
1845 reader->state = XML_TEXTREADER_START;
1846 return(1);
1847 }
1848
1849 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardaa6de472008-08-25 14:53:31 +00001850 /* Here removed traversal to child, because we want to skip the subtree,
1851 replace with traversal to sibling to skip subtree */
1852 if (reader->node->next != 0) {
1853 reader->node = reader->node->next;// Move to sibling if present,skipping sub-tree
1854 //reader->depth++;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001855 reader->state = XML_TEXTREADER_START;
1856 return(1);
1857 }
Daniel Veillardaa6de472008-08-25 14:53:31 +00001858
1859 /* if reader->node->next is NULL mean no subtree for current node,
1860 so need to move to sibling of parent node if present */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001861 if ((reader->node->type == XML_ELEMENT_NODE) ||
1862 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1863 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardaa6de472008-08-25 14:53:31 +00001864 xmlTextReaderRead(reader);// This will move to parent if present
1865 //return(xmlTextReaderReadTree(reader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001866 }
1867 }
1868
1869 if (reader->node->next != 0) {
1870 reader->node = reader->node->next;
1871 reader->state = XML_TEXTREADER_START;
1872 return(1);
1873 }
1874
1875 if (reader->node->parent != 0) {
1876 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1877 reader->state = XML_TEXTREADER_END;
1878 return(0);
1879 }
1880
1881 reader->node = reader->node->parent;
1882 reader->depth--;
1883 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardaa6de472008-08-25 14:53:31 +00001884 xmlTextReaderNextTree(reader); //Repeat process to move to sibling of parent node if present
1885 //return(1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001886 }
1887
1888 reader->state = XML_TEXTREADER_END;
1889
1890 return(1);
1891}
1892
1893/**
1894 * xmlTextReaderReadTree:
1895 * @reader: the xmlTextReaderPtr used
1896 *
1897 * Moves the position of the current instance to the next node in
1898 * the stream, exposing its properties.
1899 *
1900 * Returns 1 if the node was read successfully, 0 if there is no more
1901 * nodes to read, or -1 in case of error
1902 */
1903static int
1904xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1905 if (reader->state == XML_TEXTREADER_END)
1906 return(0);
1907
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001908next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001909 if (reader->node == NULL) {
1910 if (reader->doc->children == NULL) {
1911 reader->state = XML_TEXTREADER_END;
1912 return(0);
1913 }
1914
1915 reader->node = reader->doc->children;
1916 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001917 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001918 }
1919
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001920 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1921 (reader->node->type != XML_DTD_NODE) &&
1922 (reader->node->type != XML_XINCLUDE_START) &&
1923 (reader->node->type != XML_ENTITY_REF_NODE)) {
1924 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001925 reader->node = reader->node->children;
1926 reader->depth++;
1927 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001928 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001929 }
1930
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001931 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001933 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001934 }
1935 }
1936
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001937 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001938 reader->node = reader->node->next;
1939 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001940 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001941 }
1942
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001943 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001944 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1945 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1946 reader->state = XML_TEXTREADER_END;
1947 return(0);
1948 }
1949
1950 reader->node = reader->node->parent;
1951 reader->depth--;
1952 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001953 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001954 }
1955
1956 reader->state = XML_TEXTREADER_END;
1957
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001958found_node:
1959 if ((reader->node->type == XML_XINCLUDE_START) ||
1960 (reader->node->type == XML_XINCLUDE_END))
1961 goto next_node;
1962
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001963 return(1);
1964}
1965
1966/**
William M. Brackb1d53162003-11-18 06:54:40 +00001967 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001968 * @reader: the xmlTextReaderPtr used
1969 *
1970 * Skip to the node following the current one in document order while
1971 * avoiding the subtree if any.
1972 * Currently implemented only for Readers built on a document
1973 *
1974 * Returns 1 if the node was read successfully, 0 if there is no more
1975 * nodes to read, or -1 in case of error
1976 */
1977int
1978xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1979 if (reader == NULL)
1980 return(-1);
1981 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001982 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001983 return(-1);
1984 }
1985
1986 if (reader->state == XML_TEXTREADER_END)
1987 return(0);
1988
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001989 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001990 return(xmlTextReaderNextTree(reader));
1991
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001992 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001993 reader->node = reader->node->next;
1994 reader->state = XML_TEXTREADER_START;
1995 return(1);
1996 }
1997
1998 return(0);
1999}
2000
2001/************************************************************************
2002 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002003 * Constructor and destructors *
2004 * *
2005 ************************************************************************/
2006/**
2007 * xmlNewTextReader:
2008 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002009 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002010 *
2011 * Create an xmlTextReader structure fed with @input
2012 *
2013 * Returns the new xmlTextReaderPtr or NULL in case of error
2014 */
2015xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002016xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002017 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018
2019 if (input == NULL)
2020 return(NULL);
2021 ret = xmlMalloc(sizeof(xmlTextReader));
2022 if (ret == NULL) {
2023 xmlGenericError(xmlGenericErrorContext,
2024 "xmlNewTextReader : malloc failed\n");
2025 return(NULL);
2026 }
2027 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002028 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002029 ret->entTab = NULL;
2030 ret->entMax = 0;
2031 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002032 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002033 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002034 if (ret->buffer == NULL) {
2035 xmlFree(ret);
2036 xmlGenericError(xmlGenericErrorContext,
2037 "xmlNewTextReader : malloc failed\n");
2038 return(NULL);
2039 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002040 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2041 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002042 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002043 xmlFree(ret);
2044 xmlGenericError(xmlGenericErrorContext,
2045 "xmlNewTextReader : malloc failed\n");
2046 return(NULL);
2047 }
Daniel Veillard81273902003-09-30 00:43:48 +00002048 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002049 ret->startElement = ret->sax->startElement;
2050 ret->sax->startElement = xmlTextReaderStartElement;
2051 ret->endElement = ret->sax->endElement;
2052 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002053#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002054 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002055#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002056 ret->startElementNs = ret->sax->startElementNs;
2057 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2058 ret->endElementNs = ret->sax->endElementNs;
2059 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002060#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002061 } else {
2062 ret->startElementNs = NULL;
2063 ret->endElementNs = NULL;
2064 }
Daniel Veillard81273902003-09-30 00:43:48 +00002065#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002066 ret->characters = ret->sax->characters;
2067 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002068 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002069 ret->cdataBlock = ret->sax->cdataBlock;
2070 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002071
Daniel Veillard67df8092002-12-16 22:04:11 +00002072 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002073 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002074 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002075 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002076 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002077 }
2078 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002079 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002080 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002081 ret->base = 0;
2082 ret->cur = 4;
2083 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002084 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002085 ret->base = 0;
2086 ret->cur = 0;
2087 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002088
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002089 if (ret->ctxt == NULL) {
2090 xmlGenericError(xmlGenericErrorContext,
2091 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002092 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002093 xmlFree(ret->sax);
2094 xmlFree(ret);
2095 return(NULL);
2096 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002097 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002098 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002099 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002100 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002101 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002102 /*
2103 * use the parser dictionnary to allocate all elements and attributes names
2104 */
2105 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002106 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002107#ifdef LIBXML_XINCLUDE_ENABLED
2108 ret->xinclude = 0;
2109#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002110#ifdef LIBXML_PATTERN_ENABLED
2111 ret->patternMax = 0;
2112 ret->patternTab = NULL;
2113#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002114 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115}
2116
2117/**
2118 * xmlNewTextReaderFilename:
2119 * @URI: the URI of the resource to process
2120 *
2121 * Create an xmlTextReader structure fed with the resource at @URI
2122 *
2123 * Returns the new xmlTextReaderPtr or NULL in case of error
2124 */
2125xmlTextReaderPtr
2126xmlNewTextReaderFilename(const char *URI) {
2127 xmlParserInputBufferPtr input;
2128 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002129 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002130
2131 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2132 if (input == NULL)
2133 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002134 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002135 if (ret == NULL) {
2136 xmlFreeParserInputBuffer(input);
2137 return(NULL);
2138 }
2139 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002140 if (ret->ctxt->directory == NULL)
2141 directory = xmlParserGetDirectory(URI);
2142 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2143 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2144 if (directory != NULL)
2145 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002146 return(ret);
2147}
2148
2149/**
2150 * xmlFreeTextReader:
2151 * @reader: the xmlTextReaderPtr
2152 *
2153 * Deallocate all the resources associated to the reader
2154 */
2155void
2156xmlFreeTextReader(xmlTextReaderPtr reader) {
2157 if (reader == NULL)
2158 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002159#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002160 if (reader->rngSchemas != NULL) {
2161 xmlRelaxNGFree(reader->rngSchemas);
2162 reader->rngSchemas = NULL;
2163 }
2164 if (reader->rngValidCtxt != NULL) {
2165 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2166 reader->rngValidCtxt = NULL;
2167 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002168 if (reader->xsdPlug != NULL) {
2169 xmlSchemaSAXUnplug(reader->xsdPlug);
2170 reader->xsdPlug = NULL;
2171 }
2172 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002173 if (! reader->xsdPreserveCtxt)
2174 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002175 reader->xsdValidCtxt = NULL;
2176 }
2177 if (reader->xsdSchemas != NULL) {
2178 xmlSchemaFree(reader->xsdSchemas);
2179 reader->xsdSchemas = NULL;
2180 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002181#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002182#ifdef LIBXML_XINCLUDE_ENABLED
2183 if (reader->xincctxt != NULL)
2184 xmlXIncludeFreeContext(reader->xincctxt);
2185#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002186#ifdef LIBXML_PATTERN_ENABLED
2187 if (reader->patternTab != NULL) {
2188 int i;
2189 for (i = 0;i < reader->patternNr;i++) {
2190 if (reader->patternTab[i] != NULL)
2191 xmlFreePattern(reader->patternTab[i]);
2192 }
2193 xmlFree(reader->patternTab);
2194 }
2195#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002196 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002197 if (reader->dict == reader->ctxt->dict)
2198 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002199 if (reader->ctxt->myDoc != NULL) {
2200 if (reader->preserve == 0)
2201 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2202 reader->ctxt->myDoc = NULL;
2203 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002204 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2205 (reader->ctxt->vctxt.vstateMax > 0)){
2206 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002207 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002208 reader->ctxt->vctxt.vstateMax = 0;
2209 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002210 if (reader->allocs & XML_TEXTREADER_CTXT)
2211 xmlFreeParserCtxt(reader->ctxt);
2212 }
2213 if (reader->sax != NULL)
2214 xmlFree(reader->sax);
2215 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2216 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002217 if (reader->faketext != NULL) {
2218 xmlFreeNode(reader->faketext);
2219 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002220 if (reader->buffer != NULL)
2221 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002222 if (reader->entTab != NULL)
2223 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002224 if (reader->dict != NULL)
2225 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002226 xmlFree(reader);
2227}
2228
2229/************************************************************************
2230 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002231 * Methods for XmlTextReader *
2232 * *
2233 ************************************************************************/
2234/**
2235 * xmlTextReaderClose:
2236 * @reader: the xmlTextReaderPtr used
2237 *
2238 * This method releases any resources allocated by the current instance
2239 * changes the state to Closed and close any underlying input.
2240 *
2241 * Returns 0 or -1 in case of error
2242 */
2243int
2244xmlTextReaderClose(xmlTextReaderPtr reader) {
2245 if (reader == NULL)
2246 return(-1);
2247 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002248 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002249 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2250 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002251 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002252 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002253 if (reader->preserve == 0)
2254 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002255 reader->ctxt->myDoc = NULL;
2256 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002257 }
2258 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2259 xmlFreeParserInputBuffer(reader->input);
2260 reader->allocs -= XML_TEXTREADER_INPUT;
2261 }
2262 return(0);
2263}
2264
2265/**
2266 * xmlTextReaderGetAttributeNo:
2267 * @reader: the xmlTextReaderPtr used
2268 * @no: the zero-based index of the attribute relative to the containing element
2269 *
2270 * Provides the value of the attribute with the specified index relative
2271 * to the containing element.
2272 *
2273 * Returns a string containing the value of the specified attribute, or NULL
2274 * in case of error. The string must be deallocated by the caller.
2275 */
2276xmlChar *
2277xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2278 xmlChar *ret;
2279 int i;
2280 xmlAttrPtr cur;
2281 xmlNsPtr ns;
2282
2283 if (reader == NULL)
2284 return(NULL);
2285 if (reader->node == NULL)
2286 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002287 if (reader->curnode != NULL)
2288 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002289 /* TODO: handle the xmlDecl */
2290 if (reader->node->type != XML_ELEMENT_NODE)
2291 return(NULL);
2292
2293 ns = reader->node->nsDef;
2294 for (i = 0;(i < no) && (ns != NULL);i++) {
2295 ns = ns->next;
2296 }
2297 if (ns != NULL)
2298 return(xmlStrdup(ns->href));
2299
2300 cur = reader->node->properties;
2301 if (cur == NULL)
2302 return(NULL);
2303 for (;i < no;i++) {
2304 cur = cur->next;
2305 if (cur == NULL)
2306 return(NULL);
2307 }
2308 /* TODO walk the DTD if present */
2309
2310 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2311 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2312 return(ret);
2313}
2314
2315/**
2316 * xmlTextReaderGetAttribute:
2317 * @reader: the xmlTextReaderPtr used
2318 * @name: the qualified name of the attribute.
2319 *
2320 * Provides the value of the attribute with the specified qualified name.
2321 *
2322 * Returns a string containing the value of the specified attribute, or NULL
2323 * in case of error. The string must be deallocated by the caller.
2324 */
2325xmlChar *
2326xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2327 xmlChar *prefix = NULL;
2328 xmlChar *localname;
2329 xmlNsPtr ns;
2330 xmlChar *ret = NULL;
2331
2332 if ((reader == NULL) || (name == NULL))
2333 return(NULL);
2334 if (reader->node == NULL)
2335 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002336 if (reader->curnode != NULL)
2337 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002338
2339 /* TODO: handle the xmlDecl */
2340 if (reader->node->type != XML_ELEMENT_NODE)
2341 return(NULL);
2342
2343 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002344 if (localname == NULL) {
2345 /*
2346 * Namespace default decl
2347 */
2348 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2349 ns = reader->node->nsDef;
2350 while (ns != NULL) {
2351 if (ns->prefix == NULL) {
2352 return(xmlStrdup(ns->href));
2353 }
2354 ns = ns->next;
2355 }
2356 return NULL;
2357 }
2358 return(xmlGetNoNsProp(reader->node, name));
2359 }
2360
2361 /*
2362 * Namespace default decl
2363 */
2364 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2365 ns = reader->node->nsDef;
2366 while (ns != NULL) {
2367 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2368 ret = xmlStrdup(ns->href);
2369 break;
2370 }
2371 ns = ns->next;
2372 }
2373 } else {
2374 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2375 if (ns != NULL)
2376 ret = xmlGetNsProp(reader->node, localname, ns->href);
2377 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002378
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002379 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002380 if (prefix != NULL)
2381 xmlFree(prefix);
2382 return(ret);
2383}
2384
2385
2386/**
2387 * xmlTextReaderGetAttributeNs:
2388 * @reader: the xmlTextReaderPtr used
2389 * @localName: the local name of the attribute.
2390 * @namespaceURI: the namespace URI of the attribute.
2391 *
2392 * Provides the value of the specified attribute
2393 *
2394 * Returns a string containing the value of the specified attribute, or NULL
2395 * in case of error. The string must be deallocated by the caller.
2396 */
2397xmlChar *
2398xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2399 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002400 xmlChar *prefix = NULL;
2401 xmlNsPtr ns;
2402
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002403 if ((reader == NULL) || (localName == NULL))
2404 return(NULL);
2405 if (reader->node == NULL)
2406 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002407 if (reader->curnode != NULL)
2408 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002409
2410 /* TODO: handle the xmlDecl */
2411 if (reader->node->type != XML_ELEMENT_NODE)
2412 return(NULL);
2413
Daniel Veillard45b97e72005-08-20 21:14:28 +00002414 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2415 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2416 prefix = BAD_CAST localName;
2417 }
2418 ns = reader->node->nsDef;
2419 while (ns != NULL) {
2420 if ((prefix == NULL && ns->prefix == NULL) ||
2421 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2422 return xmlStrdup(ns->href);
2423 }
2424 ns = ns->next;
2425 }
2426 return NULL;
2427 }
2428
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002429 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2430}
2431
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002432/**
2433 * xmlTextReaderGetRemainder:
2434 * @reader: the xmlTextReaderPtr used
2435 *
2436 * Method to get the remainder of the buffered XML. this method stops the
2437 * parser, set its state to End Of File and return the input stream with
2438 * what is left that the parser did not use.
2439 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002440 * The implementation is not good, the parser certainly procgressed past
2441 * what's left in reader->input, and there is an allocation problem. Best
2442 * would be to rewrite it differently.
2443 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002444 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2445 * in case of error.
2446 */
2447xmlParserInputBufferPtr
2448xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2449 xmlParserInputBufferPtr ret = NULL;
2450
2451 if (reader == NULL)
2452 return(NULL);
2453 if (reader->node == NULL)
2454 return(NULL);
2455
2456 reader->node = NULL;
2457 reader->curnode = NULL;
2458 reader->mode = XML_TEXTREADER_MODE_EOF;
2459 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002460 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002461 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002462 if (reader->preserve == 0)
2463 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002464 reader->ctxt->myDoc = NULL;
2465 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002466 }
2467 if (reader->allocs & XML_TEXTREADER_INPUT) {
2468 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002469 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002470 reader->allocs -= XML_TEXTREADER_INPUT;
2471 } else {
2472 /*
2473 * Hum, one may need to duplicate the data structure because
2474 * without reference counting the input may be freed twice:
2475 * - by the layer which allocated it.
2476 * - by the layer to which would have been returned to.
2477 */
2478 TODO
2479 return(NULL);
2480 }
2481 return(ret);
2482}
2483
2484/**
2485 * xmlTextReaderLookupNamespace:
2486 * @reader: the xmlTextReaderPtr used
2487 * @prefix: the prefix whose namespace URI is to be resolved. To return
2488 * the default namespace, specify NULL
2489 *
2490 * Resolves a namespace prefix in the scope of the current element.
2491 *
2492 * Returns a string containing the namespace URI to which the prefix maps
2493 * or NULL in case of error. The string must be deallocated by the caller.
2494 */
2495xmlChar *
2496xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2497 xmlNsPtr ns;
2498
2499 if (reader == NULL)
2500 return(NULL);
2501 if (reader->node == NULL)
2502 return(NULL);
2503
2504 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2505 if (ns == NULL)
2506 return(NULL);
2507 return(xmlStrdup(ns->href));
2508}
2509
2510/**
2511 * xmlTextReaderMoveToAttributeNo:
2512 * @reader: the xmlTextReaderPtr used
2513 * @no: the zero-based index of the attribute relative to the containing
2514 * element.
2515 *
2516 * Moves the position of the current instance to the attribute with
2517 * the specified index relative to the containing element.
2518 *
2519 * Returns 1 in case of success, -1 in case of error, 0 if not found
2520 */
2521int
2522xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2523 int i;
2524 xmlAttrPtr cur;
2525 xmlNsPtr ns;
2526
2527 if (reader == NULL)
2528 return(-1);
2529 if (reader->node == NULL)
2530 return(-1);
2531 /* TODO: handle the xmlDecl */
2532 if (reader->node->type != XML_ELEMENT_NODE)
2533 return(-1);
2534
2535 reader->curnode = NULL;
2536
2537 ns = reader->node->nsDef;
2538 for (i = 0;(i < no) && (ns != NULL);i++) {
2539 ns = ns->next;
2540 }
2541 if (ns != NULL) {
2542 reader->curnode = (xmlNodePtr) ns;
2543 return(1);
2544 }
2545
2546 cur = reader->node->properties;
2547 if (cur == NULL)
2548 return(0);
2549 for (;i < no;i++) {
2550 cur = cur->next;
2551 if (cur == NULL)
2552 return(0);
2553 }
2554 /* TODO walk the DTD if present */
2555
2556 reader->curnode = (xmlNodePtr) cur;
2557 return(1);
2558}
2559
2560/**
2561 * xmlTextReaderMoveToAttribute:
2562 * @reader: the xmlTextReaderPtr used
2563 * @name: the qualified name of the attribute.
2564 *
2565 * Moves the position of the current instance to the attribute with
2566 * the specified qualified name.
2567 *
2568 * Returns 1 in case of success, -1 in case of error, 0 if not found
2569 */
2570int
2571xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2572 xmlChar *prefix = NULL;
2573 xmlChar *localname;
2574 xmlNsPtr ns;
2575 xmlAttrPtr prop;
2576
2577 if ((reader == NULL) || (name == NULL))
2578 return(-1);
2579 if (reader->node == NULL)
2580 return(-1);
2581
2582 /* TODO: handle the xmlDecl */
2583 if (reader->node->type != XML_ELEMENT_NODE)
2584 return(0);
2585
2586 localname = xmlSplitQName2(name, &prefix);
2587 if (localname == NULL) {
2588 /*
2589 * Namespace default decl
2590 */
2591 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2592 ns = reader->node->nsDef;
2593 while (ns != NULL) {
2594 if (ns->prefix == NULL) {
2595 reader->curnode = (xmlNodePtr) ns;
2596 return(1);
2597 }
2598 ns = ns->next;
2599 }
2600 return(0);
2601 }
2602
2603 prop = reader->node->properties;
2604 while (prop != NULL) {
2605 /*
2606 * One need to have
2607 * - same attribute names
2608 * - and the attribute carrying that namespace
2609 */
2610 if ((xmlStrEqual(prop->name, name)) &&
2611 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2612 reader->curnode = (xmlNodePtr) prop;
2613 return(1);
2614 }
2615 prop = prop->next;
2616 }
2617 return(0);
2618 }
2619
2620 /*
2621 * Namespace default decl
2622 */
2623 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2624 ns = reader->node->nsDef;
2625 while (ns != NULL) {
2626 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2627 reader->curnode = (xmlNodePtr) ns;
2628 goto found;
2629 }
2630 ns = ns->next;
2631 }
2632 goto not_found;
2633 }
2634 prop = reader->node->properties;
2635 while (prop != NULL) {
2636 /*
2637 * One need to have
2638 * - same attribute names
2639 * - and the attribute carrying that namespace
2640 */
2641 if ((xmlStrEqual(prop->name, localname)) &&
2642 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2643 reader->curnode = (xmlNodePtr) prop;
2644 goto found;
2645 }
2646 prop = prop->next;
2647 }
2648not_found:
2649 if (localname != NULL)
2650 xmlFree(localname);
2651 if (prefix != NULL)
2652 xmlFree(prefix);
2653 return(0);
2654
2655found:
2656 if (localname != NULL)
2657 xmlFree(localname);
2658 if (prefix != NULL)
2659 xmlFree(prefix);
2660 return(1);
2661}
2662
2663/**
2664 * xmlTextReaderMoveToAttributeNs:
2665 * @reader: the xmlTextReaderPtr used
2666 * @localName: the local name of the attribute.
2667 * @namespaceURI: the namespace URI of the attribute.
2668 *
2669 * Moves the position of the current instance to the attribute with the
2670 * specified local name and namespace URI.
2671 *
2672 * Returns 1 in case of success, -1 in case of error, 0 if not found
2673 */
2674int
2675xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2676 const xmlChar *localName, const xmlChar *namespaceURI) {
2677 xmlAttrPtr prop;
2678 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002679 xmlNsPtr ns;
2680 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002681
2682 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2683 return(-1);
2684 if (reader->node == NULL)
2685 return(-1);
2686 if (reader->node->type != XML_ELEMENT_NODE)
2687 return(0);
2688 node = reader->node;
2689
Daniel Veillard45b97e72005-08-20 21:14:28 +00002690 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2691 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2692 prefix = BAD_CAST localName;
2693 }
2694 ns = reader->node->nsDef;
2695 while (ns != NULL) {
2696 if ((prefix == NULL && ns->prefix == NULL) ||
2697 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2698 reader->curnode = (xmlNodePtr) ns;
2699 return(1);
2700 }
2701 ns = ns->next;
2702 }
2703 return(0);
2704 }
2705
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002706 prop = node->properties;
2707 while (prop != NULL) {
2708 /*
2709 * One need to have
2710 * - same attribute names
2711 * - and the attribute carrying that namespace
2712 */
2713 if (xmlStrEqual(prop->name, localName) &&
2714 ((prop->ns != NULL) &&
2715 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2716 reader->curnode = (xmlNodePtr) prop;
2717 return(1);
2718 }
2719 prop = prop->next;
2720 }
2721 return(0);
2722}
2723
2724/**
2725 * xmlTextReaderMoveToFirstAttribute:
2726 * @reader: the xmlTextReaderPtr used
2727 *
2728 * Moves the position of the current instance to the first attribute
2729 * associated with the current node.
2730 *
2731 * Returns 1 in case of success, -1 in case of error, 0 if not found
2732 */
2733int
2734xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2735 if (reader == NULL)
2736 return(-1);
2737 if (reader->node == NULL)
2738 return(-1);
2739 if (reader->node->type != XML_ELEMENT_NODE)
2740 return(0);
2741
2742 if (reader->node->nsDef != NULL) {
2743 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2744 return(1);
2745 }
2746 if (reader->node->properties != NULL) {
2747 reader->curnode = (xmlNodePtr) reader->node->properties;
2748 return(1);
2749 }
2750 return(0);
2751}
2752
2753/**
2754 * xmlTextReaderMoveToNextAttribute:
2755 * @reader: the xmlTextReaderPtr used
2756 *
2757 * Moves the position of the current instance to the next attribute
2758 * associated with the current node.
2759 *
2760 * Returns 1 in case of success, -1 in case of error, 0 if not found
2761 */
2762int
2763xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2764 if (reader == NULL)
2765 return(-1);
2766 if (reader->node == NULL)
2767 return(-1);
2768 if (reader->node->type != XML_ELEMENT_NODE)
2769 return(0);
2770 if (reader->curnode == NULL)
2771 return(xmlTextReaderMoveToFirstAttribute(reader));
2772
2773 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2774 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2775 if (ns->next != NULL) {
2776 reader->curnode = (xmlNodePtr) ns->next;
2777 return(1);
2778 }
2779 if (reader->node->properties != NULL) {
2780 reader->curnode = (xmlNodePtr) reader->node->properties;
2781 return(1);
2782 }
2783 return(0);
2784 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2785 (reader->curnode->next != NULL)) {
2786 reader->curnode = reader->curnode->next;
2787 return(1);
2788 }
2789 return(0);
2790}
2791
2792/**
2793 * xmlTextReaderMoveToElement:
2794 * @reader: the xmlTextReaderPtr used
2795 *
2796 * Moves the position of the current instance to the node that
2797 * contains the current Attribute node.
2798 *
2799 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2800 */
2801int
2802xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2803 if (reader == NULL)
2804 return(-1);
2805 if (reader->node == NULL)
2806 return(-1);
2807 if (reader->node->type != XML_ELEMENT_NODE)
2808 return(0);
2809 if (reader->curnode != NULL) {
2810 reader->curnode = NULL;
2811 return(1);
2812 }
2813 return(0);
2814}
2815
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002816/**
2817 * xmlTextReaderReadAttributeValue:
2818 * @reader: the xmlTextReaderPtr used
2819 *
2820 * Parses an attribute value into one or more Text and EntityReference nodes.
2821 *
2822 * Returns 1 in case of success, 0 if the reader was not positionned on an
2823 * ttribute node or all the attribute values have been read, or -1
2824 * in case of error.
2825 */
2826int
2827xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2828 if (reader == NULL)
2829 return(-1);
2830 if (reader->node == NULL)
2831 return(-1);
2832 if (reader->curnode == NULL)
2833 return(0);
2834 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2835 if (reader->curnode->children == NULL)
2836 return(0);
2837 reader->curnode = reader->curnode->children;
2838 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2839 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2840
2841 if (reader->faketext == NULL) {
2842 reader->faketext = xmlNewDocText(reader->node->doc,
2843 ns->href);
2844 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002845 if ((reader->faketext->content != NULL) &&
2846 (reader->faketext->content !=
2847 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002848 xmlFree(reader->faketext->content);
2849 reader->faketext->content = xmlStrdup(ns->href);
2850 }
2851 reader->curnode = reader->faketext;
2852 } else {
2853 if (reader->curnode->next == NULL)
2854 return(0);
2855 reader->curnode = reader->curnode->next;
2856 }
2857 return(1);
2858}
2859
Daniel Veillarde2811272004-10-19 09:04:23 +00002860/**
2861 * xmlTextReaderConstEncoding:
2862 * @reader: the xmlTextReaderPtr used
2863 *
2864 * Determine the encoding of the document being read.
2865 *
2866 * Returns a string containing the encoding of the document or NULL in
2867 * case of error. The string is deallocated with the reader.
2868 */
2869const xmlChar *
2870xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2871 xmlDocPtr doc = NULL;
2872 if (reader == NULL)
2873 return(NULL);
2874 if (reader->doc != NULL)
2875 doc = reader->doc;
2876 else if (reader->ctxt != NULL)
2877 doc = reader->ctxt->myDoc;
2878 if (doc == NULL)
2879 return(NULL);
2880
2881 if (doc->encoding == NULL)
2882 return(NULL);
2883 else
2884 return(CONSTSTR(doc->encoding));
2885}
2886
2887
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002888/************************************************************************
2889 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002890 * Acces API to the current node *
2891 * *
2892 ************************************************************************/
2893/**
2894 * xmlTextReaderAttributeCount:
2895 * @reader: the xmlTextReaderPtr used
2896 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002897 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002898 *
2899 * Returns 0 i no attributes, -1 in case of error or the attribute count
2900 */
2901int
2902xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2903 int ret;
2904 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002905 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002906 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002907
2908 if (reader == NULL)
2909 return(-1);
2910 if (reader->node == NULL)
2911 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002912
2913 if (reader->curnode != NULL)
2914 node = reader->curnode;
2915 else
2916 node = reader->node;
2917
2918 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919 return(0);
2920 if ((reader->state == XML_TEXTREADER_END) ||
2921 (reader->state == XML_TEXTREADER_BACKTRACK))
2922 return(0);
2923 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002924 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002925 while (attr != NULL) {
2926 ret++;
2927 attr = attr->next;
2928 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002929 ns = node->nsDef;
2930 while (ns != NULL) {
2931 ret++;
2932 ns = ns->next;
2933 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002934 return(ret);
2935}
2936
2937/**
2938 * xmlTextReaderNodeType:
2939 * @reader: the xmlTextReaderPtr used
2940 *
2941 * Get the node type of the current node
2942 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002943 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002944 *
2945 * Returns the xmlNodeType of the current node or -1 in case of error
2946 */
2947int
2948xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002949 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002950
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002951 if (reader == NULL)
2952 return(-1);
2953 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002954 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002955 if (reader->curnode != NULL)
2956 node = reader->curnode;
2957 else
2958 node = reader->node;
2959 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002960 case XML_ELEMENT_NODE:
2961 if ((reader->state == XML_TEXTREADER_END) ||
2962 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002963 return(XML_READER_TYPE_END_ELEMENT);
2964 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002965 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002966 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002967 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002968 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002969 if (xmlIsBlankNode(reader->node)) {
2970 if (xmlNodeGetSpacePreserve(reader->node))
2971 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2972 else
2973 return(XML_READER_TYPE_WHITESPACE);
2974 } else {
2975 return(XML_READER_TYPE_TEXT);
2976 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002977 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002978 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002979 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002980 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002981 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002982 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002983 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002984 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002986 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002987 case XML_DOCUMENT_NODE:
2988 case XML_HTML_DOCUMENT_NODE:
2989#ifdef LIBXML_DOCB_ENABLED
2990 case XML_DOCB_DOCUMENT_NODE:
2991#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002992 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002993 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002994 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002995 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002996 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002997 case XML_DOCUMENT_TYPE_NODE:
2998 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002999 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003000
3001 case XML_ELEMENT_DECL:
3002 case XML_ATTRIBUTE_DECL:
3003 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003004 case XML_XINCLUDE_START:
3005 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003006 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003007 }
3008 return(-1);
3009}
3010
3011/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003012 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003013 * @reader: the xmlTextReaderPtr used
3014 *
3015 * Check if the current node is empty
3016 *
3017 * Returns 1 if empty, 0 if not and -1 in case of error
3018 */
3019int
3020xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3021 if ((reader == NULL) || (reader->node == NULL))
3022 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003023 if (reader->node->type != XML_ELEMENT_NODE)
3024 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003025 if (reader->curnode != NULL)
3026 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003027 if (reader->node->children != NULL)
3028 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003029 if (reader->state == XML_TEXTREADER_END)
3030 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003031 if (reader->doc != NULL)
3032 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003033#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003034 if (reader->in_xinclude > 0)
3035 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003036#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003037 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003038}
3039
3040/**
3041 * xmlTextReaderLocalName:
3042 * @reader: the xmlTextReaderPtr used
3043 *
3044 * The local name of the node.
3045 *
3046 * Returns the local name or NULL if not available
3047 */
3048xmlChar *
3049xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003050 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003051 if ((reader == NULL) || (reader->node == NULL))
3052 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003053 if (reader->curnode != NULL)
3054 node = reader->curnode;
3055 else
3056 node = reader->node;
3057 if (node->type == XML_NAMESPACE_DECL) {
3058 xmlNsPtr ns = (xmlNsPtr) node;
3059 if (ns->prefix == NULL)
3060 return(xmlStrdup(BAD_CAST "xmlns"));
3061 else
3062 return(xmlStrdup(ns->prefix));
3063 }
3064 if ((node->type != XML_ELEMENT_NODE) &&
3065 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003066 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003067 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003068}
3069
3070/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003071 * xmlTextReaderConstLocalName:
3072 * @reader: the xmlTextReaderPtr used
3073 *
3074 * The local name of the node.
3075 *
3076 * Returns the local name or NULL if not available, the
3077 * string will be deallocated with the reader.
3078 */
3079const xmlChar *
3080xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3081 xmlNodePtr node;
3082 if ((reader == NULL) || (reader->node == NULL))
3083 return(NULL);
3084 if (reader->curnode != NULL)
3085 node = reader->curnode;
3086 else
3087 node = reader->node;
3088 if (node->type == XML_NAMESPACE_DECL) {
3089 xmlNsPtr ns = (xmlNsPtr) node;
3090 if (ns->prefix == NULL)
3091 return(CONSTSTR(BAD_CAST "xmlns"));
3092 else
3093 return(ns->prefix);
3094 }
3095 if ((node->type != XML_ELEMENT_NODE) &&
3096 (node->type != XML_ATTRIBUTE_NODE))
3097 return(xmlTextReaderConstName(reader));
3098 return(node->name);
3099}
3100
3101/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003102 * xmlTextReaderName:
3103 * @reader: the xmlTextReaderPtr used
3104 *
3105 * The qualified name of the node, equal to Prefix :LocalName.
3106 *
3107 * Returns the local name or NULL if not available
3108 */
3109xmlChar *
3110xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003111 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003112 xmlChar *ret;
3113
3114 if ((reader == NULL) || (reader->node == NULL))
3115 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003116 if (reader->curnode != NULL)
3117 node = reader->curnode;
3118 else
3119 node = reader->node;
3120 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003121 case XML_ELEMENT_NODE:
3122 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003123 if ((node->ns == NULL) ||
3124 (node->ns->prefix == NULL))
3125 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003126
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003127 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003128 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003129 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003130 return(ret);
3131 case XML_TEXT_NODE:
3132 return(xmlStrdup(BAD_CAST "#text"));
3133 case XML_CDATA_SECTION_NODE:
3134 return(xmlStrdup(BAD_CAST "#cdata-section"));
3135 case XML_ENTITY_NODE:
3136 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003137 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003138 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003139 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003140 case XML_COMMENT_NODE:
3141 return(xmlStrdup(BAD_CAST "#comment"));
3142 case XML_DOCUMENT_NODE:
3143 case XML_HTML_DOCUMENT_NODE:
3144#ifdef LIBXML_DOCB_ENABLED
3145 case XML_DOCB_DOCUMENT_NODE:
3146#endif
3147 return(xmlStrdup(BAD_CAST "#document"));
3148 case XML_DOCUMENT_FRAG_NODE:
3149 return(xmlStrdup(BAD_CAST "#document-fragment"));
3150 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003151 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003152 case XML_DOCUMENT_TYPE_NODE:
3153 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003154 return(xmlStrdup(node->name));
3155 case XML_NAMESPACE_DECL: {
3156 xmlNsPtr ns = (xmlNsPtr) node;
3157
3158 ret = xmlStrdup(BAD_CAST "xmlns");
3159 if (ns->prefix == NULL)
3160 return(ret);
3161 ret = xmlStrcat(ret, BAD_CAST ":");
3162 ret = xmlStrcat(ret, ns->prefix);
3163 return(ret);
3164 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003165
3166 case XML_ELEMENT_DECL:
3167 case XML_ATTRIBUTE_DECL:
3168 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003169 case XML_XINCLUDE_START:
3170 case XML_XINCLUDE_END:
3171 return(NULL);
3172 }
3173 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003174}
3175
3176/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003177 * xmlTextReaderConstName:
3178 * @reader: the xmlTextReaderPtr used
3179 *
3180 * The qualified name of the node, equal to Prefix :LocalName.
3181 *
3182 * Returns the local name or NULL if not available, the string is
3183 * deallocated with the reader.
3184 */
3185const xmlChar *
3186xmlTextReaderConstName(xmlTextReaderPtr reader) {
3187 xmlNodePtr node;
3188
3189 if ((reader == NULL) || (reader->node == NULL))
3190 return(NULL);
3191 if (reader->curnode != NULL)
3192 node = reader->curnode;
3193 else
3194 node = reader->node;
3195 switch (node->type) {
3196 case XML_ELEMENT_NODE:
3197 case XML_ATTRIBUTE_NODE:
3198 if ((node->ns == NULL) ||
3199 (node->ns->prefix == NULL))
3200 return(node->name);
3201 return(CONSTQSTR(node->ns->prefix, node->name));
3202 case XML_TEXT_NODE:
3203 return(CONSTSTR(BAD_CAST "#text"));
3204 case XML_CDATA_SECTION_NODE:
3205 return(CONSTSTR(BAD_CAST "#cdata-section"));
3206 case XML_ENTITY_NODE:
3207 case XML_ENTITY_REF_NODE:
3208 return(CONSTSTR(node->name));
3209 case XML_PI_NODE:
3210 return(CONSTSTR(node->name));
3211 case XML_COMMENT_NODE:
3212 return(CONSTSTR(BAD_CAST "#comment"));
3213 case XML_DOCUMENT_NODE:
3214 case XML_HTML_DOCUMENT_NODE:
3215#ifdef LIBXML_DOCB_ENABLED
3216 case XML_DOCB_DOCUMENT_NODE:
3217#endif
3218 return(CONSTSTR(BAD_CAST "#document"));
3219 case XML_DOCUMENT_FRAG_NODE:
3220 return(CONSTSTR(BAD_CAST "#document-fragment"));
3221 case XML_NOTATION_NODE:
3222 return(CONSTSTR(node->name));
3223 case XML_DOCUMENT_TYPE_NODE:
3224 case XML_DTD_NODE:
3225 return(CONSTSTR(node->name));
3226 case XML_NAMESPACE_DECL: {
3227 xmlNsPtr ns = (xmlNsPtr) node;
3228
3229 if (ns->prefix == NULL)
3230 return(CONSTSTR(BAD_CAST "xmlns"));
3231 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3232 }
3233
3234 case XML_ELEMENT_DECL:
3235 case XML_ATTRIBUTE_DECL:
3236 case XML_ENTITY_DECL:
3237 case XML_XINCLUDE_START:
3238 case XML_XINCLUDE_END:
3239 return(NULL);
3240 }
3241 return(NULL);
3242}
3243
3244/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003245 * xmlTextReaderPrefix:
3246 * @reader: the xmlTextReaderPtr used
3247 *
3248 * A shorthand reference to the namespace associated with the node.
3249 *
3250 * Returns the prefix or NULL if not available
3251 */
3252xmlChar *
3253xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003254 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003255 if ((reader == NULL) || (reader->node == NULL))
3256 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003257 if (reader->curnode != NULL)
3258 node = reader->curnode;
3259 else
3260 node = reader->node;
3261 if (node->type == XML_NAMESPACE_DECL) {
3262 xmlNsPtr ns = (xmlNsPtr) node;
3263 if (ns->prefix == NULL)
3264 return(NULL);
3265 return(xmlStrdup(BAD_CAST "xmlns"));
3266 }
3267 if ((node->type != XML_ELEMENT_NODE) &&
3268 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003269 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003270 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003271 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003272 return(NULL);
3273}
3274
3275/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003276 * xmlTextReaderConstPrefix:
3277 * @reader: the xmlTextReaderPtr used
3278 *
3279 * A shorthand reference to the namespace associated with the node.
3280 *
3281 * Returns the prefix or NULL if not available, the string is deallocated
3282 * with the reader.
3283 */
3284const xmlChar *
3285xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3286 xmlNodePtr node;
3287 if ((reader == NULL) || (reader->node == NULL))
3288 return(NULL);
3289 if (reader->curnode != NULL)
3290 node = reader->curnode;
3291 else
3292 node = reader->node;
3293 if (node->type == XML_NAMESPACE_DECL) {
3294 xmlNsPtr ns = (xmlNsPtr) node;
3295 if (ns->prefix == NULL)
3296 return(NULL);
3297 return(CONSTSTR(BAD_CAST "xmlns"));
3298 }
3299 if ((node->type != XML_ELEMENT_NODE) &&
3300 (node->type != XML_ATTRIBUTE_NODE))
3301 return(NULL);
3302 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3303 return(CONSTSTR(node->ns->prefix));
3304 return(NULL);
3305}
3306
3307/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003308 * xmlTextReaderNamespaceUri:
3309 * @reader: the xmlTextReaderPtr used
3310 *
3311 * The URI defining the namespace associated with the node.
3312 *
3313 * Returns the namespace URI or NULL if not available
3314 */
3315xmlChar *
3316xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003317 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003318 if ((reader == NULL) || (reader->node == NULL))
3319 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003320 if (reader->curnode != NULL)
3321 node = reader->curnode;
3322 else
3323 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003324 if (node->type == XML_NAMESPACE_DECL)
3325 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003326 if ((node->type != XML_ELEMENT_NODE) &&
3327 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003328 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003329 if (node->ns != NULL)
3330 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003331 return(NULL);
3332}
3333
3334/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003335 * xmlTextReaderConstNamespaceUri:
3336 * @reader: the xmlTextReaderPtr used
3337 *
3338 * The URI defining the namespace associated with the node.
3339 *
3340 * Returns the namespace URI or NULL if not available, the string
3341 * will be deallocated with the reader
3342 */
3343const xmlChar *
3344xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3345 xmlNodePtr node;
3346 if ((reader == NULL) || (reader->node == NULL))
3347 return(NULL);
3348 if (reader->curnode != NULL)
3349 node = reader->curnode;
3350 else
3351 node = reader->node;
3352 if (node->type == XML_NAMESPACE_DECL)
3353 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3354 if ((node->type != XML_ELEMENT_NODE) &&
3355 (node->type != XML_ATTRIBUTE_NODE))
3356 return(NULL);
3357 if (node->ns != NULL)
3358 return(CONSTSTR(node->ns->href));
3359 return(NULL);
3360}
3361
3362/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003363 * xmlTextReaderBaseUri:
3364 * @reader: the xmlTextReaderPtr used
3365 *
3366 * The base URI of the node.
3367 *
3368 * Returns the base URI or NULL if not available
3369 */
3370xmlChar *
3371xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3372 if ((reader == NULL) || (reader->node == NULL))
3373 return(NULL);
3374 return(xmlNodeGetBase(NULL, reader->node));
3375}
3376
3377/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003378 * xmlTextReaderConstBaseUri:
3379 * @reader: the xmlTextReaderPtr used
3380 *
3381 * The base URI of the node.
3382 *
3383 * Returns the base URI or NULL if not available, the string
3384 * will be deallocated with the reader
3385 */
3386const xmlChar *
3387xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3388 xmlChar *tmp;
3389 const xmlChar *ret;
3390
3391 if ((reader == NULL) || (reader->node == NULL))
3392 return(NULL);
3393 tmp = xmlNodeGetBase(NULL, reader->node);
3394 if (tmp == NULL)
3395 return(NULL);
3396 ret = CONSTSTR(tmp);
3397 xmlFree(tmp);
3398 return(ret);
3399}
3400
3401/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003402 * xmlTextReaderDepth:
3403 * @reader: the xmlTextReaderPtr used
3404 *
3405 * The depth of the node in the tree.
3406 *
3407 * Returns the depth or -1 in case of error
3408 */
3409int
3410xmlTextReaderDepth(xmlTextReaderPtr reader) {
3411 if (reader == NULL)
3412 return(-1);
3413 if (reader->node == NULL)
3414 return(0);
3415
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003416 if (reader->curnode != NULL) {
3417 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3418 (reader->curnode->type == XML_NAMESPACE_DECL))
3419 return(reader->depth + 1);
3420 return(reader->depth + 2);
3421 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003422 return(reader->depth);
3423}
3424
3425/**
3426 * xmlTextReaderHasAttributes:
3427 * @reader: the xmlTextReaderPtr used
3428 *
3429 * Whether the node has attributes.
3430 *
3431 * Returns 1 if true, 0 if false, and -1 in case or error
3432 */
3433int
3434xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003435 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003436 if (reader == NULL)
3437 return(-1);
3438 if (reader->node == NULL)
3439 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003440 if (reader->curnode != NULL)
3441 node = reader->curnode;
3442 else
3443 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003444
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003445 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003446 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003447 return(1);
3448 /* TODO: handle the xmlDecl */
3449 return(0);
3450}
3451
3452/**
3453 * xmlTextReaderHasValue:
3454 * @reader: the xmlTextReaderPtr used
3455 *
3456 * Whether the node can have a text value.
3457 *
3458 * Returns 1 if true, 0 if false, and -1 in case or error
3459 */
3460int
3461xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003462 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003463 if (reader == NULL)
3464 return(-1);
3465 if (reader->node == NULL)
3466 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003467 if (reader->curnode != NULL)
3468 node = reader->curnode;
3469 else
3470 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003471
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003472 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003473 case XML_ATTRIBUTE_NODE:
3474 case XML_TEXT_NODE:
3475 case XML_CDATA_SECTION_NODE:
3476 case XML_PI_NODE:
3477 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003478 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003479 return(1);
3480 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003481 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003482 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003483 return(0);
3484}
3485
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003486/**
3487 * xmlTextReaderValue:
3488 * @reader: the xmlTextReaderPtr used
3489 *
3490 * Provides the text value of the node if present
3491 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003492 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003493 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003494 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003495xmlChar *
3496xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003497 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003498 if (reader == NULL)
3499 return(NULL);
3500 if (reader->node == NULL)
3501 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003502 if (reader->curnode != NULL)
3503 node = reader->curnode;
3504 else
3505 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003506
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003507 switch (node->type) {
3508 case XML_NAMESPACE_DECL:
3509 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003510 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003511 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003512
3513 if (attr->parent != NULL)
3514 return (xmlNodeListGetString
3515 (attr->parent->doc, attr->children, 1));
3516 else
3517 return (xmlNodeListGetString(NULL, attr->children, 1));
3518 break;
3519 }
3520 case XML_TEXT_NODE:
3521 case XML_CDATA_SECTION_NODE:
3522 case XML_PI_NODE:
3523 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003524 if (node->content != NULL)
3525 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003526 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003527 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003528 }
3529 return(NULL);
3530}
3531
3532/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003533 * xmlTextReaderConstValue:
3534 * @reader: the xmlTextReaderPtr used
3535 *
3536 * Provides the text value of the node if present
3537 *
3538 * Returns the string or NULL if not available. The result will be
3539 * deallocated on the next Read() operation.
3540 */
3541const xmlChar *
3542xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3543 xmlNodePtr node;
3544 if (reader == NULL)
3545 return(NULL);
3546 if (reader->node == NULL)
3547 return(NULL);
3548 if (reader->curnode != NULL)
3549 node = reader->curnode;
3550 else
3551 node = reader->node;
3552
3553 switch (node->type) {
3554 case XML_NAMESPACE_DECL:
3555 return(((xmlNsPtr) node)->href);
3556 case XML_ATTRIBUTE_NODE:{
3557 xmlAttrPtr attr = (xmlAttrPtr) node;
3558
3559 if ((attr->children != NULL) &&
3560 (attr->children->type == XML_TEXT_NODE) &&
3561 (attr->children->next == NULL))
3562 return(attr->children->content);
3563 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003564 if (reader->buffer == NULL)
3565 reader->buffer = xmlBufferCreateSize(100);
3566 if (reader->buffer == NULL) {
3567 xmlGenericError(xmlGenericErrorContext,
3568 "xmlTextReaderSetup : malloc failed\n");
3569 return (NULL);
3570 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003571 reader->buffer->use = 0;
3572 xmlNodeBufGetContent(reader->buffer, node);
3573 return(reader->buffer->content);
3574 }
3575 break;
3576 }
3577 case XML_TEXT_NODE:
3578 case XML_CDATA_SECTION_NODE:
3579 case XML_PI_NODE:
3580 case XML_COMMENT_NODE:
3581 return(node->content);
3582 default:
3583 break;
3584 }
3585 return(NULL);
3586}
3587
3588/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003589 * xmlTextReaderIsDefault:
3590 * @reader: the xmlTextReaderPtr used
3591 *
3592 * Whether an Attribute node was generated from the default value
3593 * defined in the DTD or schema.
3594 *
3595 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3596 */
3597int
3598xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3599 if (reader == NULL)
3600 return(-1);
3601 return(0);
3602}
3603
3604/**
3605 * xmlTextReaderQuoteChar:
3606 * @reader: the xmlTextReaderPtr used
3607 *
3608 * The quotation mark character used to enclose the value of an attribute.
3609 *
3610 * Returns " or ' and -1 in case of error
3611 */
3612int
3613xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3614 if (reader == NULL)
3615 return(-1);
3616 /* TODO maybe lookup the attribute value for " first */
3617 return((int) '"');
3618}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003619
3620/**
3621 * xmlTextReaderXmlLang:
3622 * @reader: the xmlTextReaderPtr used
3623 *
3624 * The xml:lang scope within which the node resides.
3625 *
3626 * Returns the xml:lang value or NULL if none exists.
3627 */
3628xmlChar *
3629xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3630 if (reader == NULL)
3631 return(NULL);
3632 if (reader->node == NULL)
3633 return(NULL);
3634 return(xmlNodeGetLang(reader->node));
3635}
3636
Daniel Veillard67df8092002-12-16 22:04:11 +00003637/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003638 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003639 * @reader: the xmlTextReaderPtr used
3640 *
3641 * The xml:lang scope within which the node resides.
3642 *
3643 * Returns the xml:lang value or NULL if none exists.
3644 */
3645const xmlChar *
3646xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3647 xmlChar *tmp;
3648 const xmlChar *ret;
3649
3650 if (reader == NULL)
3651 return(NULL);
3652 if (reader->node == NULL)
3653 return(NULL);
3654 tmp = xmlNodeGetLang(reader->node);
3655 if (tmp == NULL)
3656 return(NULL);
3657 ret = CONSTSTR(tmp);
3658 xmlFree(tmp);
3659 return(ret);
3660}
3661
3662/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003663 * xmlTextReaderConstString:
3664 * @reader: the xmlTextReaderPtr used
3665 * @str: the string to intern.
3666 *
3667 * Get an interned string from the reader, allows for example to
3668 * speedup string name comparisons
3669 *
3670 * Returns an interned copy of the string or NULL in case of error. The
3671 * string will be deallocated with the reader.
3672 */
3673const xmlChar *
3674xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3675 if (reader == NULL)
3676 return(NULL);
3677 return(CONSTSTR(str));
3678}
3679
3680/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003681 * xmlTextReaderNormalization:
3682 * @reader: the xmlTextReaderPtr used
3683 *
3684 * The value indicating whether to normalize white space and attribute values.
3685 * Since attribute value and end of line normalizations are a MUST in the XML
3686 * specification only the value true is accepted. The broken bahaviour of
3687 * accepting out of range character entities like &#0; is of course not
3688 * supported either.
3689 *
3690 * Returns 1 or -1 in case of error.
3691 */
3692int
3693xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3694 if (reader == NULL)
3695 return(-1);
3696 return(1);
3697}
3698
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003699/************************************************************************
3700 * *
3701 * Extensions to the base APIs *
3702 * *
3703 ************************************************************************/
3704
3705/**
3706 * xmlTextReaderSetParserProp:
3707 * @reader: the xmlTextReaderPtr used
3708 * @prop: the xmlParserProperties to set
3709 * @value: usually 0 or 1 to (de)activate it
3710 *
3711 * Change the parser processing behaviour by changing some of its internal
3712 * properties. Note that some properties can only be changed before any
3713 * read has been done.
3714 *
3715 * Returns 0 if the call was successful, or -1 in case of error
3716 */
3717int
3718xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3719 xmlParserProperties p = (xmlParserProperties) prop;
3720 xmlParserCtxtPtr ctxt;
3721
3722 if ((reader == NULL) || (reader->ctxt == NULL))
3723 return(-1);
3724 ctxt = reader->ctxt;
3725
3726 switch (p) {
3727 case XML_PARSER_LOADDTD:
3728 if (value != 0) {
3729 if (ctxt->loadsubset == 0) {
3730 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3731 return(-1);
3732 ctxt->loadsubset = XML_DETECT_IDS;
3733 }
3734 } else {
3735 ctxt->loadsubset = 0;
3736 }
3737 return(0);
3738 case XML_PARSER_DEFAULTATTRS:
3739 if (value != 0) {
3740 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3741 } else {
3742 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3743 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3744 }
3745 return(0);
3746 case XML_PARSER_VALIDATE:
3747 if (value != 0) {
3748 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003749 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003750 } else {
3751 ctxt->validate = 0;
3752 }
3753 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003754 case XML_PARSER_SUBST_ENTITIES:
3755 if (value != 0) {
3756 ctxt->replaceEntities = 1;
3757 } else {
3758 ctxt->replaceEntities = 0;
3759 }
3760 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003761 }
3762 return(-1);
3763}
3764
3765/**
3766 * xmlTextReaderGetParserProp:
3767 * @reader: the xmlTextReaderPtr used
3768 * @prop: the xmlParserProperties to get
3769 *
3770 * Read the parser internal property.
3771 *
3772 * Returns the value, usually 0 or 1, or -1 in case of error.
3773 */
3774int
3775xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3776 xmlParserProperties p = (xmlParserProperties) prop;
3777 xmlParserCtxtPtr ctxt;
3778
3779 if ((reader == NULL) || (reader->ctxt == NULL))
3780 return(-1);
3781 ctxt = reader->ctxt;
3782
3783 switch (p) {
3784 case XML_PARSER_LOADDTD:
3785 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3786 return(1);
3787 return(0);
3788 case XML_PARSER_DEFAULTATTRS:
3789 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3790 return(1);
3791 return(0);
3792 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003793 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003794 case XML_PARSER_SUBST_ENTITIES:
3795 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003796 }
3797 return(-1);
3798}
3799
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003800
Daniel Veillarde18fc182002-12-28 22:56:33 +00003801/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003802 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003803 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003804 *
3805 * Provide the line number of the current parsing point.
3806 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003807 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003808 */
3809int
3810xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3811{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003812 if ((reader == NULL) || (reader->ctxt == NULL) ||
3813 (reader->ctxt->input == NULL)) {
3814 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003815 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003816 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003817}
3818
3819/**
3820 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003821 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003822 *
3823 * Provide the column number of the current parsing point.
3824 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003825 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003826 */
3827int
3828xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3829{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003830 if ((reader == NULL) || (reader->ctxt == NULL) ||
3831 (reader->ctxt->input == NULL)) {
3832 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003833 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003834 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003835}
3836
3837/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003838 * xmlTextReaderCurrentNode:
3839 * @reader: the xmlTextReaderPtr used
3840 *
3841 * Hacking interface allowing to get the xmlNodePtr correponding to the
3842 * current node being accessed by the xmlTextReader. This is dangerous
3843 * because the underlying node may be destroyed on the next Reads.
3844 *
3845 * Returns the xmlNodePtr or NULL in case of error.
3846 */
3847xmlNodePtr
3848xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3849 if (reader == NULL)
3850 return(NULL);
3851
3852 if (reader->curnode != NULL)
3853 return(reader->curnode);
3854 return(reader->node);
3855}
3856
3857/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003858 * xmlTextReaderPreserve:
3859 * @reader: the xmlTextReaderPtr used
3860 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003861 * This tells the XML Reader to preserve the current node.
3862 * The caller must also use xmlTextReaderCurrentDoc() to
3863 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003864 *
3865 * Returns the xmlNodePtr or NULL in case of error.
3866 */
3867xmlNodePtr
3868xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3869 xmlNodePtr cur, parent;
3870
3871 if (reader == NULL)
3872 return(NULL);
3873
3874 if (reader->curnode != NULL)
3875 cur = reader->curnode;
3876 else
3877 cur = reader->node;
3878 if (cur == NULL)
3879 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003880
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003881 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003882 cur->extra |= NODE_IS_PRESERVED;
3883 cur->extra |= NODE_IS_SPRESERVED;
3884 }
3885 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003886
3887 parent = cur->parent;;
3888 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003889 if (parent->type == XML_ELEMENT_NODE)
3890 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003891 parent = parent->parent;
3892 }
3893 return(cur);
3894}
3895
Daniel Veillard1e906612003-12-05 14:57:46 +00003896#ifdef LIBXML_PATTERN_ENABLED
3897/**
3898 * xmlTextReaderPreservePattern:
3899 * @reader: the xmlTextReaderPtr used
3900 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003901 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003902 *
3903 * This tells the XML Reader to preserve all nodes matched by the
3904 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3905 * keep an handle on the resulting document once parsing has finished
3906 *
3907 * Returns a positive number in case of success and -1 in case of error
3908 */
3909int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003910xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3911 const xmlChar **namespaces)
3912{
Daniel Veillard1e906612003-12-05 14:57:46 +00003913 xmlPatternPtr comp;
3914
3915 if ((reader == NULL) || (pattern == NULL))
3916 return(-1);
3917
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003918 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003919 if (comp == NULL)
3920 return(-1);
3921
3922 if (reader->patternMax <= 0) {
3923 reader->patternMax = 4;
3924 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3925 sizeof(reader->patternTab[0]));
3926 if (reader->patternTab == NULL) {
3927 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3928 return (-1);
3929 }
3930 }
3931 if (reader->patternNr >= reader->patternMax) {
3932 xmlPatternPtr *tmp;
3933 reader->patternMax *= 2;
3934 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3935 reader->patternMax *
3936 sizeof(reader->patternTab[0]));
3937 if (tmp == NULL) {
3938 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3939 reader->patternMax /= 2;
3940 return (-1);
3941 }
3942 reader->patternTab = tmp;
3943 }
3944 reader->patternTab[reader->patternNr] = comp;
3945 return(reader->patternNr++);
3946}
3947#endif
3948
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003949/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003950 * xmlTextReaderCurrentDoc:
3951 * @reader: the xmlTextReaderPtr used
3952 *
3953 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003954 * current document being accessed by the xmlTextReader.
3955 * NOTE: as a result of this call, the reader will not destroy the
3956 * associated XML document and calling xmlFreeDoc() on the result
3957 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003958 *
3959 * Returns the xmlDocPtr or NULL in case of error.
3960 */
3961xmlDocPtr
3962xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003963 if (reader == NULL)
3964 return(NULL);
3965 if (reader->doc != NULL)
3966 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00003967 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003968 return(NULL);
3969
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003970 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003971 return(reader->ctxt->myDoc);
3972}
3973
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003974#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003975
3976static char *
3977xmlTextReaderBuildMessage(const char *msg, va_list ap);
3978
Daniel Veillardffa3c742005-07-21 13:24:09 +00003979static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003980xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3981
Daniel Veillardffa3c742005-07-21 13:24:09 +00003982static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003983xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3984
Daniel Veillardffa3c742005-07-21 13:24:09 +00003985static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003986{
3987 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3988 char * str;
3989 va_list ap;
3990
3991 va_start(ap,msg);
3992 str = xmlTextReaderBuildMessage(msg,ap);
3993 if (!reader->errorFunc) {
3994 xmlTextReaderValidityError(ctx, "%s", str);
3995 } else {
3996 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3997 }
3998 if (str != NULL)
3999 xmlFree(str);
4000 va_end(ap);
4001}
4002
Daniel Veillardffa3c742005-07-21 13:24:09 +00004003static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004004{
4005 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4006 char * str;
4007 va_list ap;
4008
4009 va_start(ap,msg);
4010 str = xmlTextReaderBuildMessage(msg,ap);
4011 if (!reader->errorFunc) {
4012 xmlTextReaderValidityWarning(ctx, "%s", str);
4013 } else {
4014 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
4015 }
4016 if (str != NULL)
4017 xmlFree(str);
4018 va_end(ap);
4019}
4020
4021static void
4022xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4023
4024static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4025{
4026 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4027
4028 if (reader->sErrorFunc) {
4029 reader->sErrorFunc(reader->errorFuncArg, error);
4030 } else {
4031 xmlTextReaderStructuredError(reader, error);
4032 }
4033}
4034
Daniel Veillardf4e55762003-04-15 23:32:22 +00004035/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004036 * xmlTextReaderRelaxNGSetSchema:
4037 * @reader: the xmlTextReaderPtr used
4038 * @schema: a precompiled RelaxNG schema
4039 *
4040 * Use RelaxNG to validate the document as it is processed.
4041 * Activation is only possible before the first Read().
4042 * if @schema is NULL, then RelaxNG validation is desactivated.
4043 @ The @schema should not be freed until the reader is deallocated
4044 * or its use has been deactivated.
4045 *
4046 * Returns 0 in case the RelaxNG validation could be (des)activated and
4047 * -1 in case of error.
4048 */
4049int
4050xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004051 if (reader == NULL)
4052 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004053 if (schema == NULL) {
4054 if (reader->rngSchemas != NULL) {
4055 xmlRelaxNGFree(reader->rngSchemas);
4056 reader->rngSchemas = NULL;
4057 }
4058 if (reader->rngValidCtxt != NULL) {
4059 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4060 reader->rngValidCtxt = NULL;
4061 }
4062 return(0);
4063 }
4064 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4065 return(-1);
4066 if (reader->rngSchemas != NULL) {
4067 xmlRelaxNGFree(reader->rngSchemas);
4068 reader->rngSchemas = NULL;
4069 }
4070 if (reader->rngValidCtxt != NULL) {
4071 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4072 reader->rngValidCtxt = NULL;
4073 }
4074 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4075 if (reader->rngValidCtxt == NULL)
4076 return(-1);
4077 if (reader->errorFunc != NULL) {
4078 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004079 xmlTextReaderValidityErrorRelay,
4080 xmlTextReaderValidityWarningRelay,
4081 reader);
4082 }
4083 if (reader->sErrorFunc != NULL) {
4084 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4085 xmlTextReaderValidityStructuredRelay,
4086 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004087 }
4088 reader->rngValidErrors = 0;
4089 reader->rngFullNode = NULL;
4090 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4091 return(0);
4092}
4093
4094/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004095 * xmlTextReaderSetSchema:
4096 * @reader: the xmlTextReaderPtr used
4097 * @schema: a precompiled Schema schema
4098 *
4099 * Use XSD Schema to validate the document as it is processed.
4100 * Activation is only possible before the first Read().
4101 * if @schema is NULL, then Schema validation is desactivated.
4102 @ The @schema should not be freed until the reader is deallocated
4103 * or its use has been deactivated.
4104 *
4105 * Returns 0 in case the Schema validation could be (des)activated and
4106 * -1 in case of error.
4107 */
4108int
4109xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4110 if (reader == NULL)
4111 return(-1);
4112 if (schema == NULL) {
4113 if (reader->xsdPlug != NULL) {
4114 xmlSchemaSAXUnplug(reader->xsdPlug);
4115 reader->xsdPlug = NULL;
4116 }
4117 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004118 if (! reader->xsdPreserveCtxt)
4119 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4120 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004121 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004122 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004123 if (reader->xsdSchemas != NULL) {
4124 xmlSchemaFree(reader->xsdSchemas);
4125 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004126 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004127 return(0);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004128 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004129 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4130 return(-1);
4131 if (reader->xsdPlug != NULL) {
4132 xmlSchemaSAXUnplug(reader->xsdPlug);
4133 reader->xsdPlug = NULL;
4134 }
4135 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004136 if (! reader->xsdPreserveCtxt)
4137 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004138 reader->xsdValidCtxt = NULL;
4139 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004140 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004141 if (reader->xsdSchemas != NULL) {
4142 xmlSchemaFree(reader->xsdSchemas);
4143 reader->xsdSchemas = NULL;
4144 }
4145 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4146 if (reader->xsdValidCtxt == NULL) {
4147 xmlSchemaFree(reader->xsdSchemas);
4148 reader->xsdSchemas = NULL;
4149 return(-1);
4150 }
4151 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4152 &(reader->ctxt->sax),
4153 &(reader->ctxt->userData));
4154 if (reader->xsdPlug == NULL) {
4155 xmlSchemaFree(reader->xsdSchemas);
4156 reader->xsdSchemas = NULL;
4157 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4158 reader->xsdValidCtxt = NULL;
4159 return(-1);
4160 }
4161 if (reader->errorFunc != NULL) {
4162 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004163 xmlTextReaderValidityErrorRelay,
4164 xmlTextReaderValidityWarningRelay,
4165 reader);
4166 }
4167 if (reader->sErrorFunc != NULL) {
4168 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4169 xmlTextReaderValidityStructuredRelay,
4170 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004171 }
4172 reader->xsdValidErrors = 0;
4173 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4174 return(0);
4175}
4176
4177/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004178 * xmlTextReaderRelaxNGValidate:
4179 * @reader: the xmlTextReaderPtr used
4180 * @rng: the path to a RelaxNG schema or NULL
4181 *
4182 * Use RelaxNG to validate the document as it is processed.
4183 * Activation is only possible before the first Read().
William M. Brackd46c1ca2007-02-08 23:34:34 +00004184 * if @rng is NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004185 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004186 * Returns 0 in case the RelaxNG validation could be (de)activated and
Daniel Veillardf4e55762003-04-15 23:32:22 +00004187 * -1 in case of error.
4188 */
4189int
4190xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4191 xmlRelaxNGParserCtxtPtr ctxt;
4192
4193 if (reader == NULL)
4194 return(-1);
4195
4196 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004197 if (reader->rngValidCtxt != NULL) {
4198 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4199 reader->rngValidCtxt = NULL;
4200 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004201 if (reader->rngSchemas != NULL) {
4202 xmlRelaxNGFree(reader->rngSchemas);
4203 reader->rngSchemas = NULL;
4204 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004205 return(0);
4206 }
4207 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4208 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004209 if (reader->rngSchemas != NULL) {
4210 xmlRelaxNGFree(reader->rngSchemas);
4211 reader->rngSchemas = NULL;
4212 }
4213 if (reader->rngValidCtxt != NULL) {
4214 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4215 reader->rngValidCtxt = NULL;
4216 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004217 ctxt = xmlRelaxNGNewParserCtxt(rng);
4218 if (reader->errorFunc != NULL) {
4219 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004220 xmlTextReaderValidityErrorRelay,
4221 xmlTextReaderValidityWarningRelay,
4222 reader);
4223 }
William M. Brackd46c1ca2007-02-08 23:34:34 +00004224 if (reader->sErrorFunc != NULL) {
4225 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004226 xmlTextReaderValidityStructuredRelay,
4227 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004228 }
4229 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4230 xmlRelaxNGFreeParserCtxt(ctxt);
4231 if (reader->rngSchemas == NULL)
4232 return(-1);
4233 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004234 if (reader->rngValidCtxt == NULL) {
4235 xmlRelaxNGFree(reader->rngSchemas);
4236 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004237 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004238 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004239 if (reader->errorFunc != NULL) {
4240 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004241 xmlTextReaderValidityErrorRelay,
4242 xmlTextReaderValidityWarningRelay,
4243 reader);
4244 }
4245 if (reader->sErrorFunc != NULL) {
4246 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4247 xmlTextReaderValidityStructuredRelay,
4248 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004249 }
4250 reader->rngValidErrors = 0;
4251 reader->rngFullNode = NULL;
4252 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4253 return(0);
4254}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004255
4256/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004257 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004258 * @reader: the xmlTextReaderPtr used
4259 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004260 * @ctxt: the XML Schema validation context or NULL
4261 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004262 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004263 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004264 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004265 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004266 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004267 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004268 * -1 in case of error.
4269 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004270static int
4271xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4272 const char *xsd,
4273 xmlSchemaValidCtxtPtr ctxt,
4274 int options ATTRIBUTE_UNUSED)
4275{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004276 if (reader == NULL)
4277 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004278
4279 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004280 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004281
4282 if (((xsd != NULL) || (ctxt != NULL)) &&
4283 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4284 (reader->ctxt == NULL)))
4285 return(-1);
4286
4287 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004288 if (reader->xsdPlug != NULL) {
4289 xmlSchemaSAXUnplug(reader->xsdPlug);
4290 reader->xsdPlug = NULL;
4291 }
4292 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004293 if (! reader->xsdPreserveCtxt)
4294 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004295 reader->xsdValidCtxt = NULL;
4296 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004297 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004298 if (reader->xsdSchemas != NULL) {
4299 xmlSchemaFree(reader->xsdSchemas);
4300 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004301 }
4302
4303 if ((xsd == NULL) && (ctxt == NULL)) {
4304 /* We just want to deactivate the validation, so get out. */
4305 return(0);
4306 }
4307
4308 if (xsd != NULL) {
4309 xmlSchemaParserCtxtPtr pctxt;
4310 /* Parse the schema and create validation environment. */
4311 pctxt = xmlSchemaNewParserCtxt(xsd);
4312 if (reader->errorFunc != NULL) {
4313 xmlSchemaSetParserErrors(pctxt,
4314 xmlTextReaderValidityErrorRelay,
4315 xmlTextReaderValidityWarningRelay,
4316 reader);
4317 }
4318 reader->xsdSchemas = xmlSchemaParse(pctxt);
4319 xmlSchemaFreeParserCtxt(pctxt);
4320 if (reader->xsdSchemas == NULL)
4321 return(-1);
4322 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4323 if (reader->xsdValidCtxt == NULL) {
4324 xmlSchemaFree(reader->xsdSchemas);
4325 reader->xsdSchemas = NULL;
4326 return(-1);
4327 }
4328 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4329 &(reader->ctxt->sax),
4330 &(reader->ctxt->userData));
4331 if (reader->xsdPlug == NULL) {
4332 xmlSchemaFree(reader->xsdSchemas);
4333 reader->xsdSchemas = NULL;
4334 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4335 reader->xsdValidCtxt = NULL;
4336 return(-1);
4337 }
4338 } else {
4339 /* Use the given validation context. */
4340 reader->xsdValidCtxt = ctxt;
4341 reader->xsdPreserveCtxt = 1;
4342 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4343 &(reader->ctxt->sax),
4344 &(reader->ctxt->userData));
4345 if (reader->xsdPlug == NULL) {
4346 reader->xsdValidCtxt = NULL;
4347 reader->xsdPreserveCtxt = 0;
4348 return(-1);
4349 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004350 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004351 /*
4352 * Redirect the validation context's error channels to use
4353 * the reader channels.
4354 * TODO: In case the user provides the validation context we
4355 * could make this redirection optional.
4356 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004357 if (reader->errorFunc != NULL) {
4358 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004359 xmlTextReaderValidityErrorRelay,
4360 xmlTextReaderValidityWarningRelay,
4361 reader);
4362 }
4363 if (reader->sErrorFunc != NULL) {
4364 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4365 xmlTextReaderValidityStructuredRelay,
4366 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004367 }
4368 reader->xsdValidErrors = 0;
4369 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4370 return(0);
4371}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004372
4373/**
4374 * xmlTextReaderSchemaValidateCtxt:
4375 * @reader: the xmlTextReaderPtr used
4376 * @ctxt: the XML Schema validation context or NULL
4377 * @options: options (not used yet)
4378 *
4379 * Use W3C XSD schema context to validate the document as it is processed.
4380 * Activation is only possible before the first Read().
4381 * If @ctxt is NULL, then XML Schema validation is deactivated.
4382 *
4383 * Returns 0 in case the schemas validation could be (de)activated and
4384 * -1 in case of error.
4385 */
4386int
4387xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4388 xmlSchemaValidCtxtPtr ctxt,
4389 int options)
4390{
4391 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4392}
4393
4394/**
4395 * xmlTextReaderSchemaValidate:
4396 * @reader: the xmlTextReaderPtr used
4397 * @xsd: the path to a W3C XSD schema or NULL
4398 *
4399 * Use W3C XSD schema to validate the document as it is processed.
4400 * Activation is only possible before the first Read().
4401 * If @xsd is NULL, then XML Schema validation is deactivated.
4402 *
4403 * Returns 0 in case the schemas validation could be (de)activated and
4404 * -1 in case of error.
4405 */
4406int
4407xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4408{
4409 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4410}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004411#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004412
Daniel Veillarde2811272004-10-19 09:04:23 +00004413/**
4414 * xmlTextReaderIsNamespaceDecl:
4415 * @reader: the xmlTextReaderPtr used
4416 *
4417 * Determine whether the current node is a namespace declaration
4418 * rather than a regular attribute.
4419 *
4420 * Returns 1 if the current node is a namespace declaration, 0 if it
4421 * is a regular attribute or other type of node, or -1 in case of
4422 * error.
4423 */
4424int
4425xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4426 xmlNodePtr node;
4427 if (reader == NULL)
4428 return(-1);
4429 if (reader->node == NULL)
4430 return(-1);
4431 if (reader->curnode != NULL)
4432 node = reader->curnode;
4433 else
4434 node = reader->node;
4435
4436 if (XML_NAMESPACE_DECL == node->type)
4437 return(1);
4438 else
4439 return(0);
4440}
4441
4442/**
4443 * xmlTextReaderConstXmlVersion:
4444 * @reader: the xmlTextReaderPtr used
4445 *
4446 * Determine the XML version of the document being read.
4447 *
4448 * Returns a string containing the XML version of the document or NULL
4449 * in case of error. The string is deallocated with the reader.
4450 */
4451const xmlChar *
4452xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4453 xmlDocPtr doc = NULL;
4454 if (reader == NULL)
4455 return(NULL);
4456 if (reader->doc != NULL)
4457 doc = reader->doc;
4458 else if (reader->ctxt != NULL)
4459 doc = reader->ctxt->myDoc;
4460 if (doc == NULL)
4461 return(NULL);
4462
4463 if (doc->version == NULL)
4464 return(NULL);
4465 else
4466 return(CONSTSTR(doc->version));
4467}
4468
4469/**
4470 * xmlTextReaderStandalone:
4471 * @reader: the xmlTextReaderPtr used
4472 *
4473 * Determine the standalone status of the document being read.
4474 *
4475 * Returns 1 if the document was declared to be standalone, 0 if it
4476 * was declared to be not standalone, or -1 if the document did not
4477 * specify its standalone status or in case of error.
4478 */
4479int
4480xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4481 xmlDocPtr doc = NULL;
4482 if (reader == NULL)
4483 return(-1);
4484 if (reader->doc != NULL)
4485 doc = reader->doc;
4486 else if (reader->ctxt != NULL)
4487 doc = reader->ctxt->myDoc;
4488 if (doc == NULL)
4489 return(-1);
4490
4491 return(doc->standalone);
4492}
4493
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004494/************************************************************************
4495 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004496 * Error Handling Extensions *
4497 * *
4498 ************************************************************************/
4499
4500/* helper to build a xmlMalloc'ed string from a format and va_list */
4501static char *
4502xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4503 int size;
4504 int chars;
4505 char *larger;
4506 char *str;
4507
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004508 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004509 if (str == NULL) {
4510 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4511 return NULL;
4512 }
4513
4514 size = 150;
4515
4516 while (1) {
4517 chars = vsnprintf(str, size, msg, ap);
4518 if ((chars > -1) && (chars < size))
4519 break;
4520 if (chars > -1)
4521 size += chars + 1;
4522 else
4523 size += 100;
4524 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4525 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4526 xmlFree(str);
4527 return NULL;
4528 }
4529 str = larger;
4530 }
4531
4532 return str;
4533}
4534
Daniel Veillard417be3a2003-01-20 21:26:34 +00004535/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004536 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004537 * @locator: the xmlTextReaderLocatorPtr used
4538 *
4539 * Obtain the line number for the given locator.
4540 *
4541 * Returns the line number or -1 in case of error.
4542 */
4543int
4544xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4545 /* we know that locator is a xmlParserCtxtPtr */
4546 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4547 int ret = -1;
4548
Daniel Veillardce682bc2004-11-05 17:22:25 +00004549 if (locator == NULL)
4550 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004551 if (ctx->node != NULL) {
4552 ret = xmlGetLineNo(ctx->node);
4553 }
4554 else {
4555 /* inspired from error.c */
4556 xmlParserInputPtr input;
4557 input = ctx->input;
4558 if ((input->filename == NULL) && (ctx->inputNr > 1))
4559 input = ctx->inputTab[ctx->inputNr - 2];
4560 if (input != NULL) {
4561 ret = input->line;
4562 }
4563 else {
4564 ret = -1;
4565 }
4566 }
4567
4568 return ret;
4569}
4570
4571/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004572 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004573 * @locator: the xmlTextReaderLocatorPtr used
4574 *
4575 * Obtain the base URI for the given locator.
4576 *
4577 * Returns the base URI or NULL in case of error.
4578 */
4579xmlChar *
4580xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4581 /* we know that locator is a xmlParserCtxtPtr */
4582 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4583 xmlChar *ret = NULL;
4584
Daniel Veillardce682bc2004-11-05 17:22:25 +00004585 if (locator == NULL)
4586 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004587 if (ctx->node != NULL) {
4588 ret = xmlNodeGetBase(NULL,ctx->node);
4589 }
4590 else {
4591 /* inspired from error.c */
4592 xmlParserInputPtr input;
4593 input = ctx->input;
4594 if ((input->filename == NULL) && (ctx->inputNr > 1))
4595 input = ctx->inputTab[ctx->inputNr - 2];
4596 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004597 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004598 }
4599 else {
4600 ret = NULL;
4601 }
4602 }
4603
4604 return ret;
4605}
4606
Daniel Veillard26f70262003-01-16 22:45:08 +00004607static void
William M. Brack899e64a2003-09-26 18:03:42 +00004608xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004609 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4610 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4611
William M. Bracka3215c72004-07-31 16:24:01 +00004612 if (str != NULL) {
4613 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004614 reader->errorFunc(reader->errorFuncArg,
4615 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004616 severity,
4617 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004618 xmlFree(str);
4619 }
4620}
4621
4622static void
William M. Brack93d004f2004-02-03 00:14:10 +00004623xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4624 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4625 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4626
4627 if (error && reader->sErrorFunc) {
4628 reader->sErrorFunc(reader->errorFuncArg,
4629 (xmlErrorPtr) error);
4630 }
4631}
4632
Daniel Veillardffa3c742005-07-21 13:24:09 +00004633static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004634xmlTextReaderError(void *ctxt, const char *msg, ...) {
4635 va_list ap;
4636
4637 va_start(ap,msg);
4638 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004639 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004640 xmlTextReaderBuildMessage(msg,ap));
4641 va_end(ap);
4642
4643}
4644
Daniel Veillardffa3c742005-07-21 13:24:09 +00004645static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004646xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4647 va_list ap;
4648
4649 va_start(ap,msg);
4650 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004651 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004652 xmlTextReaderBuildMessage(msg,ap));
4653 va_end(ap);
4654}
4655
Daniel Veillardffa3c742005-07-21 13:24:09 +00004656static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004657xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4658 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004659 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004660
Daniel Veillard417be3a2003-01-20 21:26:34 +00004661 if ((len > 1) && (msg[len - 2] != ':')) {
4662 /*
4663 * some callbacks only report locator information:
4664 * skip them (mimicking behaviour in error.c)
4665 */
4666 va_start(ap,msg);
4667 xmlTextReaderGenericError(ctxt,
4668 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4669 xmlTextReaderBuildMessage(msg,ap));
4670 va_end(ap);
4671 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004672}
4673
Daniel Veillardffa3c742005-07-21 13:24:09 +00004674static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004675xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4676 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004677 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004678
Daniel Veillard417be3a2003-01-20 21:26:34 +00004679 if ((len != 0) && (msg[len - 1] != ':')) {
4680 /*
4681 * some callbacks only report locator information:
4682 * skip them (mimicking behaviour in error.c)
4683 */
4684 va_start(ap,msg);
4685 xmlTextReaderGenericError(ctxt,
4686 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4687 xmlTextReaderBuildMessage(msg,ap));
4688 va_end(ap);
4689 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004690}
4691
4692/**
4693 * xmlTextReaderSetErrorHandler:
4694 * @reader: the xmlTextReaderPtr used
4695 * @f: the callback function to call on error and warnings
4696 * @arg: a user argument to pass to the callback function
4697 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004698 * Register a callback function that will be called on error and warnings.
4699 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004700 * If @f is NULL, the default error and warning handlers are restored.
4701 */
4702void
4703xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4704 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004705 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004706 if (f != NULL) {
4707 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004708 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004709 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4710 reader->ctxt->sax->warning = xmlTextReaderWarning;
4711 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4712 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004713 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004714 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004715#ifdef LIBXML_SCHEMAS_ENABLED
4716 if (reader->rngValidCtxt) {
4717 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4718 xmlTextReaderValidityErrorRelay,
4719 xmlTextReaderValidityWarningRelay,
4720 reader);
4721 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4722 }
4723 if (reader->xsdValidCtxt) {
4724 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4725 xmlTextReaderValidityErrorRelay,
4726 xmlTextReaderValidityWarningRelay,
4727 reader);
4728 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4729 }
4730#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004731 }
4732 else {
4733 /* restore defaults */
4734 reader->ctxt->sax->error = xmlParserError;
4735 reader->ctxt->vctxt.error = xmlParserValidityError;
4736 reader->ctxt->sax->warning = xmlParserWarning;
4737 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4738 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004739 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004740 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004741#ifdef LIBXML_SCHEMAS_ENABLED
4742 if (reader->rngValidCtxt) {
4743 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4744 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4745 }
4746 if (reader->xsdValidCtxt) {
4747 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4748 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4749 }
4750#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004751 }
4752}
4753
Daniel Veillard417be3a2003-01-20 21:26:34 +00004754/**
William M. Brack93d004f2004-02-03 00:14:10 +00004755* xmlTextReaderSetStructuredErrorHandler:
4756 * @reader: the xmlTextReaderPtr used
4757 * @f: the callback function to call on error and warnings
4758 * @arg: a user argument to pass to the callback function
4759 *
4760 * Register a callback function that will be called on error and warnings.
4761 *
4762 * If @f is NULL, the default error and warning handlers are restored.
4763 */
4764void
4765xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4766 xmlStructuredErrorFunc f,
4767 void *arg) {
4768 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004769 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004770 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4771 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4772 reader->ctxt->sax->warning = xmlTextReaderWarning;
4773 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4774 reader->sErrorFunc = f;
4775 reader->errorFunc = NULL;
4776 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004777#ifdef LIBXML_SCHEMAS_ENABLED
4778 if (reader->rngValidCtxt) {
4779 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4780 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4781 xmlTextReaderValidityStructuredRelay,
4782 reader);
4783 }
4784 if (reader->xsdValidCtxt) {
4785 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4786 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4787 xmlTextReaderValidityStructuredRelay,
4788 reader);
4789 }
4790#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004791 }
4792 else {
4793 /* restore defaults */
4794 reader->ctxt->sax->error = xmlParserError;
4795 reader->ctxt->sax->serror = NULL;
4796 reader->ctxt->vctxt.error = xmlParserValidityError;
4797 reader->ctxt->sax->warning = xmlParserWarning;
4798 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4799 reader->errorFunc = NULL;
4800 reader->sErrorFunc = NULL;
4801 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004802#ifdef LIBXML_SCHEMAS_ENABLED
4803 if (reader->rngValidCtxt) {
4804 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4805 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4806 }
4807 if (reader->xsdValidCtxt) {
4808 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4809 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4810 }
4811#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004812 }
4813}
4814
4815/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004816 * xmlTextReaderIsValid:
4817 * @reader: the xmlTextReaderPtr used
4818 *
4819 * Retrieve the validity status from the parser context
4820 *
4821 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4822 */
4823int
4824xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004825 if (reader == NULL) return(-1);
4826#ifdef LIBXML_SCHEMAS_ENABLED
4827 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4828 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004829 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4830 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004831#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004832 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004833 return(reader->ctxt->valid);
4834 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004835}
4836
4837/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004838 * xmlTextReaderGetErrorHandler:
4839 * @reader: the xmlTextReaderPtr used
4840 * @f: the callback function or NULL is no callback has been registered
4841 * @arg: a user argument
4842 *
4843 * Retrieve the error callback function and user argument.
4844 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004845void
4846xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4847 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004848 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004849 if (f != NULL) *f = reader->errorFunc;
4850 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004851}
4852
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004853
4854/************************************************************************
4855 * *
4856 * New set (2.6.0) of simpler and more flexible APIs *
4857 * *
4858 ************************************************************************/
4859
4860/**
4861 * xmlTextReaderSetup:
4862 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00004863 * @input: xmlParserInputBufferPtr used to feed the reader, will
4864 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004865 * @URL: the base URL to use for the document
4866 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004867 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004868 *
4869 * Setup an XML reader with new options
4870 *
4871 * Returns 0 in case of success and -1 in case of error.
4872 */
Aleksey Sanind8377642007-01-03 23:13:12 +00004873int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004874xmlTextReaderSetup(xmlTextReaderPtr reader,
4875 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004876 const char *encoding, int options)
4877{
William M. Brackd46c1ca2007-02-08 23:34:34 +00004878 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00004879 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00004880 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00004881 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00004882 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004883
Daniel Veillard8874b942005-08-25 13:19:21 +00004884 /*
4885 * we force the generation of compact text nodes on the reader
4886 * since usr applications should never modify the tree
4887 */
4888 options |= XML_PARSE_COMPACT;
4889
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004890 reader->doc = NULL;
4891 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004892 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004893 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004894 if ((input != NULL) && (reader->input != NULL) &&
4895 (reader->allocs & XML_TEXTREADER_INPUT)) {
4896 xmlFreeParserInputBuffer(reader->input);
4897 reader->input = NULL;
4898 reader->allocs -= XML_TEXTREADER_INPUT;
4899 }
4900 if (input != NULL) {
4901 reader->input = input;
4902 reader->allocs |= XML_TEXTREADER_INPUT;
4903 }
4904 if (reader->buffer == NULL)
4905 reader->buffer = xmlBufferCreateSize(100);
4906 if (reader->buffer == NULL) {
4907 xmlGenericError(xmlGenericErrorContext,
4908 "xmlTextReaderSetup : malloc failed\n");
4909 return (-1);
4910 }
4911 if (reader->sax == NULL)
4912 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4913 if (reader->sax == NULL) {
4914 xmlGenericError(xmlGenericErrorContext,
4915 "xmlTextReaderSetup : malloc failed\n");
4916 return (-1);
4917 }
4918 xmlSAXVersion(reader->sax, 2);
4919 reader->startElement = reader->sax->startElement;
4920 reader->sax->startElement = xmlTextReaderStartElement;
4921 reader->endElement = reader->sax->endElement;
4922 reader->sax->endElement = xmlTextReaderEndElement;
4923#ifdef LIBXML_SAX1_ENABLED
4924 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4925#endif /* LIBXML_SAX1_ENABLED */
4926 reader->startElementNs = reader->sax->startElementNs;
4927 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4928 reader->endElementNs = reader->sax->endElementNs;
4929 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4930#ifdef LIBXML_SAX1_ENABLED
4931 } else {
4932 reader->startElementNs = NULL;
4933 reader->endElementNs = NULL;
4934 }
4935#endif /* LIBXML_SAX1_ENABLED */
4936 reader->characters = reader->sax->characters;
4937 reader->sax->characters = xmlTextReaderCharacters;
4938 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4939 reader->cdataBlock = reader->sax->cdataBlock;
4940 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4941
4942 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4943 reader->node = NULL;
4944 reader->curnode = NULL;
4945 if (input != NULL) {
4946 if (reader->input->buffer->use < 4) {
4947 xmlParserInputBufferRead(input, 4);
4948 }
4949 if (reader->ctxt == NULL) {
4950 if (reader->input->buffer->use >= 4) {
4951 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4952 (const char *) reader->input->buffer->content, 4, URL);
4953 reader->base = 0;
4954 reader->cur = 4;
4955 } else {
4956 reader->ctxt =
4957 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4958 reader->base = 0;
4959 reader->cur = 0;
4960 }
4961 } else {
4962 xmlParserInputPtr inputStream;
4963 xmlParserInputBufferPtr buf;
4964 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4965
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004966 xmlCtxtReset(reader->ctxt);
4967 buf = xmlAllocParserInputBuffer(enc);
4968 if (buf == NULL) return(-1);
4969 inputStream = xmlNewInputStream(reader->ctxt);
4970 if (inputStream == NULL) {
4971 xmlFreeParserInputBuffer(buf);
4972 return(-1);
4973 }
4974
4975 if (URL == NULL)
4976 inputStream->filename = NULL;
4977 else
4978 inputStream->filename = (char *)
4979 xmlCanonicPath((const xmlChar *) URL);
4980 inputStream->buf = buf;
4981 inputStream->base = inputStream->buf->buffer->content;
4982 inputStream->cur = inputStream->buf->buffer->content;
4983 inputStream->end =
4984 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4985
4986 inputPush(reader->ctxt, inputStream);
4987 reader->cur = 0;
4988 }
4989 if (reader->ctxt == NULL) {
4990 xmlGenericError(xmlGenericErrorContext,
4991 "xmlTextReaderSetup : malloc failed\n");
4992 return (-1);
4993 }
4994 }
4995 if (reader->dict != NULL) {
4996 if (reader->ctxt->dict != NULL) {
4997 if (reader->dict != reader->ctxt->dict) {
4998 xmlDictFree(reader->dict);
4999 reader->dict = reader->ctxt->dict;
5000 }
5001 } else {
5002 reader->ctxt->dict = reader->dict;
5003 }
5004 } else {
5005 if (reader->ctxt->dict == NULL)
5006 reader->ctxt->dict = xmlDictCreate();
5007 reader->dict = reader->ctxt->dict;
5008 }
5009 reader->ctxt->_private = reader;
5010 reader->ctxt->linenumbers = 1;
5011 reader->ctxt->dictNames = 1;
5012 /*
5013 * use the parser dictionnary to allocate all elements and attributes names
5014 */
5015 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005016 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005017
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005018#ifdef LIBXML_XINCLUDE_ENABLED
5019 if (reader->xincctxt != NULL) {
5020 xmlXIncludeFreeContext(reader->xincctxt);
5021 reader->xincctxt = NULL;
5022 }
5023 if (options & XML_PARSE_XINCLUDE) {
5024 reader->xinclude = 1;
5025 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5026 options -= XML_PARSE_XINCLUDE;
5027 } else
5028 reader->xinclude = 0;
5029 reader->in_xinclude = 0;
5030#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005031#ifdef LIBXML_PATTERN_ENABLED
5032 if (reader->patternTab == NULL) {
5033 reader->patternNr = 0;
5034 reader->patternMax = 0;
5035 }
5036 while (reader->patternNr > 0) {
5037 reader->patternNr--;
5038 if (reader->patternTab[reader->patternNr] != NULL) {
5039 xmlFreePattern(reader->patternTab[reader->patternNr]);
5040 reader->patternTab[reader->patternNr] = NULL;
5041 }
5042 }
5043#endif
5044
Daniel Veillardc36965d2003-12-02 10:28:48 +00005045 if (options & XML_PARSE_DTDVALID)
5046 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5047
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005048 xmlCtxtUseOptions(reader->ctxt, options);
5049 if (encoding != NULL) {
5050 xmlCharEncodingHandlerPtr hdlr;
5051
5052 hdlr = xmlFindCharEncodingHandler(encoding);
5053 if (hdlr != NULL)
5054 xmlSwitchToEncoding(reader->ctxt, hdlr);
5055 }
5056 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5057 (reader->ctxt->input->filename == NULL))
5058 reader->ctxt->input->filename = (char *)
5059 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005060
5061 reader->doc = NULL;
5062
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005063 return (0);
5064}
5065
5066/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005067 * xmlTextReaderByteConsumed:
5068 * @reader: an XML reader
5069 *
5070 * This function provides the current index of the parser used
5071 * by the reader, relative to the start of the current entity.
5072 * This function actually just wraps a call to xmlBytesConsumed()
5073 * for the parser context associated with the reader.
5074 * See xmlBytesConsumed() for more information.
5075 *
5076 * Returns the index in bytes from the beginning of the entity or -1
5077 * in case the index could not be computed.
5078 */
5079long
5080xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5081 if ((reader == NULL) || (reader->ctxt == NULL))
5082 return(-1);
5083 return(xmlByteConsumed(reader->ctxt));
5084}
5085
5086
5087/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005088 * xmlReaderWalker:
5089 * @doc: a preparsed document
5090 *
5091 * Create an xmltextReader for a preparsed document.
5092 *
5093 * Returns the new reader or NULL in case of error.
5094 */
5095xmlTextReaderPtr
5096xmlReaderWalker(xmlDocPtr doc)
5097{
5098 xmlTextReaderPtr ret;
5099
5100 if (doc == NULL)
5101 return(NULL);
5102
5103 ret = xmlMalloc(sizeof(xmlTextReader));
5104 if (ret == NULL) {
5105 xmlGenericError(xmlGenericErrorContext,
5106 "xmlNewTextReader : malloc failed\n");
5107 return(NULL);
5108 }
5109 memset(ret, 0, sizeof(xmlTextReader));
5110 ret->entNr = 0;
5111 ret->input = NULL;
5112 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5113 ret->node = NULL;
5114 ret->curnode = NULL;
5115 ret->base = 0;
5116 ret->cur = 0;
5117 ret->allocs = XML_TEXTREADER_CTXT;
5118 ret->doc = doc;
5119 ret->state = XML_TEXTREADER_START;
5120 ret->dict = xmlDictCreate();
5121 return(ret);
5122}
5123
5124/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005125 * xmlReaderForDoc:
5126 * @cur: a pointer to a zero terminated string
5127 * @URL: the base URL to use for the document
5128 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005129 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005130 *
5131 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005132 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005133 *
5134 * Returns the new reader or NULL in case of error.
5135 */
5136xmlTextReaderPtr
5137xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5138 int options)
5139{
5140 int len;
5141
5142 if (cur == NULL)
5143 return (NULL);
5144 len = xmlStrlen(cur);
5145
5146 return (xmlReaderForMemory
5147 ((const char *) cur, len, URL, encoding, options));
5148}
5149
5150/**
5151 * xmlReaderForFile:
5152 * @filename: a file or URL
5153 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005154 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005155 *
5156 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005157 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005158 *
5159 * Returns the new reader or NULL in case of error.
5160 */
5161xmlTextReaderPtr
5162xmlReaderForFile(const char *filename, const char *encoding, int options)
5163{
5164 xmlTextReaderPtr reader;
5165
5166 reader = xmlNewTextReaderFilename(filename);
5167 if (reader == NULL)
5168 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005169 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005170 return (reader);
5171}
5172
5173/**
5174 * xmlReaderForMemory:
5175 * @buffer: a pointer to a char array
5176 * @size: the size of the array
5177 * @URL: the base URL to use for the document
5178 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005179 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005180 *
5181 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005182 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005183 *
5184 * Returns the new reader or NULL in case of error.
5185 */
5186xmlTextReaderPtr
5187xmlReaderForMemory(const char *buffer, int size, const char *URL,
5188 const char *encoding, int options)
5189{
5190 xmlTextReaderPtr reader;
5191 xmlParserInputBufferPtr buf;
5192
Daniel Veillard21924522004-02-19 16:37:07 +00005193 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005194 XML_CHAR_ENCODING_NONE);
5195 if (buf == NULL) {
5196 return (NULL);
5197 }
5198 reader = xmlNewTextReader(buf, URL);
5199 if (reader == NULL) {
5200 xmlFreeParserInputBuffer(buf);
5201 return (NULL);
5202 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005203 reader->allocs |= XML_TEXTREADER_INPUT;
5204 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005205 return (reader);
5206}
5207
5208/**
5209 * xmlReaderForFd:
5210 * @fd: an open file descriptor
5211 * @URL: the base URL to use for the document
5212 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005213 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005214 *
5215 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005216 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005217 * NOTE that the file descriptor will not be closed when the
5218 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005219 *
5220 * Returns the new reader or NULL in case of error.
5221 */
5222xmlTextReaderPtr
5223xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5224{
5225 xmlTextReaderPtr reader;
5226 xmlParserInputBufferPtr input;
5227
5228 if (fd < 0)
5229 return (NULL);
5230
5231 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5232 if (input == NULL)
5233 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005234 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005235 reader = xmlNewTextReader(input, URL);
5236 if (reader == NULL) {
5237 xmlFreeParserInputBuffer(input);
5238 return (NULL);
5239 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005240 reader->allocs |= XML_TEXTREADER_INPUT;
5241 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005242 return (reader);
5243}
5244
5245/**
5246 * xmlReaderForIO:
5247 * @ioread: an I/O read function
5248 * @ioclose: an I/O close function
5249 * @ioctx: an I/O handler
5250 * @URL: the base URL to use for the document
5251 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005252 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005253 *
5254 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005255 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005256 *
5257 * Returns the new reader or NULL in case of error.
5258 */
5259xmlTextReaderPtr
5260xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5261 void *ioctx, const char *URL, const char *encoding,
5262 int options)
5263{
5264 xmlTextReaderPtr reader;
5265 xmlParserInputBufferPtr input;
5266
5267 if (ioread == NULL)
5268 return (NULL);
5269
5270 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5271 XML_CHAR_ENCODING_NONE);
5272 if (input == NULL)
5273 return (NULL);
5274 reader = xmlNewTextReader(input, URL);
5275 if (reader == NULL) {
5276 xmlFreeParserInputBuffer(input);
5277 return (NULL);
5278 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005279 reader->allocs |= XML_TEXTREADER_INPUT;
5280 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005281 return (reader);
5282}
5283
5284/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005285 * xmlReaderNewWalker:
5286 * @reader: an XML reader
5287 * @doc: a preparsed document
5288 *
5289 * Setup an xmltextReader to parse a preparsed XML document.
5290 * This reuses the existing @reader xmlTextReader.
5291 *
5292 * Returns 0 in case of success and -1 in case of error
5293 */
5294int
5295xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5296{
5297 if (doc == NULL)
5298 return (-1);
5299 if (reader == NULL)
5300 return (-1);
5301
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005302 if (reader->input != NULL) {
5303 xmlFreeParserInputBuffer(reader->input);
5304 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005305 if (reader->ctxt != NULL) {
5306 xmlCtxtReset(reader->ctxt);
5307 }
5308
5309 reader->entNr = 0;
5310 reader->input = NULL;
5311 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5312 reader->node = NULL;
5313 reader->curnode = NULL;
5314 reader->base = 0;
5315 reader->cur = 0;
5316 reader->allocs = XML_TEXTREADER_CTXT;
5317 reader->doc = doc;
5318 reader->state = XML_TEXTREADER_START;
5319 if (reader->dict == NULL) {
5320 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5321 reader->dict = reader->ctxt->dict;
5322 else
5323 reader->dict = xmlDictCreate();
5324 }
5325 return(0);
5326}
5327
5328/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005329 * xmlReaderNewDoc:
5330 * @reader: an XML reader
5331 * @cur: a pointer to a zero terminated string
5332 * @URL: the base URL to use for the document
5333 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005334 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005335 *
5336 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005337 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005338 * This reuses the existing @reader xmlTextReader.
5339 *
5340 * Returns 0 in case of success and -1 in case of error
5341 */
5342int
5343xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5344 const char *URL, const char *encoding, int options)
5345{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005346
5347 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005348
5349 if (cur == NULL)
5350 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005351 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005352 return (-1);
5353
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005354 len = xmlStrlen(cur);
5355 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5356 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005357}
5358
5359/**
5360 * xmlReaderNewFile:
5361 * @reader: an XML reader
5362 * @filename: a file or URL
5363 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005364 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005365 *
5366 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005367 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005368 * This reuses the existing @reader xmlTextReader.
5369 *
5370 * Returns 0 in case of success and -1 in case of error
5371 */
5372int
5373xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5374 const char *encoding, int options)
5375{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005376 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377
5378 if (filename == NULL)
5379 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005380 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005381 return (-1);
5382
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005383 input =
5384 xmlParserInputBufferCreateFilename(filename,
5385 XML_CHAR_ENCODING_NONE);
5386 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005387 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005388 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005389}
5390
5391/**
5392 * xmlReaderNewMemory:
5393 * @reader: an XML reader
5394 * @buffer: a pointer to a char array
5395 * @size: the size of the array
5396 * @URL: the base URL to use for the document
5397 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005398 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005399 *
5400 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005401 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005402 * This reuses the existing @reader xmlTextReader.
5403 *
5404 * Returns 0 in case of success and -1 in case of error
5405 */
5406int
5407xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5408 const char *URL, const char *encoding, int options)
5409{
5410 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005411
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005412 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005413 return (-1);
5414 if (buffer == NULL)
5415 return (-1);
5416
Daniel Veillard21924522004-02-19 16:37:07 +00005417 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005418 XML_CHAR_ENCODING_NONE);
5419 if (input == NULL) {
5420 return (-1);
5421 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005422 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005423}
5424
5425/**
5426 * xmlReaderNewFd:
5427 * @reader: an XML reader
5428 * @fd: an open file descriptor
5429 * @URL: the base URL to use for the document
5430 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005431 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005432 *
5433 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005434 * NOTE that the file descriptor will not be closed when the
5435 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005436 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005437 * This reuses the existing @reader xmlTextReader.
5438 *
5439 * Returns 0 in case of success and -1 in case of error
5440 */
5441int
5442xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5443 const char *URL, const char *encoding, int options)
5444{
5445 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005446
5447 if (fd < 0)
5448 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005449 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005450 return (-1);
5451
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005452 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5453 if (input == NULL)
5454 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005455 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005456 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005457}
5458
5459/**
5460 * xmlReaderNewIO:
5461 * @reader: an XML reader
5462 * @ioread: an I/O read function
5463 * @ioclose: an I/O close function
5464 * @ioctx: an I/O handler
5465 * @URL: the base URL to use for the document
5466 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005467 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005468 *
5469 * Setup an xmltextReader to parse an XML document from I/O functions
5470 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005471 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005472 * This reuses the existing @reader xmlTextReader.
5473 *
5474 * Returns 0 in case of success and -1 in case of error
5475 */
5476int
5477xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5478 xmlInputCloseCallback ioclose, void *ioctx,
5479 const char *URL, const char *encoding, int options)
5480{
5481 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005482
5483 if (ioread == NULL)
5484 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005485 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005486 return (-1);
5487
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005488 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5489 XML_CHAR_ENCODING_NONE);
5490 if (input == NULL)
5491 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005492 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005493}
Daniel Veillard26f70262003-01-16 22:45:08 +00005494/************************************************************************
5495 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005496 * Utilities *
5497 * *
5498 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005499#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005500/**
5501 * xmlBase64Decode:
5502 * @in: the input buffer
5503 * @inlen: the size of the input (in), the size read from it (out)
5504 * @to: the output buffer
5505 * @tolen: the size of the output (in), the size written to (out)
5506 *
5507 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005508 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005509 *
5510 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5511 * 2 if there wasn't enough space on the output or -1 in case of error.
5512 */
5513static int
5514xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5515 unsigned char *to, unsigned long *tolen) {
5516 unsigned long incur; /* current index in in[] */
5517 unsigned long inblk; /* last block index in in[] */
5518 unsigned long outcur; /* current index in out[] */
5519 unsigned long inmax; /* size of in[] */
5520 unsigned long outmax; /* size of out[] */
5521 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005522 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005523 int nbintmp; /* number of byte in intmp[] */
5524 int is_ignore; /* cur should be ignored */
5525 int is_end = 0; /* the end of the base64 was found */
5526 int retval = 1;
5527 int i;
5528
5529 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5530 return(-1);
5531
5532 incur = 0;
5533 inblk = 0;
5534 outcur = 0;
5535 inmax = *inlen;
5536 outmax = *tolen;
5537 nbintmp = 0;
5538
5539 while (1) {
5540 if (incur >= inmax)
5541 break;
5542 cur = in[incur++];
5543 is_ignore = 0;
5544 if ((cur >= 'A') && (cur <= 'Z'))
5545 cur = cur - 'A';
5546 else if ((cur >= 'a') && (cur <= 'z'))
5547 cur = cur - 'a' + 26;
5548 else if ((cur >= '0') && (cur <= '9'))
5549 cur = cur - '0' + 52;
5550 else if (cur == '+')
5551 cur = 62;
5552 else if (cur == '/')
5553 cur = 63;
5554 else if (cur == '.')
5555 cur = 0;
5556 else if (cur == '=') /*no op , end of the base64 stream */
5557 is_end = 1;
5558 else {
5559 is_ignore = 1;
5560 if (nbintmp == 0)
5561 inblk = incur;
5562 }
5563
5564 if (!is_ignore) {
5565 int nbouttmp = 3;
5566 int is_break = 0;
5567
5568 if (is_end) {
5569 if (nbintmp == 0)
5570 break;
5571 if ((nbintmp == 1) || (nbintmp == 2))
5572 nbouttmp = 1;
5573 else
5574 nbouttmp = 2;
5575 nbintmp = 3;
5576 is_break = 1;
5577 }
5578 intmp[nbintmp++] = cur;
5579 /*
5580 * if intmp is full, push the 4byte sequence as a 3 byte
5581 * sequence out
5582 */
5583 if (nbintmp == 4) {
5584 nbintmp = 0;
5585 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5586 outtmp[1] =
5587 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5588 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5589 if (outcur + 3 >= outmax) {
5590 retval = 2;
5591 break;
5592 }
5593
5594 for (i = 0; i < nbouttmp; i++)
5595 to[outcur++] = outtmp[i];
5596 inblk = incur;
5597 }
5598
5599 if (is_break) {
5600 retval = 0;
5601 break;
5602 }
5603 }
5604 }
5605
5606 *tolen = outcur;
5607 *inlen = inblk;
5608 return (retval);
5609}
5610
5611/*
5612 * Test routine for the xmlBase64Decode function
5613 */
5614#if 0
5615int main(int argc, char **argv) {
5616 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5617 char output[100];
5618 char output2[100];
5619 char output3[100];
5620 unsigned long inlen = strlen(input);
5621 unsigned long outlen = 100;
5622 int ret;
5623 unsigned long cons, tmp, tmp2, prod;
5624
5625 /*
5626 * Direct
5627 */
5628 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5629
5630 output[outlen] = 0;
5631 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5632
5633 /*
5634 * output chunking
5635 */
5636 cons = 0;
5637 prod = 0;
5638 while (cons < inlen) {
5639 tmp = 5;
5640 tmp2 = inlen - cons;
5641
5642 printf("%ld %ld\n", cons, prod);
5643 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5644 cons += tmp2;
5645 prod += tmp;
5646 printf("%ld %ld\n", cons, prod);
5647 }
5648 output2[outlen] = 0;
5649 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5650
5651 /*
5652 * input chunking
5653 */
5654 cons = 0;
5655 prod = 0;
5656 while (cons < inlen) {
5657 tmp = 100 - prod;
5658 tmp2 = inlen - cons;
5659 if (tmp2 > 5)
5660 tmp2 = 5;
5661
5662 printf("%ld %ld\n", cons, prod);
5663 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5664 cons += tmp2;
5665 prod += tmp;
5666 printf("%ld %ld\n", cons, prod);
5667 }
5668 output3[outlen] = 0;
5669 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5670 return(0);
5671
5672}
5673#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005674#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005675#define bottom_xmlreader
5676#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005677#endif /* LIBXML_READER_ENABLED */