blob: 92b053ed48a42b17334fdcdf25bfd4bbb8f87182 [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) {
1850 if (reader->node->children != 0) {
1851 reader->node = reader->node->children;
1852 reader->depth++;
1853 reader->state = XML_TEXTREADER_START;
1854 return(1);
1855 }
1856
1857 if ((reader->node->type == XML_ELEMENT_NODE) ||
1858 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1859 reader->state = XML_TEXTREADER_BACKTRACK;
1860 return(1);
1861 }
1862 }
1863
1864 if (reader->node->next != 0) {
1865 reader->node = reader->node->next;
1866 reader->state = XML_TEXTREADER_START;
1867 return(1);
1868 }
1869
1870 if (reader->node->parent != 0) {
1871 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1872 reader->state = XML_TEXTREADER_END;
1873 return(0);
1874 }
1875
1876 reader->node = reader->node->parent;
1877 reader->depth--;
1878 reader->state = XML_TEXTREADER_BACKTRACK;
1879 return(1);
1880 }
1881
1882 reader->state = XML_TEXTREADER_END;
1883
1884 return(1);
1885}
1886
1887/**
1888 * xmlTextReaderReadTree:
1889 * @reader: the xmlTextReaderPtr used
1890 *
1891 * Moves the position of the current instance to the next node in
1892 * the stream, exposing its properties.
1893 *
1894 * Returns 1 if the node was read successfully, 0 if there is no more
1895 * nodes to read, or -1 in case of error
1896 */
1897static int
1898xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1899 if (reader->state == XML_TEXTREADER_END)
1900 return(0);
1901
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001902next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 if (reader->node == NULL) {
1904 if (reader->doc->children == NULL) {
1905 reader->state = XML_TEXTREADER_END;
1906 return(0);
1907 }
1908
1909 reader->node = reader->doc->children;
1910 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001911 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001912 }
1913
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001914 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1915 (reader->node->type != XML_DTD_NODE) &&
1916 (reader->node->type != XML_XINCLUDE_START) &&
1917 (reader->node->type != XML_ENTITY_REF_NODE)) {
1918 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001919 reader->node = reader->node->children;
1920 reader->depth++;
1921 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001922 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 }
1924
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001925 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001926 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001927 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001928 }
1929 }
1930
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001931 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 reader->node = reader->node->next;
1933 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001934 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001935 }
1936
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001937 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001938 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1939 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1940 reader->state = XML_TEXTREADER_END;
1941 return(0);
1942 }
1943
1944 reader->node = reader->node->parent;
1945 reader->depth--;
1946 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001947 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001948 }
1949
1950 reader->state = XML_TEXTREADER_END;
1951
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001952found_node:
1953 if ((reader->node->type == XML_XINCLUDE_START) ||
1954 (reader->node->type == XML_XINCLUDE_END))
1955 goto next_node;
1956
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001957 return(1);
1958}
1959
1960/**
William M. Brackb1d53162003-11-18 06:54:40 +00001961 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001962 * @reader: the xmlTextReaderPtr used
1963 *
1964 * Skip to the node following the current one in document order while
1965 * avoiding the subtree if any.
1966 * Currently implemented only for Readers built on a document
1967 *
1968 * Returns 1 if the node was read successfully, 0 if there is no more
1969 * nodes to read, or -1 in case of error
1970 */
1971int
1972xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1973 if (reader == NULL)
1974 return(-1);
1975 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001976 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001977 return(-1);
1978 }
1979
1980 if (reader->state == XML_TEXTREADER_END)
1981 return(0);
1982
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001983 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001984 return(xmlTextReaderNextTree(reader));
1985
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001986 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001987 reader->node = reader->node->next;
1988 reader->state = XML_TEXTREADER_START;
1989 return(1);
1990 }
1991
1992 return(0);
1993}
1994
1995/************************************************************************
1996 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001997 * Constructor and destructors *
1998 * *
1999 ************************************************************************/
2000/**
2001 * xmlNewTextReader:
2002 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002003 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002004 *
2005 * Create an xmlTextReader structure fed with @input
2006 *
2007 * Returns the new xmlTextReaderPtr or NULL in case of error
2008 */
2009xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002010xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002011 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002012
2013 if (input == NULL)
2014 return(NULL);
2015 ret = xmlMalloc(sizeof(xmlTextReader));
2016 if (ret == NULL) {
2017 xmlGenericError(xmlGenericErrorContext,
2018 "xmlNewTextReader : malloc failed\n");
2019 return(NULL);
2020 }
2021 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002022 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002023 ret->entTab = NULL;
2024 ret->entMax = 0;
2025 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002026 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002027 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002028 if (ret->buffer == NULL) {
2029 xmlFree(ret);
2030 xmlGenericError(xmlGenericErrorContext,
2031 "xmlNewTextReader : malloc failed\n");
2032 return(NULL);
2033 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002034 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2035 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002036 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002037 xmlFree(ret);
2038 xmlGenericError(xmlGenericErrorContext,
2039 "xmlNewTextReader : malloc failed\n");
2040 return(NULL);
2041 }
Daniel Veillard81273902003-09-30 00:43:48 +00002042 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002043 ret->startElement = ret->sax->startElement;
2044 ret->sax->startElement = xmlTextReaderStartElement;
2045 ret->endElement = ret->sax->endElement;
2046 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002047#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002048 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002049#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002050 ret->startElementNs = ret->sax->startElementNs;
2051 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2052 ret->endElementNs = ret->sax->endElementNs;
2053 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002054#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002055 } else {
2056 ret->startElementNs = NULL;
2057 ret->endElementNs = NULL;
2058 }
Daniel Veillard81273902003-09-30 00:43:48 +00002059#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002060 ret->characters = ret->sax->characters;
2061 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002062 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002063 ret->cdataBlock = ret->sax->cdataBlock;
2064 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002065
Daniel Veillard67df8092002-12-16 22:04:11 +00002066 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002067 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002068 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002069 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002070 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002071 }
2072 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002073 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002074 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002075 ret->base = 0;
2076 ret->cur = 4;
2077 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002078 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002079 ret->base = 0;
2080 ret->cur = 0;
2081 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002082
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002083 if (ret->ctxt == NULL) {
2084 xmlGenericError(xmlGenericErrorContext,
2085 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002086 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002087 xmlFree(ret->sax);
2088 xmlFree(ret);
2089 return(NULL);
2090 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002091 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002092 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002093 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002094 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002095 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002096 /*
2097 * use the parser dictionnary to allocate all elements and attributes names
2098 */
2099 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002100 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002101#ifdef LIBXML_XINCLUDE_ENABLED
2102 ret->xinclude = 0;
2103#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002104#ifdef LIBXML_PATTERN_ENABLED
2105 ret->patternMax = 0;
2106 ret->patternTab = NULL;
2107#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002108 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002109}
2110
2111/**
2112 * xmlNewTextReaderFilename:
2113 * @URI: the URI of the resource to process
2114 *
2115 * Create an xmlTextReader structure fed with the resource at @URI
2116 *
2117 * Returns the new xmlTextReaderPtr or NULL in case of error
2118 */
2119xmlTextReaderPtr
2120xmlNewTextReaderFilename(const char *URI) {
2121 xmlParserInputBufferPtr input;
2122 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002123 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002124
2125 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2126 if (input == NULL)
2127 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002128 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002129 if (ret == NULL) {
2130 xmlFreeParserInputBuffer(input);
2131 return(NULL);
2132 }
2133 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002134 if (ret->ctxt->directory == NULL)
2135 directory = xmlParserGetDirectory(URI);
2136 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2137 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2138 if (directory != NULL)
2139 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002140 return(ret);
2141}
2142
2143/**
2144 * xmlFreeTextReader:
2145 * @reader: the xmlTextReaderPtr
2146 *
2147 * Deallocate all the resources associated to the reader
2148 */
2149void
2150xmlFreeTextReader(xmlTextReaderPtr reader) {
2151 if (reader == NULL)
2152 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002153#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002154 if (reader->rngSchemas != NULL) {
2155 xmlRelaxNGFree(reader->rngSchemas);
2156 reader->rngSchemas = NULL;
2157 }
2158 if (reader->rngValidCtxt != NULL) {
2159 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2160 reader->rngValidCtxt = NULL;
2161 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002162 if (reader->xsdPlug != NULL) {
2163 xmlSchemaSAXUnplug(reader->xsdPlug);
2164 reader->xsdPlug = NULL;
2165 }
2166 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002167 if (! reader->xsdPreserveCtxt)
2168 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002169 reader->xsdValidCtxt = NULL;
2170 }
2171 if (reader->xsdSchemas != NULL) {
2172 xmlSchemaFree(reader->xsdSchemas);
2173 reader->xsdSchemas = NULL;
2174 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002175#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002176#ifdef LIBXML_XINCLUDE_ENABLED
2177 if (reader->xincctxt != NULL)
2178 xmlXIncludeFreeContext(reader->xincctxt);
2179#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002180#ifdef LIBXML_PATTERN_ENABLED
2181 if (reader->patternTab != NULL) {
2182 int i;
2183 for (i = 0;i < reader->patternNr;i++) {
2184 if (reader->patternTab[i] != NULL)
2185 xmlFreePattern(reader->patternTab[i]);
2186 }
2187 xmlFree(reader->patternTab);
2188 }
2189#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002190 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002191 if (reader->dict == reader->ctxt->dict)
2192 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002193 if (reader->ctxt->myDoc != NULL) {
2194 if (reader->preserve == 0)
2195 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2196 reader->ctxt->myDoc = NULL;
2197 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002198 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2199 (reader->ctxt->vctxt.vstateMax > 0)){
2200 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002201 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002202 reader->ctxt->vctxt.vstateMax = 0;
2203 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002204 if (reader->allocs & XML_TEXTREADER_CTXT)
2205 xmlFreeParserCtxt(reader->ctxt);
2206 }
2207 if (reader->sax != NULL)
2208 xmlFree(reader->sax);
2209 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2210 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002211 if (reader->faketext != NULL) {
2212 xmlFreeNode(reader->faketext);
2213 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002214 if (reader->buffer != NULL)
2215 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002216 if (reader->entTab != NULL)
2217 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002218 if (reader->dict != NULL)
2219 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002220 xmlFree(reader);
2221}
2222
2223/************************************************************************
2224 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002225 * Methods for XmlTextReader *
2226 * *
2227 ************************************************************************/
2228/**
2229 * xmlTextReaderClose:
2230 * @reader: the xmlTextReaderPtr used
2231 *
2232 * This method releases any resources allocated by the current instance
2233 * changes the state to Closed and close any underlying input.
2234 *
2235 * Returns 0 or -1 in case of error
2236 */
2237int
2238xmlTextReaderClose(xmlTextReaderPtr reader) {
2239 if (reader == NULL)
2240 return(-1);
2241 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002242 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002243 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2244 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002245 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002246 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002247 if (reader->preserve == 0)
2248 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002249 reader->ctxt->myDoc = NULL;
2250 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002251 }
2252 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2253 xmlFreeParserInputBuffer(reader->input);
2254 reader->allocs -= XML_TEXTREADER_INPUT;
2255 }
2256 return(0);
2257}
2258
2259/**
2260 * xmlTextReaderGetAttributeNo:
2261 * @reader: the xmlTextReaderPtr used
2262 * @no: the zero-based index of the attribute relative to the containing element
2263 *
2264 * Provides the value of the attribute with the specified index relative
2265 * to the containing element.
2266 *
2267 * Returns a string containing the value of the specified attribute, or NULL
2268 * in case of error. The string must be deallocated by the caller.
2269 */
2270xmlChar *
2271xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2272 xmlChar *ret;
2273 int i;
2274 xmlAttrPtr cur;
2275 xmlNsPtr ns;
2276
2277 if (reader == NULL)
2278 return(NULL);
2279 if (reader->node == NULL)
2280 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002281 if (reader->curnode != NULL)
2282 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002283 /* TODO: handle the xmlDecl */
2284 if (reader->node->type != XML_ELEMENT_NODE)
2285 return(NULL);
2286
2287 ns = reader->node->nsDef;
2288 for (i = 0;(i < no) && (ns != NULL);i++) {
2289 ns = ns->next;
2290 }
2291 if (ns != NULL)
2292 return(xmlStrdup(ns->href));
2293
2294 cur = reader->node->properties;
2295 if (cur == NULL)
2296 return(NULL);
2297 for (;i < no;i++) {
2298 cur = cur->next;
2299 if (cur == NULL)
2300 return(NULL);
2301 }
2302 /* TODO walk the DTD if present */
2303
2304 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2305 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2306 return(ret);
2307}
2308
2309/**
2310 * xmlTextReaderGetAttribute:
2311 * @reader: the xmlTextReaderPtr used
2312 * @name: the qualified name of the attribute.
2313 *
2314 * Provides the value of the attribute with the specified qualified name.
2315 *
2316 * Returns a string containing the value of the specified attribute, or NULL
2317 * in case of error. The string must be deallocated by the caller.
2318 */
2319xmlChar *
2320xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2321 xmlChar *prefix = NULL;
2322 xmlChar *localname;
2323 xmlNsPtr ns;
2324 xmlChar *ret = NULL;
2325
2326 if ((reader == NULL) || (name == NULL))
2327 return(NULL);
2328 if (reader->node == NULL)
2329 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002330 if (reader->curnode != NULL)
2331 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002332
2333 /* TODO: handle the xmlDecl */
2334 if (reader->node->type != XML_ELEMENT_NODE)
2335 return(NULL);
2336
2337 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002338 if (localname == NULL) {
2339 /*
2340 * Namespace default decl
2341 */
2342 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2343 ns = reader->node->nsDef;
2344 while (ns != NULL) {
2345 if (ns->prefix == NULL) {
2346 return(xmlStrdup(ns->href));
2347 }
2348 ns = ns->next;
2349 }
2350 return NULL;
2351 }
2352 return(xmlGetNoNsProp(reader->node, name));
2353 }
2354
2355 /*
2356 * Namespace default decl
2357 */
2358 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2359 ns = reader->node->nsDef;
2360 while (ns != NULL) {
2361 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2362 ret = xmlStrdup(ns->href);
2363 break;
2364 }
2365 ns = ns->next;
2366 }
2367 } else {
2368 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2369 if (ns != NULL)
2370 ret = xmlGetNsProp(reader->node, localname, ns->href);
2371 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002372
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002373 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002374 if (prefix != NULL)
2375 xmlFree(prefix);
2376 return(ret);
2377}
2378
2379
2380/**
2381 * xmlTextReaderGetAttributeNs:
2382 * @reader: the xmlTextReaderPtr used
2383 * @localName: the local name of the attribute.
2384 * @namespaceURI: the namespace URI of the attribute.
2385 *
2386 * Provides the value of the specified attribute
2387 *
2388 * Returns a string containing the value of the specified attribute, or NULL
2389 * in case of error. The string must be deallocated by the caller.
2390 */
2391xmlChar *
2392xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2393 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002394 xmlChar *prefix = NULL;
2395 xmlNsPtr ns;
2396
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002397 if ((reader == NULL) || (localName == NULL))
2398 return(NULL);
2399 if (reader->node == NULL)
2400 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002401 if (reader->curnode != NULL)
2402 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002403
2404 /* TODO: handle the xmlDecl */
2405 if (reader->node->type != XML_ELEMENT_NODE)
2406 return(NULL);
2407
Daniel Veillard45b97e72005-08-20 21:14:28 +00002408 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2409 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2410 prefix = BAD_CAST localName;
2411 }
2412 ns = reader->node->nsDef;
2413 while (ns != NULL) {
2414 if ((prefix == NULL && ns->prefix == NULL) ||
2415 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2416 return xmlStrdup(ns->href);
2417 }
2418 ns = ns->next;
2419 }
2420 return NULL;
2421 }
2422
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002423 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2424}
2425
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002426/**
2427 * xmlTextReaderGetRemainder:
2428 * @reader: the xmlTextReaderPtr used
2429 *
2430 * Method to get the remainder of the buffered XML. this method stops the
2431 * parser, set its state to End Of File and return the input stream with
2432 * what is left that the parser did not use.
2433 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002434 * The implementation is not good, the parser certainly procgressed past
2435 * what's left in reader->input, and there is an allocation problem. Best
2436 * would be to rewrite it differently.
2437 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002438 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2439 * in case of error.
2440 */
2441xmlParserInputBufferPtr
2442xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2443 xmlParserInputBufferPtr ret = NULL;
2444
2445 if (reader == NULL)
2446 return(NULL);
2447 if (reader->node == NULL)
2448 return(NULL);
2449
2450 reader->node = NULL;
2451 reader->curnode = NULL;
2452 reader->mode = XML_TEXTREADER_MODE_EOF;
2453 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002454 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002455 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002456 if (reader->preserve == 0)
2457 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002458 reader->ctxt->myDoc = NULL;
2459 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002460 }
2461 if (reader->allocs & XML_TEXTREADER_INPUT) {
2462 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002463 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002464 reader->allocs -= XML_TEXTREADER_INPUT;
2465 } else {
2466 /*
2467 * Hum, one may need to duplicate the data structure because
2468 * without reference counting the input may be freed twice:
2469 * - by the layer which allocated it.
2470 * - by the layer to which would have been returned to.
2471 */
2472 TODO
2473 return(NULL);
2474 }
2475 return(ret);
2476}
2477
2478/**
2479 * xmlTextReaderLookupNamespace:
2480 * @reader: the xmlTextReaderPtr used
2481 * @prefix: the prefix whose namespace URI is to be resolved. To return
2482 * the default namespace, specify NULL
2483 *
2484 * Resolves a namespace prefix in the scope of the current element.
2485 *
2486 * Returns a string containing the namespace URI to which the prefix maps
2487 * or NULL in case of error. The string must be deallocated by the caller.
2488 */
2489xmlChar *
2490xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2491 xmlNsPtr ns;
2492
2493 if (reader == NULL)
2494 return(NULL);
2495 if (reader->node == NULL)
2496 return(NULL);
2497
2498 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2499 if (ns == NULL)
2500 return(NULL);
2501 return(xmlStrdup(ns->href));
2502}
2503
2504/**
2505 * xmlTextReaderMoveToAttributeNo:
2506 * @reader: the xmlTextReaderPtr used
2507 * @no: the zero-based index of the attribute relative to the containing
2508 * element.
2509 *
2510 * Moves the position of the current instance to the attribute with
2511 * the specified index relative to the containing element.
2512 *
2513 * Returns 1 in case of success, -1 in case of error, 0 if not found
2514 */
2515int
2516xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2517 int i;
2518 xmlAttrPtr cur;
2519 xmlNsPtr ns;
2520
2521 if (reader == NULL)
2522 return(-1);
2523 if (reader->node == NULL)
2524 return(-1);
2525 /* TODO: handle the xmlDecl */
2526 if (reader->node->type != XML_ELEMENT_NODE)
2527 return(-1);
2528
2529 reader->curnode = NULL;
2530
2531 ns = reader->node->nsDef;
2532 for (i = 0;(i < no) && (ns != NULL);i++) {
2533 ns = ns->next;
2534 }
2535 if (ns != NULL) {
2536 reader->curnode = (xmlNodePtr) ns;
2537 return(1);
2538 }
2539
2540 cur = reader->node->properties;
2541 if (cur == NULL)
2542 return(0);
2543 for (;i < no;i++) {
2544 cur = cur->next;
2545 if (cur == NULL)
2546 return(0);
2547 }
2548 /* TODO walk the DTD if present */
2549
2550 reader->curnode = (xmlNodePtr) cur;
2551 return(1);
2552}
2553
2554/**
2555 * xmlTextReaderMoveToAttribute:
2556 * @reader: the xmlTextReaderPtr used
2557 * @name: the qualified name of the attribute.
2558 *
2559 * Moves the position of the current instance to the attribute with
2560 * the specified qualified name.
2561 *
2562 * Returns 1 in case of success, -1 in case of error, 0 if not found
2563 */
2564int
2565xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2566 xmlChar *prefix = NULL;
2567 xmlChar *localname;
2568 xmlNsPtr ns;
2569 xmlAttrPtr prop;
2570
2571 if ((reader == NULL) || (name == NULL))
2572 return(-1);
2573 if (reader->node == NULL)
2574 return(-1);
2575
2576 /* TODO: handle the xmlDecl */
2577 if (reader->node->type != XML_ELEMENT_NODE)
2578 return(0);
2579
2580 localname = xmlSplitQName2(name, &prefix);
2581 if (localname == NULL) {
2582 /*
2583 * Namespace default decl
2584 */
2585 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2586 ns = reader->node->nsDef;
2587 while (ns != NULL) {
2588 if (ns->prefix == NULL) {
2589 reader->curnode = (xmlNodePtr) ns;
2590 return(1);
2591 }
2592 ns = ns->next;
2593 }
2594 return(0);
2595 }
2596
2597 prop = reader->node->properties;
2598 while (prop != NULL) {
2599 /*
2600 * One need to have
2601 * - same attribute names
2602 * - and the attribute carrying that namespace
2603 */
2604 if ((xmlStrEqual(prop->name, name)) &&
2605 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2606 reader->curnode = (xmlNodePtr) prop;
2607 return(1);
2608 }
2609 prop = prop->next;
2610 }
2611 return(0);
2612 }
2613
2614 /*
2615 * Namespace default decl
2616 */
2617 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2618 ns = reader->node->nsDef;
2619 while (ns != NULL) {
2620 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2621 reader->curnode = (xmlNodePtr) ns;
2622 goto found;
2623 }
2624 ns = ns->next;
2625 }
2626 goto not_found;
2627 }
2628 prop = reader->node->properties;
2629 while (prop != NULL) {
2630 /*
2631 * One need to have
2632 * - same attribute names
2633 * - and the attribute carrying that namespace
2634 */
2635 if ((xmlStrEqual(prop->name, localname)) &&
2636 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2637 reader->curnode = (xmlNodePtr) prop;
2638 goto found;
2639 }
2640 prop = prop->next;
2641 }
2642not_found:
2643 if (localname != NULL)
2644 xmlFree(localname);
2645 if (prefix != NULL)
2646 xmlFree(prefix);
2647 return(0);
2648
2649found:
2650 if (localname != NULL)
2651 xmlFree(localname);
2652 if (prefix != NULL)
2653 xmlFree(prefix);
2654 return(1);
2655}
2656
2657/**
2658 * xmlTextReaderMoveToAttributeNs:
2659 * @reader: the xmlTextReaderPtr used
2660 * @localName: the local name of the attribute.
2661 * @namespaceURI: the namespace URI of the attribute.
2662 *
2663 * Moves the position of the current instance to the attribute with the
2664 * specified local name and namespace URI.
2665 *
2666 * Returns 1 in case of success, -1 in case of error, 0 if not found
2667 */
2668int
2669xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2670 const xmlChar *localName, const xmlChar *namespaceURI) {
2671 xmlAttrPtr prop;
2672 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002673 xmlNsPtr ns;
2674 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002675
2676 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2677 return(-1);
2678 if (reader->node == NULL)
2679 return(-1);
2680 if (reader->node->type != XML_ELEMENT_NODE)
2681 return(0);
2682 node = reader->node;
2683
Daniel Veillard45b97e72005-08-20 21:14:28 +00002684 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2685 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2686 prefix = BAD_CAST localName;
2687 }
2688 ns = reader->node->nsDef;
2689 while (ns != NULL) {
2690 if ((prefix == NULL && ns->prefix == NULL) ||
2691 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2692 reader->curnode = (xmlNodePtr) ns;
2693 return(1);
2694 }
2695 ns = ns->next;
2696 }
2697 return(0);
2698 }
2699
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002700 prop = node->properties;
2701 while (prop != NULL) {
2702 /*
2703 * One need to have
2704 * - same attribute names
2705 * - and the attribute carrying that namespace
2706 */
2707 if (xmlStrEqual(prop->name, localName) &&
2708 ((prop->ns != NULL) &&
2709 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2710 reader->curnode = (xmlNodePtr) prop;
2711 return(1);
2712 }
2713 prop = prop->next;
2714 }
2715 return(0);
2716}
2717
2718/**
2719 * xmlTextReaderMoveToFirstAttribute:
2720 * @reader: the xmlTextReaderPtr used
2721 *
2722 * Moves the position of the current instance to the first attribute
2723 * associated with the current node.
2724 *
2725 * Returns 1 in case of success, -1 in case of error, 0 if not found
2726 */
2727int
2728xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2729 if (reader == NULL)
2730 return(-1);
2731 if (reader->node == NULL)
2732 return(-1);
2733 if (reader->node->type != XML_ELEMENT_NODE)
2734 return(0);
2735
2736 if (reader->node->nsDef != NULL) {
2737 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2738 return(1);
2739 }
2740 if (reader->node->properties != NULL) {
2741 reader->curnode = (xmlNodePtr) reader->node->properties;
2742 return(1);
2743 }
2744 return(0);
2745}
2746
2747/**
2748 * xmlTextReaderMoveToNextAttribute:
2749 * @reader: the xmlTextReaderPtr used
2750 *
2751 * Moves the position of the current instance to the next attribute
2752 * associated with the current node.
2753 *
2754 * Returns 1 in case of success, -1 in case of error, 0 if not found
2755 */
2756int
2757xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2758 if (reader == NULL)
2759 return(-1);
2760 if (reader->node == NULL)
2761 return(-1);
2762 if (reader->node->type != XML_ELEMENT_NODE)
2763 return(0);
2764 if (reader->curnode == NULL)
2765 return(xmlTextReaderMoveToFirstAttribute(reader));
2766
2767 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2768 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2769 if (ns->next != NULL) {
2770 reader->curnode = (xmlNodePtr) ns->next;
2771 return(1);
2772 }
2773 if (reader->node->properties != NULL) {
2774 reader->curnode = (xmlNodePtr) reader->node->properties;
2775 return(1);
2776 }
2777 return(0);
2778 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2779 (reader->curnode->next != NULL)) {
2780 reader->curnode = reader->curnode->next;
2781 return(1);
2782 }
2783 return(0);
2784}
2785
2786/**
2787 * xmlTextReaderMoveToElement:
2788 * @reader: the xmlTextReaderPtr used
2789 *
2790 * Moves the position of the current instance to the node that
2791 * contains the current Attribute node.
2792 *
2793 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2794 */
2795int
2796xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2797 if (reader == NULL)
2798 return(-1);
2799 if (reader->node == NULL)
2800 return(-1);
2801 if (reader->node->type != XML_ELEMENT_NODE)
2802 return(0);
2803 if (reader->curnode != NULL) {
2804 reader->curnode = NULL;
2805 return(1);
2806 }
2807 return(0);
2808}
2809
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002810/**
2811 * xmlTextReaderReadAttributeValue:
2812 * @reader: the xmlTextReaderPtr used
2813 *
2814 * Parses an attribute value into one or more Text and EntityReference nodes.
2815 *
2816 * Returns 1 in case of success, 0 if the reader was not positionned on an
2817 * ttribute node or all the attribute values have been read, or -1
2818 * in case of error.
2819 */
2820int
2821xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2822 if (reader == NULL)
2823 return(-1);
2824 if (reader->node == NULL)
2825 return(-1);
2826 if (reader->curnode == NULL)
2827 return(0);
2828 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2829 if (reader->curnode->children == NULL)
2830 return(0);
2831 reader->curnode = reader->curnode->children;
2832 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2833 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2834
2835 if (reader->faketext == NULL) {
2836 reader->faketext = xmlNewDocText(reader->node->doc,
2837 ns->href);
2838 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002839 if ((reader->faketext->content != NULL) &&
2840 (reader->faketext->content !=
2841 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002842 xmlFree(reader->faketext->content);
2843 reader->faketext->content = xmlStrdup(ns->href);
2844 }
2845 reader->curnode = reader->faketext;
2846 } else {
2847 if (reader->curnode->next == NULL)
2848 return(0);
2849 reader->curnode = reader->curnode->next;
2850 }
2851 return(1);
2852}
2853
Daniel Veillarde2811272004-10-19 09:04:23 +00002854/**
2855 * xmlTextReaderConstEncoding:
2856 * @reader: the xmlTextReaderPtr used
2857 *
2858 * Determine the encoding of the document being read.
2859 *
2860 * Returns a string containing the encoding of the document or NULL in
2861 * case of error. The string is deallocated with the reader.
2862 */
2863const xmlChar *
2864xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2865 xmlDocPtr doc = NULL;
2866 if (reader == NULL)
2867 return(NULL);
2868 if (reader->doc != NULL)
2869 doc = reader->doc;
2870 else if (reader->ctxt != NULL)
2871 doc = reader->ctxt->myDoc;
2872 if (doc == NULL)
2873 return(NULL);
2874
2875 if (doc->encoding == NULL)
2876 return(NULL);
2877 else
2878 return(CONSTSTR(doc->encoding));
2879}
2880
2881
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002882/************************************************************************
2883 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002884 * Acces API to the current node *
2885 * *
2886 ************************************************************************/
2887/**
2888 * xmlTextReaderAttributeCount:
2889 * @reader: the xmlTextReaderPtr used
2890 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002891 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002892 *
2893 * Returns 0 i no attributes, -1 in case of error or the attribute count
2894 */
2895int
2896xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2897 int ret;
2898 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002899 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002900 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002901
2902 if (reader == NULL)
2903 return(-1);
2904 if (reader->node == NULL)
2905 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002906
2907 if (reader->curnode != NULL)
2908 node = reader->curnode;
2909 else
2910 node = reader->node;
2911
2912 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002913 return(0);
2914 if ((reader->state == XML_TEXTREADER_END) ||
2915 (reader->state == XML_TEXTREADER_BACKTRACK))
2916 return(0);
2917 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002918 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919 while (attr != NULL) {
2920 ret++;
2921 attr = attr->next;
2922 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002923 ns = node->nsDef;
2924 while (ns != NULL) {
2925 ret++;
2926 ns = ns->next;
2927 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002928 return(ret);
2929}
2930
2931/**
2932 * xmlTextReaderNodeType:
2933 * @reader: the xmlTextReaderPtr used
2934 *
2935 * Get the node type of the current node
2936 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002937 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002938 *
2939 * Returns the xmlNodeType of the current node or -1 in case of error
2940 */
2941int
2942xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002943 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002944
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002945 if (reader == NULL)
2946 return(-1);
2947 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002948 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002949 if (reader->curnode != NULL)
2950 node = reader->curnode;
2951 else
2952 node = reader->node;
2953 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002954 case XML_ELEMENT_NODE:
2955 if ((reader->state == XML_TEXTREADER_END) ||
2956 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002957 return(XML_READER_TYPE_END_ELEMENT);
2958 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002959 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002960 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002961 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002962 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002963 if (xmlIsBlankNode(reader->node)) {
2964 if (xmlNodeGetSpacePreserve(reader->node))
2965 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2966 else
2967 return(XML_READER_TYPE_WHITESPACE);
2968 } else {
2969 return(XML_READER_TYPE_TEXT);
2970 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002971 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002972 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002973 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002974 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002975 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002976 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002977 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002978 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002979 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002980 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002981 case XML_DOCUMENT_NODE:
2982 case XML_HTML_DOCUMENT_NODE:
2983#ifdef LIBXML_DOCB_ENABLED
2984 case XML_DOCB_DOCUMENT_NODE:
2985#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002986 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002987 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002988 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002989 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002990 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002991 case XML_DOCUMENT_TYPE_NODE:
2992 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002993 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002994
2995 case XML_ELEMENT_DECL:
2996 case XML_ATTRIBUTE_DECL:
2997 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002998 case XML_XINCLUDE_START:
2999 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003000 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003001 }
3002 return(-1);
3003}
3004
3005/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003006 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003007 * @reader: the xmlTextReaderPtr used
3008 *
3009 * Check if the current node is empty
3010 *
3011 * Returns 1 if empty, 0 if not and -1 in case of error
3012 */
3013int
3014xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3015 if ((reader == NULL) || (reader->node == NULL))
3016 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003017 if (reader->node->type != XML_ELEMENT_NODE)
3018 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003019 if (reader->curnode != NULL)
3020 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003021 if (reader->node->children != NULL)
3022 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003023 if (reader->state == XML_TEXTREADER_END)
3024 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003025 if (reader->doc != NULL)
3026 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003027#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003028 if (reader->in_xinclude > 0)
3029 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003030#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003031 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003032}
3033
3034/**
3035 * xmlTextReaderLocalName:
3036 * @reader: the xmlTextReaderPtr used
3037 *
3038 * The local name of the node.
3039 *
3040 * Returns the local name or NULL if not available
3041 */
3042xmlChar *
3043xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003044 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003045 if ((reader == NULL) || (reader->node == NULL))
3046 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003047 if (reader->curnode != NULL)
3048 node = reader->curnode;
3049 else
3050 node = reader->node;
3051 if (node->type == XML_NAMESPACE_DECL) {
3052 xmlNsPtr ns = (xmlNsPtr) node;
3053 if (ns->prefix == NULL)
3054 return(xmlStrdup(BAD_CAST "xmlns"));
3055 else
3056 return(xmlStrdup(ns->prefix));
3057 }
3058 if ((node->type != XML_ELEMENT_NODE) &&
3059 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003060 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003061 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003062}
3063
3064/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003065 * xmlTextReaderConstLocalName:
3066 * @reader: the xmlTextReaderPtr used
3067 *
3068 * The local name of the node.
3069 *
3070 * Returns the local name or NULL if not available, the
3071 * string will be deallocated with the reader.
3072 */
3073const xmlChar *
3074xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3075 xmlNodePtr node;
3076 if ((reader == NULL) || (reader->node == NULL))
3077 return(NULL);
3078 if (reader->curnode != NULL)
3079 node = reader->curnode;
3080 else
3081 node = reader->node;
3082 if (node->type == XML_NAMESPACE_DECL) {
3083 xmlNsPtr ns = (xmlNsPtr) node;
3084 if (ns->prefix == NULL)
3085 return(CONSTSTR(BAD_CAST "xmlns"));
3086 else
3087 return(ns->prefix);
3088 }
3089 if ((node->type != XML_ELEMENT_NODE) &&
3090 (node->type != XML_ATTRIBUTE_NODE))
3091 return(xmlTextReaderConstName(reader));
3092 return(node->name);
3093}
3094
3095/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003096 * xmlTextReaderName:
3097 * @reader: the xmlTextReaderPtr used
3098 *
3099 * The qualified name of the node, equal to Prefix :LocalName.
3100 *
3101 * Returns the local name or NULL if not available
3102 */
3103xmlChar *
3104xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003105 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003106 xmlChar *ret;
3107
3108 if ((reader == NULL) || (reader->node == NULL))
3109 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003110 if (reader->curnode != NULL)
3111 node = reader->curnode;
3112 else
3113 node = reader->node;
3114 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003115 case XML_ELEMENT_NODE:
3116 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003117 if ((node->ns == NULL) ||
3118 (node->ns->prefix == NULL))
3119 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003120
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003121 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003122 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003123 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003124 return(ret);
3125 case XML_TEXT_NODE:
3126 return(xmlStrdup(BAD_CAST "#text"));
3127 case XML_CDATA_SECTION_NODE:
3128 return(xmlStrdup(BAD_CAST "#cdata-section"));
3129 case XML_ENTITY_NODE:
3130 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003131 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003132 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003133 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003134 case XML_COMMENT_NODE:
3135 return(xmlStrdup(BAD_CAST "#comment"));
3136 case XML_DOCUMENT_NODE:
3137 case XML_HTML_DOCUMENT_NODE:
3138#ifdef LIBXML_DOCB_ENABLED
3139 case XML_DOCB_DOCUMENT_NODE:
3140#endif
3141 return(xmlStrdup(BAD_CAST "#document"));
3142 case XML_DOCUMENT_FRAG_NODE:
3143 return(xmlStrdup(BAD_CAST "#document-fragment"));
3144 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003145 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003146 case XML_DOCUMENT_TYPE_NODE:
3147 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003148 return(xmlStrdup(node->name));
3149 case XML_NAMESPACE_DECL: {
3150 xmlNsPtr ns = (xmlNsPtr) node;
3151
3152 ret = xmlStrdup(BAD_CAST "xmlns");
3153 if (ns->prefix == NULL)
3154 return(ret);
3155 ret = xmlStrcat(ret, BAD_CAST ":");
3156 ret = xmlStrcat(ret, ns->prefix);
3157 return(ret);
3158 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003159
3160 case XML_ELEMENT_DECL:
3161 case XML_ATTRIBUTE_DECL:
3162 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003163 case XML_XINCLUDE_START:
3164 case XML_XINCLUDE_END:
3165 return(NULL);
3166 }
3167 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003168}
3169
3170/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003171 * xmlTextReaderConstName:
3172 * @reader: the xmlTextReaderPtr used
3173 *
3174 * The qualified name of the node, equal to Prefix :LocalName.
3175 *
3176 * Returns the local name or NULL if not available, the string is
3177 * deallocated with the reader.
3178 */
3179const xmlChar *
3180xmlTextReaderConstName(xmlTextReaderPtr reader) {
3181 xmlNodePtr node;
3182
3183 if ((reader == NULL) || (reader->node == NULL))
3184 return(NULL);
3185 if (reader->curnode != NULL)
3186 node = reader->curnode;
3187 else
3188 node = reader->node;
3189 switch (node->type) {
3190 case XML_ELEMENT_NODE:
3191 case XML_ATTRIBUTE_NODE:
3192 if ((node->ns == NULL) ||
3193 (node->ns->prefix == NULL))
3194 return(node->name);
3195 return(CONSTQSTR(node->ns->prefix, node->name));
3196 case XML_TEXT_NODE:
3197 return(CONSTSTR(BAD_CAST "#text"));
3198 case XML_CDATA_SECTION_NODE:
3199 return(CONSTSTR(BAD_CAST "#cdata-section"));
3200 case XML_ENTITY_NODE:
3201 case XML_ENTITY_REF_NODE:
3202 return(CONSTSTR(node->name));
3203 case XML_PI_NODE:
3204 return(CONSTSTR(node->name));
3205 case XML_COMMENT_NODE:
3206 return(CONSTSTR(BAD_CAST "#comment"));
3207 case XML_DOCUMENT_NODE:
3208 case XML_HTML_DOCUMENT_NODE:
3209#ifdef LIBXML_DOCB_ENABLED
3210 case XML_DOCB_DOCUMENT_NODE:
3211#endif
3212 return(CONSTSTR(BAD_CAST "#document"));
3213 case XML_DOCUMENT_FRAG_NODE:
3214 return(CONSTSTR(BAD_CAST "#document-fragment"));
3215 case XML_NOTATION_NODE:
3216 return(CONSTSTR(node->name));
3217 case XML_DOCUMENT_TYPE_NODE:
3218 case XML_DTD_NODE:
3219 return(CONSTSTR(node->name));
3220 case XML_NAMESPACE_DECL: {
3221 xmlNsPtr ns = (xmlNsPtr) node;
3222
3223 if (ns->prefix == NULL)
3224 return(CONSTSTR(BAD_CAST "xmlns"));
3225 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3226 }
3227
3228 case XML_ELEMENT_DECL:
3229 case XML_ATTRIBUTE_DECL:
3230 case XML_ENTITY_DECL:
3231 case XML_XINCLUDE_START:
3232 case XML_XINCLUDE_END:
3233 return(NULL);
3234 }
3235 return(NULL);
3236}
3237
3238/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003239 * xmlTextReaderPrefix:
3240 * @reader: the xmlTextReaderPtr used
3241 *
3242 * A shorthand reference to the namespace associated with the node.
3243 *
3244 * Returns the prefix or NULL if not available
3245 */
3246xmlChar *
3247xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003248 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003249 if ((reader == NULL) || (reader->node == NULL))
3250 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003251 if (reader->curnode != NULL)
3252 node = reader->curnode;
3253 else
3254 node = reader->node;
3255 if (node->type == XML_NAMESPACE_DECL) {
3256 xmlNsPtr ns = (xmlNsPtr) node;
3257 if (ns->prefix == NULL)
3258 return(NULL);
3259 return(xmlStrdup(BAD_CAST "xmlns"));
3260 }
3261 if ((node->type != XML_ELEMENT_NODE) &&
3262 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003263 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003264 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003265 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003266 return(NULL);
3267}
3268
3269/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003270 * xmlTextReaderConstPrefix:
3271 * @reader: the xmlTextReaderPtr used
3272 *
3273 * A shorthand reference to the namespace associated with the node.
3274 *
3275 * Returns the prefix or NULL if not available, the string is deallocated
3276 * with the reader.
3277 */
3278const xmlChar *
3279xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3280 xmlNodePtr node;
3281 if ((reader == NULL) || (reader->node == NULL))
3282 return(NULL);
3283 if (reader->curnode != NULL)
3284 node = reader->curnode;
3285 else
3286 node = reader->node;
3287 if (node->type == XML_NAMESPACE_DECL) {
3288 xmlNsPtr ns = (xmlNsPtr) node;
3289 if (ns->prefix == NULL)
3290 return(NULL);
3291 return(CONSTSTR(BAD_CAST "xmlns"));
3292 }
3293 if ((node->type != XML_ELEMENT_NODE) &&
3294 (node->type != XML_ATTRIBUTE_NODE))
3295 return(NULL);
3296 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3297 return(CONSTSTR(node->ns->prefix));
3298 return(NULL);
3299}
3300
3301/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003302 * xmlTextReaderNamespaceUri:
3303 * @reader: the xmlTextReaderPtr used
3304 *
3305 * The URI defining the namespace associated with the node.
3306 *
3307 * Returns the namespace URI or NULL if not available
3308 */
3309xmlChar *
3310xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003311 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003312 if ((reader == NULL) || (reader->node == NULL))
3313 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003314 if (reader->curnode != NULL)
3315 node = reader->curnode;
3316 else
3317 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003318 if (node->type == XML_NAMESPACE_DECL)
3319 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003320 if ((node->type != XML_ELEMENT_NODE) &&
3321 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003322 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003323 if (node->ns != NULL)
3324 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003325 return(NULL);
3326}
3327
3328/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003329 * xmlTextReaderConstNamespaceUri:
3330 * @reader: the xmlTextReaderPtr used
3331 *
3332 * The URI defining the namespace associated with the node.
3333 *
3334 * Returns the namespace URI or NULL if not available, the string
3335 * will be deallocated with the reader
3336 */
3337const xmlChar *
3338xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3339 xmlNodePtr node;
3340 if ((reader == NULL) || (reader->node == NULL))
3341 return(NULL);
3342 if (reader->curnode != NULL)
3343 node = reader->curnode;
3344 else
3345 node = reader->node;
3346 if (node->type == XML_NAMESPACE_DECL)
3347 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3348 if ((node->type != XML_ELEMENT_NODE) &&
3349 (node->type != XML_ATTRIBUTE_NODE))
3350 return(NULL);
3351 if (node->ns != NULL)
3352 return(CONSTSTR(node->ns->href));
3353 return(NULL);
3354}
3355
3356/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003357 * xmlTextReaderBaseUri:
3358 * @reader: the xmlTextReaderPtr used
3359 *
3360 * The base URI of the node.
3361 *
3362 * Returns the base URI or NULL if not available
3363 */
3364xmlChar *
3365xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3366 if ((reader == NULL) || (reader->node == NULL))
3367 return(NULL);
3368 return(xmlNodeGetBase(NULL, reader->node));
3369}
3370
3371/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003372 * xmlTextReaderConstBaseUri:
3373 * @reader: the xmlTextReaderPtr used
3374 *
3375 * The base URI of the node.
3376 *
3377 * Returns the base URI or NULL if not available, the string
3378 * will be deallocated with the reader
3379 */
3380const xmlChar *
3381xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3382 xmlChar *tmp;
3383 const xmlChar *ret;
3384
3385 if ((reader == NULL) || (reader->node == NULL))
3386 return(NULL);
3387 tmp = xmlNodeGetBase(NULL, reader->node);
3388 if (tmp == NULL)
3389 return(NULL);
3390 ret = CONSTSTR(tmp);
3391 xmlFree(tmp);
3392 return(ret);
3393}
3394
3395/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003396 * xmlTextReaderDepth:
3397 * @reader: the xmlTextReaderPtr used
3398 *
3399 * The depth of the node in the tree.
3400 *
3401 * Returns the depth or -1 in case of error
3402 */
3403int
3404xmlTextReaderDepth(xmlTextReaderPtr reader) {
3405 if (reader == NULL)
3406 return(-1);
3407 if (reader->node == NULL)
3408 return(0);
3409
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003410 if (reader->curnode != NULL) {
3411 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3412 (reader->curnode->type == XML_NAMESPACE_DECL))
3413 return(reader->depth + 1);
3414 return(reader->depth + 2);
3415 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003416 return(reader->depth);
3417}
3418
3419/**
3420 * xmlTextReaderHasAttributes:
3421 * @reader: the xmlTextReaderPtr used
3422 *
3423 * Whether the node has attributes.
3424 *
3425 * Returns 1 if true, 0 if false, and -1 in case or error
3426 */
3427int
3428xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003429 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003430 if (reader == NULL)
3431 return(-1);
3432 if (reader->node == NULL)
3433 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003434 if (reader->curnode != NULL)
3435 node = reader->curnode;
3436 else
3437 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003438
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003439 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003440 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003441 return(1);
3442 /* TODO: handle the xmlDecl */
3443 return(0);
3444}
3445
3446/**
3447 * xmlTextReaderHasValue:
3448 * @reader: the xmlTextReaderPtr used
3449 *
3450 * Whether the node can have a text value.
3451 *
3452 * Returns 1 if true, 0 if false, and -1 in case or error
3453 */
3454int
3455xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003456 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003457 if (reader == NULL)
3458 return(-1);
3459 if (reader->node == NULL)
3460 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003461 if (reader->curnode != NULL)
3462 node = reader->curnode;
3463 else
3464 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003465
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003466 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003467 case XML_ATTRIBUTE_NODE:
3468 case XML_TEXT_NODE:
3469 case XML_CDATA_SECTION_NODE:
3470 case XML_PI_NODE:
3471 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003472 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003473 return(1);
3474 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003475 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003476 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003477 return(0);
3478}
3479
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003480/**
3481 * xmlTextReaderValue:
3482 * @reader: the xmlTextReaderPtr used
3483 *
3484 * Provides the text value of the node if present
3485 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003486 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003487 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003488 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003489xmlChar *
3490xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003491 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003492 if (reader == NULL)
3493 return(NULL);
3494 if (reader->node == NULL)
3495 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003496 if (reader->curnode != NULL)
3497 node = reader->curnode;
3498 else
3499 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003500
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003501 switch (node->type) {
3502 case XML_NAMESPACE_DECL:
3503 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003504 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003505 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003506
3507 if (attr->parent != NULL)
3508 return (xmlNodeListGetString
3509 (attr->parent->doc, attr->children, 1));
3510 else
3511 return (xmlNodeListGetString(NULL, attr->children, 1));
3512 break;
3513 }
3514 case XML_TEXT_NODE:
3515 case XML_CDATA_SECTION_NODE:
3516 case XML_PI_NODE:
3517 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003518 if (node->content != NULL)
3519 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003520 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003521 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003522 }
3523 return(NULL);
3524}
3525
3526/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003527 * xmlTextReaderConstValue:
3528 * @reader: the xmlTextReaderPtr used
3529 *
3530 * Provides the text value of the node if present
3531 *
3532 * Returns the string or NULL if not available. The result will be
3533 * deallocated on the next Read() operation.
3534 */
3535const xmlChar *
3536xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3537 xmlNodePtr node;
3538 if (reader == NULL)
3539 return(NULL);
3540 if (reader->node == NULL)
3541 return(NULL);
3542 if (reader->curnode != NULL)
3543 node = reader->curnode;
3544 else
3545 node = reader->node;
3546
3547 switch (node->type) {
3548 case XML_NAMESPACE_DECL:
3549 return(((xmlNsPtr) node)->href);
3550 case XML_ATTRIBUTE_NODE:{
3551 xmlAttrPtr attr = (xmlAttrPtr) node;
3552
3553 if ((attr->children != NULL) &&
3554 (attr->children->type == XML_TEXT_NODE) &&
3555 (attr->children->next == NULL))
3556 return(attr->children->content);
3557 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003558 if (reader->buffer == NULL)
3559 reader->buffer = xmlBufferCreateSize(100);
3560 if (reader->buffer == NULL) {
3561 xmlGenericError(xmlGenericErrorContext,
3562 "xmlTextReaderSetup : malloc failed\n");
3563 return (NULL);
3564 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003565 reader->buffer->use = 0;
3566 xmlNodeBufGetContent(reader->buffer, node);
3567 return(reader->buffer->content);
3568 }
3569 break;
3570 }
3571 case XML_TEXT_NODE:
3572 case XML_CDATA_SECTION_NODE:
3573 case XML_PI_NODE:
3574 case XML_COMMENT_NODE:
3575 return(node->content);
3576 default:
3577 break;
3578 }
3579 return(NULL);
3580}
3581
3582/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003583 * xmlTextReaderIsDefault:
3584 * @reader: the xmlTextReaderPtr used
3585 *
3586 * Whether an Attribute node was generated from the default value
3587 * defined in the DTD or schema.
3588 *
3589 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3590 */
3591int
3592xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3593 if (reader == NULL)
3594 return(-1);
3595 return(0);
3596}
3597
3598/**
3599 * xmlTextReaderQuoteChar:
3600 * @reader: the xmlTextReaderPtr used
3601 *
3602 * The quotation mark character used to enclose the value of an attribute.
3603 *
3604 * Returns " or ' and -1 in case of error
3605 */
3606int
3607xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3608 if (reader == NULL)
3609 return(-1);
3610 /* TODO maybe lookup the attribute value for " first */
3611 return((int) '"');
3612}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003613
3614/**
3615 * xmlTextReaderXmlLang:
3616 * @reader: the xmlTextReaderPtr used
3617 *
3618 * The xml:lang scope within which the node resides.
3619 *
3620 * Returns the xml:lang value or NULL if none exists.
3621 */
3622xmlChar *
3623xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3624 if (reader == NULL)
3625 return(NULL);
3626 if (reader->node == NULL)
3627 return(NULL);
3628 return(xmlNodeGetLang(reader->node));
3629}
3630
Daniel Veillard67df8092002-12-16 22:04:11 +00003631/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003632 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003633 * @reader: the xmlTextReaderPtr used
3634 *
3635 * The xml:lang scope within which the node resides.
3636 *
3637 * Returns the xml:lang value or NULL if none exists.
3638 */
3639const xmlChar *
3640xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3641 xmlChar *tmp;
3642 const xmlChar *ret;
3643
3644 if (reader == NULL)
3645 return(NULL);
3646 if (reader->node == NULL)
3647 return(NULL);
3648 tmp = xmlNodeGetLang(reader->node);
3649 if (tmp == NULL)
3650 return(NULL);
3651 ret = CONSTSTR(tmp);
3652 xmlFree(tmp);
3653 return(ret);
3654}
3655
3656/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003657 * xmlTextReaderConstString:
3658 * @reader: the xmlTextReaderPtr used
3659 * @str: the string to intern.
3660 *
3661 * Get an interned string from the reader, allows for example to
3662 * speedup string name comparisons
3663 *
3664 * Returns an interned copy of the string or NULL in case of error. The
3665 * string will be deallocated with the reader.
3666 */
3667const xmlChar *
3668xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3669 if (reader == NULL)
3670 return(NULL);
3671 return(CONSTSTR(str));
3672}
3673
3674/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003675 * xmlTextReaderNormalization:
3676 * @reader: the xmlTextReaderPtr used
3677 *
3678 * The value indicating whether to normalize white space and attribute values.
3679 * Since attribute value and end of line normalizations are a MUST in the XML
3680 * specification only the value true is accepted. The broken bahaviour of
3681 * accepting out of range character entities like &#0; is of course not
3682 * supported either.
3683 *
3684 * Returns 1 or -1 in case of error.
3685 */
3686int
3687xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3688 if (reader == NULL)
3689 return(-1);
3690 return(1);
3691}
3692
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003693/************************************************************************
3694 * *
3695 * Extensions to the base APIs *
3696 * *
3697 ************************************************************************/
3698
3699/**
3700 * xmlTextReaderSetParserProp:
3701 * @reader: the xmlTextReaderPtr used
3702 * @prop: the xmlParserProperties to set
3703 * @value: usually 0 or 1 to (de)activate it
3704 *
3705 * Change the parser processing behaviour by changing some of its internal
3706 * properties. Note that some properties can only be changed before any
3707 * read has been done.
3708 *
3709 * Returns 0 if the call was successful, or -1 in case of error
3710 */
3711int
3712xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3713 xmlParserProperties p = (xmlParserProperties) prop;
3714 xmlParserCtxtPtr ctxt;
3715
3716 if ((reader == NULL) || (reader->ctxt == NULL))
3717 return(-1);
3718 ctxt = reader->ctxt;
3719
3720 switch (p) {
3721 case XML_PARSER_LOADDTD:
3722 if (value != 0) {
3723 if (ctxt->loadsubset == 0) {
3724 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3725 return(-1);
3726 ctxt->loadsubset = XML_DETECT_IDS;
3727 }
3728 } else {
3729 ctxt->loadsubset = 0;
3730 }
3731 return(0);
3732 case XML_PARSER_DEFAULTATTRS:
3733 if (value != 0) {
3734 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3735 } else {
3736 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3737 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3738 }
3739 return(0);
3740 case XML_PARSER_VALIDATE:
3741 if (value != 0) {
3742 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003743 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003744 } else {
3745 ctxt->validate = 0;
3746 }
3747 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003748 case XML_PARSER_SUBST_ENTITIES:
3749 if (value != 0) {
3750 ctxt->replaceEntities = 1;
3751 } else {
3752 ctxt->replaceEntities = 0;
3753 }
3754 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003755 }
3756 return(-1);
3757}
3758
3759/**
3760 * xmlTextReaderGetParserProp:
3761 * @reader: the xmlTextReaderPtr used
3762 * @prop: the xmlParserProperties to get
3763 *
3764 * Read the parser internal property.
3765 *
3766 * Returns the value, usually 0 or 1, or -1 in case of error.
3767 */
3768int
3769xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3770 xmlParserProperties p = (xmlParserProperties) prop;
3771 xmlParserCtxtPtr ctxt;
3772
3773 if ((reader == NULL) || (reader->ctxt == NULL))
3774 return(-1);
3775 ctxt = reader->ctxt;
3776
3777 switch (p) {
3778 case XML_PARSER_LOADDTD:
3779 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3780 return(1);
3781 return(0);
3782 case XML_PARSER_DEFAULTATTRS:
3783 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3784 return(1);
3785 return(0);
3786 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003787 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003788 case XML_PARSER_SUBST_ENTITIES:
3789 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003790 }
3791 return(-1);
3792}
3793
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003794
Daniel Veillarde18fc182002-12-28 22:56:33 +00003795/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003796 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003797 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003798 *
3799 * Provide the line number of the current parsing point.
3800 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003801 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003802 */
3803int
3804xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3805{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003806 if ((reader == NULL) || (reader->ctxt == NULL) ||
3807 (reader->ctxt->input == NULL)) {
3808 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003809 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003810 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003811}
3812
3813/**
3814 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003815 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003816 *
3817 * Provide the column number of the current parsing point.
3818 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003819 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003820 */
3821int
3822xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3823{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003824 if ((reader == NULL) || (reader->ctxt == NULL) ||
3825 (reader->ctxt->input == NULL)) {
3826 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003827 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003828 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003829}
3830
3831/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003832 * xmlTextReaderCurrentNode:
3833 * @reader: the xmlTextReaderPtr used
3834 *
3835 * Hacking interface allowing to get the xmlNodePtr correponding to the
3836 * current node being accessed by the xmlTextReader. This is dangerous
3837 * because the underlying node may be destroyed on the next Reads.
3838 *
3839 * Returns the xmlNodePtr or NULL in case of error.
3840 */
3841xmlNodePtr
3842xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3843 if (reader == NULL)
3844 return(NULL);
3845
3846 if (reader->curnode != NULL)
3847 return(reader->curnode);
3848 return(reader->node);
3849}
3850
3851/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003852 * xmlTextReaderPreserve:
3853 * @reader: the xmlTextReaderPtr used
3854 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003855 * This tells the XML Reader to preserve the current node.
3856 * The caller must also use xmlTextReaderCurrentDoc() to
3857 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003858 *
3859 * Returns the xmlNodePtr or NULL in case of error.
3860 */
3861xmlNodePtr
3862xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3863 xmlNodePtr cur, parent;
3864
3865 if (reader == NULL)
3866 return(NULL);
3867
3868 if (reader->curnode != NULL)
3869 cur = reader->curnode;
3870 else
3871 cur = reader->node;
3872 if (cur == NULL)
3873 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003874
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003875 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003876 cur->extra |= NODE_IS_PRESERVED;
3877 cur->extra |= NODE_IS_SPRESERVED;
3878 }
3879 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003880
3881 parent = cur->parent;;
3882 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003883 if (parent->type == XML_ELEMENT_NODE)
3884 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003885 parent = parent->parent;
3886 }
3887 return(cur);
3888}
3889
Daniel Veillard1e906612003-12-05 14:57:46 +00003890#ifdef LIBXML_PATTERN_ENABLED
3891/**
3892 * xmlTextReaderPreservePattern:
3893 * @reader: the xmlTextReaderPtr used
3894 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003895 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003896 *
3897 * This tells the XML Reader to preserve all nodes matched by the
3898 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3899 * keep an handle on the resulting document once parsing has finished
3900 *
3901 * Returns a positive number in case of success and -1 in case of error
3902 */
3903int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003904xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3905 const xmlChar **namespaces)
3906{
Daniel Veillard1e906612003-12-05 14:57:46 +00003907 xmlPatternPtr comp;
3908
3909 if ((reader == NULL) || (pattern == NULL))
3910 return(-1);
3911
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003912 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003913 if (comp == NULL)
3914 return(-1);
3915
3916 if (reader->patternMax <= 0) {
3917 reader->patternMax = 4;
3918 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3919 sizeof(reader->patternTab[0]));
3920 if (reader->patternTab == NULL) {
3921 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3922 return (-1);
3923 }
3924 }
3925 if (reader->patternNr >= reader->patternMax) {
3926 xmlPatternPtr *tmp;
3927 reader->patternMax *= 2;
3928 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3929 reader->patternMax *
3930 sizeof(reader->patternTab[0]));
3931 if (tmp == NULL) {
3932 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3933 reader->patternMax /= 2;
3934 return (-1);
3935 }
3936 reader->patternTab = tmp;
3937 }
3938 reader->patternTab[reader->patternNr] = comp;
3939 return(reader->patternNr++);
3940}
3941#endif
3942
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003943/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003944 * xmlTextReaderCurrentDoc:
3945 * @reader: the xmlTextReaderPtr used
3946 *
3947 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003948 * current document being accessed by the xmlTextReader.
3949 * NOTE: as a result of this call, the reader will not destroy the
3950 * associated XML document and calling xmlFreeDoc() on the result
3951 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003952 *
3953 * Returns the xmlDocPtr or NULL in case of error.
3954 */
3955xmlDocPtr
3956xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003957 if (reader == NULL)
3958 return(NULL);
3959 if (reader->doc != NULL)
3960 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00003961 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003962 return(NULL);
3963
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003964 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003965 return(reader->ctxt->myDoc);
3966}
3967
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003968#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003969
3970static char *
3971xmlTextReaderBuildMessage(const char *msg, va_list ap);
3972
Daniel Veillardffa3c742005-07-21 13:24:09 +00003973static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003974xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3975
Daniel Veillardffa3c742005-07-21 13:24:09 +00003976static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003977xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3978
Daniel Veillardffa3c742005-07-21 13:24:09 +00003979static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003980{
3981 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3982 char * str;
3983 va_list ap;
3984
3985 va_start(ap,msg);
3986 str = xmlTextReaderBuildMessage(msg,ap);
3987 if (!reader->errorFunc) {
3988 xmlTextReaderValidityError(ctx, "%s", str);
3989 } else {
3990 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3991 }
3992 if (str != NULL)
3993 xmlFree(str);
3994 va_end(ap);
3995}
3996
Daniel Veillardffa3c742005-07-21 13:24:09 +00003997static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003998{
3999 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4000 char * str;
4001 va_list ap;
4002
4003 va_start(ap,msg);
4004 str = xmlTextReaderBuildMessage(msg,ap);
4005 if (!reader->errorFunc) {
4006 xmlTextReaderValidityWarning(ctx, "%s", str);
4007 } else {
4008 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
4009 }
4010 if (str != NULL)
4011 xmlFree(str);
4012 va_end(ap);
4013}
4014
4015static void
4016xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4017
4018static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4019{
4020 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4021
4022 if (reader->sErrorFunc) {
4023 reader->sErrorFunc(reader->errorFuncArg, error);
4024 } else {
4025 xmlTextReaderStructuredError(reader, error);
4026 }
4027}
4028
Daniel Veillardf4e55762003-04-15 23:32:22 +00004029/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004030 * xmlTextReaderRelaxNGSetSchema:
4031 * @reader: the xmlTextReaderPtr used
4032 * @schema: a precompiled RelaxNG schema
4033 *
4034 * Use RelaxNG to validate the document as it is processed.
4035 * Activation is only possible before the first Read().
4036 * if @schema is NULL, then RelaxNG validation is desactivated.
4037 @ The @schema should not be freed until the reader is deallocated
4038 * or its use has been deactivated.
4039 *
4040 * Returns 0 in case the RelaxNG validation could be (des)activated and
4041 * -1 in case of error.
4042 */
4043int
4044xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004045 if (reader == NULL)
4046 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004047 if (schema == NULL) {
4048 if (reader->rngSchemas != NULL) {
4049 xmlRelaxNGFree(reader->rngSchemas);
4050 reader->rngSchemas = NULL;
4051 }
4052 if (reader->rngValidCtxt != NULL) {
4053 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4054 reader->rngValidCtxt = NULL;
4055 }
4056 return(0);
4057 }
4058 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4059 return(-1);
4060 if (reader->rngSchemas != NULL) {
4061 xmlRelaxNGFree(reader->rngSchemas);
4062 reader->rngSchemas = NULL;
4063 }
4064 if (reader->rngValidCtxt != NULL) {
4065 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4066 reader->rngValidCtxt = NULL;
4067 }
4068 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4069 if (reader->rngValidCtxt == NULL)
4070 return(-1);
4071 if (reader->errorFunc != NULL) {
4072 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004073 xmlTextReaderValidityErrorRelay,
4074 xmlTextReaderValidityWarningRelay,
4075 reader);
4076 }
4077 if (reader->sErrorFunc != NULL) {
4078 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4079 xmlTextReaderValidityStructuredRelay,
4080 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004081 }
4082 reader->rngValidErrors = 0;
4083 reader->rngFullNode = NULL;
4084 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4085 return(0);
4086}
4087
4088/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004089 * xmlTextReaderSetSchema:
4090 * @reader: the xmlTextReaderPtr used
4091 * @schema: a precompiled Schema schema
4092 *
4093 * Use XSD Schema to validate the document as it is processed.
4094 * Activation is only possible before the first Read().
4095 * if @schema is NULL, then Schema validation is desactivated.
4096 @ The @schema should not be freed until the reader is deallocated
4097 * or its use has been deactivated.
4098 *
4099 * Returns 0 in case the Schema validation could be (des)activated and
4100 * -1 in case of error.
4101 */
4102int
4103xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4104 if (reader == NULL)
4105 return(-1);
4106 if (schema == NULL) {
4107 if (reader->xsdPlug != NULL) {
4108 xmlSchemaSAXUnplug(reader->xsdPlug);
4109 reader->xsdPlug = NULL;
4110 }
4111 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004112 if (! reader->xsdPreserveCtxt)
4113 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4114 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004115 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004116 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004117 if (reader->xsdSchemas != NULL) {
4118 xmlSchemaFree(reader->xsdSchemas);
4119 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004120 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004121 return(0);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004122 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004123 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4124 return(-1);
4125 if (reader->xsdPlug != NULL) {
4126 xmlSchemaSAXUnplug(reader->xsdPlug);
4127 reader->xsdPlug = NULL;
4128 }
4129 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004130 if (! reader->xsdPreserveCtxt)
4131 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004132 reader->xsdValidCtxt = NULL;
4133 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004134 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004135 if (reader->xsdSchemas != NULL) {
4136 xmlSchemaFree(reader->xsdSchemas);
4137 reader->xsdSchemas = NULL;
4138 }
4139 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4140 if (reader->xsdValidCtxt == NULL) {
4141 xmlSchemaFree(reader->xsdSchemas);
4142 reader->xsdSchemas = NULL;
4143 return(-1);
4144 }
4145 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4146 &(reader->ctxt->sax),
4147 &(reader->ctxt->userData));
4148 if (reader->xsdPlug == NULL) {
4149 xmlSchemaFree(reader->xsdSchemas);
4150 reader->xsdSchemas = NULL;
4151 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4152 reader->xsdValidCtxt = NULL;
4153 return(-1);
4154 }
4155 if (reader->errorFunc != NULL) {
4156 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004157 xmlTextReaderValidityErrorRelay,
4158 xmlTextReaderValidityWarningRelay,
4159 reader);
4160 }
4161 if (reader->sErrorFunc != NULL) {
4162 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4163 xmlTextReaderValidityStructuredRelay,
4164 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004165 }
4166 reader->xsdValidErrors = 0;
4167 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4168 return(0);
4169}
4170
4171/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004172 * xmlTextReaderRelaxNGValidate:
4173 * @reader: the xmlTextReaderPtr used
4174 * @rng: the path to a RelaxNG schema or NULL
4175 *
4176 * Use RelaxNG to validate the document as it is processed.
4177 * Activation is only possible before the first Read().
William M. Brackd46c1ca2007-02-08 23:34:34 +00004178 * if @rng is NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004179 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004180 * Returns 0 in case the RelaxNG validation could be (de)activated and
Daniel Veillardf4e55762003-04-15 23:32:22 +00004181 * -1 in case of error.
4182 */
4183int
4184xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4185 xmlRelaxNGParserCtxtPtr ctxt;
4186
4187 if (reader == NULL)
4188 return(-1);
4189
4190 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004191 if (reader->rngValidCtxt != NULL) {
4192 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4193 reader->rngValidCtxt = NULL;
4194 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004195 if (reader->rngSchemas != NULL) {
4196 xmlRelaxNGFree(reader->rngSchemas);
4197 reader->rngSchemas = NULL;
4198 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004199 return(0);
4200 }
4201 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4202 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004203 if (reader->rngSchemas != NULL) {
4204 xmlRelaxNGFree(reader->rngSchemas);
4205 reader->rngSchemas = NULL;
4206 }
4207 if (reader->rngValidCtxt != NULL) {
4208 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4209 reader->rngValidCtxt = NULL;
4210 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004211 ctxt = xmlRelaxNGNewParserCtxt(rng);
4212 if (reader->errorFunc != NULL) {
4213 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004214 xmlTextReaderValidityErrorRelay,
4215 xmlTextReaderValidityWarningRelay,
4216 reader);
4217 }
William M. Brackd46c1ca2007-02-08 23:34:34 +00004218 if (reader->sErrorFunc != NULL) {
4219 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004220 xmlTextReaderValidityStructuredRelay,
4221 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004222 }
4223 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4224 xmlRelaxNGFreeParserCtxt(ctxt);
4225 if (reader->rngSchemas == NULL)
4226 return(-1);
4227 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004228 if (reader->rngValidCtxt == NULL) {
4229 xmlRelaxNGFree(reader->rngSchemas);
4230 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004231 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004232 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004233 if (reader->errorFunc != NULL) {
4234 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004235 xmlTextReaderValidityErrorRelay,
4236 xmlTextReaderValidityWarningRelay,
4237 reader);
4238 }
4239 if (reader->sErrorFunc != NULL) {
4240 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4241 xmlTextReaderValidityStructuredRelay,
4242 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004243 }
4244 reader->rngValidErrors = 0;
4245 reader->rngFullNode = NULL;
4246 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4247 return(0);
4248}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004249
4250/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004251 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004252 * @reader: the xmlTextReaderPtr used
4253 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004254 * @ctxt: the XML Schema validation context or NULL
4255 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004256 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004257 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004258 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004259 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004260 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004261 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004262 * -1 in case of error.
4263 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004264static int
4265xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4266 const char *xsd,
4267 xmlSchemaValidCtxtPtr ctxt,
4268 int options ATTRIBUTE_UNUSED)
4269{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004270 if (reader == NULL)
4271 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004272
4273 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004274 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004275
4276 if (((xsd != NULL) || (ctxt != NULL)) &&
4277 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4278 (reader->ctxt == NULL)))
4279 return(-1);
4280
4281 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004282 if (reader->xsdPlug != NULL) {
4283 xmlSchemaSAXUnplug(reader->xsdPlug);
4284 reader->xsdPlug = NULL;
4285 }
4286 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004287 if (! reader->xsdPreserveCtxt)
4288 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004289 reader->xsdValidCtxt = NULL;
4290 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004291 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004292 if (reader->xsdSchemas != NULL) {
4293 xmlSchemaFree(reader->xsdSchemas);
4294 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004295 }
4296
4297 if ((xsd == NULL) && (ctxt == NULL)) {
4298 /* We just want to deactivate the validation, so get out. */
4299 return(0);
4300 }
4301
4302 if (xsd != NULL) {
4303 xmlSchemaParserCtxtPtr pctxt;
4304 /* Parse the schema and create validation environment. */
4305 pctxt = xmlSchemaNewParserCtxt(xsd);
4306 if (reader->errorFunc != NULL) {
4307 xmlSchemaSetParserErrors(pctxt,
4308 xmlTextReaderValidityErrorRelay,
4309 xmlTextReaderValidityWarningRelay,
4310 reader);
4311 }
4312 reader->xsdSchemas = xmlSchemaParse(pctxt);
4313 xmlSchemaFreeParserCtxt(pctxt);
4314 if (reader->xsdSchemas == NULL)
4315 return(-1);
4316 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4317 if (reader->xsdValidCtxt == NULL) {
4318 xmlSchemaFree(reader->xsdSchemas);
4319 reader->xsdSchemas = NULL;
4320 return(-1);
4321 }
4322 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4323 &(reader->ctxt->sax),
4324 &(reader->ctxt->userData));
4325 if (reader->xsdPlug == NULL) {
4326 xmlSchemaFree(reader->xsdSchemas);
4327 reader->xsdSchemas = NULL;
4328 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4329 reader->xsdValidCtxt = NULL;
4330 return(-1);
4331 }
4332 } else {
4333 /* Use the given validation context. */
4334 reader->xsdValidCtxt = ctxt;
4335 reader->xsdPreserveCtxt = 1;
4336 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4337 &(reader->ctxt->sax),
4338 &(reader->ctxt->userData));
4339 if (reader->xsdPlug == NULL) {
4340 reader->xsdValidCtxt = NULL;
4341 reader->xsdPreserveCtxt = 0;
4342 return(-1);
4343 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004344 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004345 /*
4346 * Redirect the validation context's error channels to use
4347 * the reader channels.
4348 * TODO: In case the user provides the validation context we
4349 * could make this redirection optional.
4350 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004351 if (reader->errorFunc != NULL) {
4352 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004353 xmlTextReaderValidityErrorRelay,
4354 xmlTextReaderValidityWarningRelay,
4355 reader);
4356 }
4357 if (reader->sErrorFunc != NULL) {
4358 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4359 xmlTextReaderValidityStructuredRelay,
4360 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004361 }
4362 reader->xsdValidErrors = 0;
4363 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4364 return(0);
4365}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004366
4367/**
4368 * xmlTextReaderSchemaValidateCtxt:
4369 * @reader: the xmlTextReaderPtr used
4370 * @ctxt: the XML Schema validation context or NULL
4371 * @options: options (not used yet)
4372 *
4373 * Use W3C XSD schema context to validate the document as it is processed.
4374 * Activation is only possible before the first Read().
4375 * If @ctxt is NULL, then XML Schema validation is deactivated.
4376 *
4377 * Returns 0 in case the schemas validation could be (de)activated and
4378 * -1 in case of error.
4379 */
4380int
4381xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4382 xmlSchemaValidCtxtPtr ctxt,
4383 int options)
4384{
4385 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4386}
4387
4388/**
4389 * xmlTextReaderSchemaValidate:
4390 * @reader: the xmlTextReaderPtr used
4391 * @xsd: the path to a W3C XSD schema or NULL
4392 *
4393 * Use W3C XSD schema to validate the document as it is processed.
4394 * Activation is only possible before the first Read().
4395 * If @xsd is NULL, then XML Schema validation is deactivated.
4396 *
4397 * Returns 0 in case the schemas validation could be (de)activated and
4398 * -1 in case of error.
4399 */
4400int
4401xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4402{
4403 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4404}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004405#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004406
Daniel Veillarde2811272004-10-19 09:04:23 +00004407/**
4408 * xmlTextReaderIsNamespaceDecl:
4409 * @reader: the xmlTextReaderPtr used
4410 *
4411 * Determine whether the current node is a namespace declaration
4412 * rather than a regular attribute.
4413 *
4414 * Returns 1 if the current node is a namespace declaration, 0 if it
4415 * is a regular attribute or other type of node, or -1 in case of
4416 * error.
4417 */
4418int
4419xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4420 xmlNodePtr node;
4421 if (reader == NULL)
4422 return(-1);
4423 if (reader->node == NULL)
4424 return(-1);
4425 if (reader->curnode != NULL)
4426 node = reader->curnode;
4427 else
4428 node = reader->node;
4429
4430 if (XML_NAMESPACE_DECL == node->type)
4431 return(1);
4432 else
4433 return(0);
4434}
4435
4436/**
4437 * xmlTextReaderConstXmlVersion:
4438 * @reader: the xmlTextReaderPtr used
4439 *
4440 * Determine the XML version of the document being read.
4441 *
4442 * Returns a string containing the XML version of the document or NULL
4443 * in case of error. The string is deallocated with the reader.
4444 */
4445const xmlChar *
4446xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4447 xmlDocPtr doc = NULL;
4448 if (reader == NULL)
4449 return(NULL);
4450 if (reader->doc != NULL)
4451 doc = reader->doc;
4452 else if (reader->ctxt != NULL)
4453 doc = reader->ctxt->myDoc;
4454 if (doc == NULL)
4455 return(NULL);
4456
4457 if (doc->version == NULL)
4458 return(NULL);
4459 else
4460 return(CONSTSTR(doc->version));
4461}
4462
4463/**
4464 * xmlTextReaderStandalone:
4465 * @reader: the xmlTextReaderPtr used
4466 *
4467 * Determine the standalone status of the document being read.
4468 *
4469 * Returns 1 if the document was declared to be standalone, 0 if it
4470 * was declared to be not standalone, or -1 if the document did not
4471 * specify its standalone status or in case of error.
4472 */
4473int
4474xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4475 xmlDocPtr doc = NULL;
4476 if (reader == NULL)
4477 return(-1);
4478 if (reader->doc != NULL)
4479 doc = reader->doc;
4480 else if (reader->ctxt != NULL)
4481 doc = reader->ctxt->myDoc;
4482 if (doc == NULL)
4483 return(-1);
4484
4485 return(doc->standalone);
4486}
4487
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004488/************************************************************************
4489 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004490 * Error Handling Extensions *
4491 * *
4492 ************************************************************************/
4493
4494/* helper to build a xmlMalloc'ed string from a format and va_list */
4495static char *
4496xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4497 int size;
4498 int chars;
4499 char *larger;
4500 char *str;
4501
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004502 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004503 if (str == NULL) {
4504 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4505 return NULL;
4506 }
4507
4508 size = 150;
4509
4510 while (1) {
4511 chars = vsnprintf(str, size, msg, ap);
4512 if ((chars > -1) && (chars < size))
4513 break;
4514 if (chars > -1)
4515 size += chars + 1;
4516 else
4517 size += 100;
4518 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4519 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4520 xmlFree(str);
4521 return NULL;
4522 }
4523 str = larger;
4524 }
4525
4526 return str;
4527}
4528
Daniel Veillard417be3a2003-01-20 21:26:34 +00004529/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004530 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004531 * @locator: the xmlTextReaderLocatorPtr used
4532 *
4533 * Obtain the line number for the given locator.
4534 *
4535 * Returns the line number or -1 in case of error.
4536 */
4537int
4538xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4539 /* we know that locator is a xmlParserCtxtPtr */
4540 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4541 int ret = -1;
4542
Daniel Veillardce682bc2004-11-05 17:22:25 +00004543 if (locator == NULL)
4544 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004545 if (ctx->node != NULL) {
4546 ret = xmlGetLineNo(ctx->node);
4547 }
4548 else {
4549 /* inspired from error.c */
4550 xmlParserInputPtr input;
4551 input = ctx->input;
4552 if ((input->filename == NULL) && (ctx->inputNr > 1))
4553 input = ctx->inputTab[ctx->inputNr - 2];
4554 if (input != NULL) {
4555 ret = input->line;
4556 }
4557 else {
4558 ret = -1;
4559 }
4560 }
4561
4562 return ret;
4563}
4564
4565/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004566 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004567 * @locator: the xmlTextReaderLocatorPtr used
4568 *
4569 * Obtain the base URI for the given locator.
4570 *
4571 * Returns the base URI or NULL in case of error.
4572 */
4573xmlChar *
4574xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4575 /* we know that locator is a xmlParserCtxtPtr */
4576 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4577 xmlChar *ret = NULL;
4578
Daniel Veillardce682bc2004-11-05 17:22:25 +00004579 if (locator == NULL)
4580 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004581 if (ctx->node != NULL) {
4582 ret = xmlNodeGetBase(NULL,ctx->node);
4583 }
4584 else {
4585 /* inspired from error.c */
4586 xmlParserInputPtr input;
4587 input = ctx->input;
4588 if ((input->filename == NULL) && (ctx->inputNr > 1))
4589 input = ctx->inputTab[ctx->inputNr - 2];
4590 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004591 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004592 }
4593 else {
4594 ret = NULL;
4595 }
4596 }
4597
4598 return ret;
4599}
4600
Daniel Veillard26f70262003-01-16 22:45:08 +00004601static void
William M. Brack899e64a2003-09-26 18:03:42 +00004602xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004603 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4604 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4605
William M. Bracka3215c72004-07-31 16:24:01 +00004606 if (str != NULL) {
4607 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004608 reader->errorFunc(reader->errorFuncArg,
4609 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004610 severity,
4611 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004612 xmlFree(str);
4613 }
4614}
4615
4616static void
William M. Brack93d004f2004-02-03 00:14:10 +00004617xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4618 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4619 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4620
4621 if (error && reader->sErrorFunc) {
4622 reader->sErrorFunc(reader->errorFuncArg,
4623 (xmlErrorPtr) error);
4624 }
4625}
4626
Daniel Veillardffa3c742005-07-21 13:24:09 +00004627static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004628xmlTextReaderError(void *ctxt, const char *msg, ...) {
4629 va_list ap;
4630
4631 va_start(ap,msg);
4632 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004633 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004634 xmlTextReaderBuildMessage(msg,ap));
4635 va_end(ap);
4636
4637}
4638
Daniel Veillardffa3c742005-07-21 13:24:09 +00004639static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004640xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4641 va_list ap;
4642
4643 va_start(ap,msg);
4644 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004645 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004646 xmlTextReaderBuildMessage(msg,ap));
4647 va_end(ap);
4648}
4649
Daniel Veillardffa3c742005-07-21 13:24:09 +00004650static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004651xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4652 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004653 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004654
Daniel Veillard417be3a2003-01-20 21:26:34 +00004655 if ((len > 1) && (msg[len - 2] != ':')) {
4656 /*
4657 * some callbacks only report locator information:
4658 * skip them (mimicking behaviour in error.c)
4659 */
4660 va_start(ap,msg);
4661 xmlTextReaderGenericError(ctxt,
4662 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4663 xmlTextReaderBuildMessage(msg,ap));
4664 va_end(ap);
4665 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004666}
4667
Daniel Veillardffa3c742005-07-21 13:24:09 +00004668static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004669xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4670 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004671 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004672
Daniel Veillard417be3a2003-01-20 21:26:34 +00004673 if ((len != 0) && (msg[len - 1] != ':')) {
4674 /*
4675 * some callbacks only report locator information:
4676 * skip them (mimicking behaviour in error.c)
4677 */
4678 va_start(ap,msg);
4679 xmlTextReaderGenericError(ctxt,
4680 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4681 xmlTextReaderBuildMessage(msg,ap));
4682 va_end(ap);
4683 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004684}
4685
4686/**
4687 * xmlTextReaderSetErrorHandler:
4688 * @reader: the xmlTextReaderPtr used
4689 * @f: the callback function to call on error and warnings
4690 * @arg: a user argument to pass to the callback function
4691 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004692 * Register a callback function that will be called on error and warnings.
4693 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004694 * If @f is NULL, the default error and warning handlers are restored.
4695 */
4696void
4697xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4698 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004699 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004700 if (f != NULL) {
4701 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004702 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004703 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4704 reader->ctxt->sax->warning = xmlTextReaderWarning;
4705 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4706 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004707 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004708 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004709#ifdef LIBXML_SCHEMAS_ENABLED
4710 if (reader->rngValidCtxt) {
4711 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4712 xmlTextReaderValidityErrorRelay,
4713 xmlTextReaderValidityWarningRelay,
4714 reader);
4715 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4716 }
4717 if (reader->xsdValidCtxt) {
4718 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4719 xmlTextReaderValidityErrorRelay,
4720 xmlTextReaderValidityWarningRelay,
4721 reader);
4722 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4723 }
4724#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004725 }
4726 else {
4727 /* restore defaults */
4728 reader->ctxt->sax->error = xmlParserError;
4729 reader->ctxt->vctxt.error = xmlParserValidityError;
4730 reader->ctxt->sax->warning = xmlParserWarning;
4731 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4732 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004733 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004734 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004735#ifdef LIBXML_SCHEMAS_ENABLED
4736 if (reader->rngValidCtxt) {
4737 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4738 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4739 }
4740 if (reader->xsdValidCtxt) {
4741 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4742 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4743 }
4744#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004745 }
4746}
4747
Daniel Veillard417be3a2003-01-20 21:26:34 +00004748/**
William M. Brack93d004f2004-02-03 00:14:10 +00004749* xmlTextReaderSetStructuredErrorHandler:
4750 * @reader: the xmlTextReaderPtr used
4751 * @f: the callback function to call on error and warnings
4752 * @arg: a user argument to pass to the callback function
4753 *
4754 * Register a callback function that will be called on error and warnings.
4755 *
4756 * If @f is NULL, the default error and warning handlers are restored.
4757 */
4758void
4759xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4760 xmlStructuredErrorFunc f,
4761 void *arg) {
4762 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004763 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004764 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4765 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4766 reader->ctxt->sax->warning = xmlTextReaderWarning;
4767 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4768 reader->sErrorFunc = f;
4769 reader->errorFunc = NULL;
4770 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004771#ifdef LIBXML_SCHEMAS_ENABLED
4772 if (reader->rngValidCtxt) {
4773 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4774 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4775 xmlTextReaderValidityStructuredRelay,
4776 reader);
4777 }
4778 if (reader->xsdValidCtxt) {
4779 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4780 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4781 xmlTextReaderValidityStructuredRelay,
4782 reader);
4783 }
4784#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004785 }
4786 else {
4787 /* restore defaults */
4788 reader->ctxt->sax->error = xmlParserError;
4789 reader->ctxt->sax->serror = NULL;
4790 reader->ctxt->vctxt.error = xmlParserValidityError;
4791 reader->ctxt->sax->warning = xmlParserWarning;
4792 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4793 reader->errorFunc = NULL;
4794 reader->sErrorFunc = NULL;
4795 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004796#ifdef LIBXML_SCHEMAS_ENABLED
4797 if (reader->rngValidCtxt) {
4798 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4799 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4800 }
4801 if (reader->xsdValidCtxt) {
4802 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4803 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4804 }
4805#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004806 }
4807}
4808
4809/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004810 * xmlTextReaderIsValid:
4811 * @reader: the xmlTextReaderPtr used
4812 *
4813 * Retrieve the validity status from the parser context
4814 *
4815 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4816 */
4817int
4818xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004819 if (reader == NULL) return(-1);
4820#ifdef LIBXML_SCHEMAS_ENABLED
4821 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4822 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004823 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4824 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004825#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004826 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004827 return(reader->ctxt->valid);
4828 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004829}
4830
4831/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004832 * xmlTextReaderGetErrorHandler:
4833 * @reader: the xmlTextReaderPtr used
4834 * @f: the callback function or NULL is no callback has been registered
4835 * @arg: a user argument
4836 *
4837 * Retrieve the error callback function and user argument.
4838 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004839void
4840xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4841 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004842 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004843 if (f != NULL) *f = reader->errorFunc;
4844 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004845}
4846
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004847
4848/************************************************************************
4849 * *
4850 * New set (2.6.0) of simpler and more flexible APIs *
4851 * *
4852 ************************************************************************/
4853
4854/**
4855 * xmlTextReaderSetup:
4856 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00004857 * @input: xmlParserInputBufferPtr used to feed the reader, will
4858 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004859 * @URL: the base URL to use for the document
4860 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004861 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004862 *
4863 * Setup an XML reader with new options
4864 *
4865 * Returns 0 in case of success and -1 in case of error.
4866 */
Aleksey Sanind8377642007-01-03 23:13:12 +00004867int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004868xmlTextReaderSetup(xmlTextReaderPtr reader,
4869 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004870 const char *encoding, int options)
4871{
William M. Brackd46c1ca2007-02-08 23:34:34 +00004872 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00004873 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00004874 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00004875 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00004876 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004877
Daniel Veillard8874b942005-08-25 13:19:21 +00004878 /*
4879 * we force the generation of compact text nodes on the reader
4880 * since usr applications should never modify the tree
4881 */
4882 options |= XML_PARSE_COMPACT;
4883
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004884 reader->doc = NULL;
4885 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004886 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004887 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004888 if ((input != NULL) && (reader->input != NULL) &&
4889 (reader->allocs & XML_TEXTREADER_INPUT)) {
4890 xmlFreeParserInputBuffer(reader->input);
4891 reader->input = NULL;
4892 reader->allocs -= XML_TEXTREADER_INPUT;
4893 }
4894 if (input != NULL) {
4895 reader->input = input;
4896 reader->allocs |= XML_TEXTREADER_INPUT;
4897 }
4898 if (reader->buffer == NULL)
4899 reader->buffer = xmlBufferCreateSize(100);
4900 if (reader->buffer == NULL) {
4901 xmlGenericError(xmlGenericErrorContext,
4902 "xmlTextReaderSetup : malloc failed\n");
4903 return (-1);
4904 }
4905 if (reader->sax == NULL)
4906 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4907 if (reader->sax == NULL) {
4908 xmlGenericError(xmlGenericErrorContext,
4909 "xmlTextReaderSetup : malloc failed\n");
4910 return (-1);
4911 }
4912 xmlSAXVersion(reader->sax, 2);
4913 reader->startElement = reader->sax->startElement;
4914 reader->sax->startElement = xmlTextReaderStartElement;
4915 reader->endElement = reader->sax->endElement;
4916 reader->sax->endElement = xmlTextReaderEndElement;
4917#ifdef LIBXML_SAX1_ENABLED
4918 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4919#endif /* LIBXML_SAX1_ENABLED */
4920 reader->startElementNs = reader->sax->startElementNs;
4921 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4922 reader->endElementNs = reader->sax->endElementNs;
4923 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4924#ifdef LIBXML_SAX1_ENABLED
4925 } else {
4926 reader->startElementNs = NULL;
4927 reader->endElementNs = NULL;
4928 }
4929#endif /* LIBXML_SAX1_ENABLED */
4930 reader->characters = reader->sax->characters;
4931 reader->sax->characters = xmlTextReaderCharacters;
4932 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4933 reader->cdataBlock = reader->sax->cdataBlock;
4934 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4935
4936 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4937 reader->node = NULL;
4938 reader->curnode = NULL;
4939 if (input != NULL) {
4940 if (reader->input->buffer->use < 4) {
4941 xmlParserInputBufferRead(input, 4);
4942 }
4943 if (reader->ctxt == NULL) {
4944 if (reader->input->buffer->use >= 4) {
4945 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4946 (const char *) reader->input->buffer->content, 4, URL);
4947 reader->base = 0;
4948 reader->cur = 4;
4949 } else {
4950 reader->ctxt =
4951 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4952 reader->base = 0;
4953 reader->cur = 0;
4954 }
4955 } else {
4956 xmlParserInputPtr inputStream;
4957 xmlParserInputBufferPtr buf;
4958 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4959
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004960 xmlCtxtReset(reader->ctxt);
4961 buf = xmlAllocParserInputBuffer(enc);
4962 if (buf == NULL) return(-1);
4963 inputStream = xmlNewInputStream(reader->ctxt);
4964 if (inputStream == NULL) {
4965 xmlFreeParserInputBuffer(buf);
4966 return(-1);
4967 }
4968
4969 if (URL == NULL)
4970 inputStream->filename = NULL;
4971 else
4972 inputStream->filename = (char *)
4973 xmlCanonicPath((const xmlChar *) URL);
4974 inputStream->buf = buf;
4975 inputStream->base = inputStream->buf->buffer->content;
4976 inputStream->cur = inputStream->buf->buffer->content;
4977 inputStream->end =
4978 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4979
4980 inputPush(reader->ctxt, inputStream);
4981 reader->cur = 0;
4982 }
4983 if (reader->ctxt == NULL) {
4984 xmlGenericError(xmlGenericErrorContext,
4985 "xmlTextReaderSetup : malloc failed\n");
4986 return (-1);
4987 }
4988 }
4989 if (reader->dict != NULL) {
4990 if (reader->ctxt->dict != NULL) {
4991 if (reader->dict != reader->ctxt->dict) {
4992 xmlDictFree(reader->dict);
4993 reader->dict = reader->ctxt->dict;
4994 }
4995 } else {
4996 reader->ctxt->dict = reader->dict;
4997 }
4998 } else {
4999 if (reader->ctxt->dict == NULL)
5000 reader->ctxt->dict = xmlDictCreate();
5001 reader->dict = reader->ctxt->dict;
5002 }
5003 reader->ctxt->_private = reader;
5004 reader->ctxt->linenumbers = 1;
5005 reader->ctxt->dictNames = 1;
5006 /*
5007 * use the parser dictionnary to allocate all elements and attributes names
5008 */
5009 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005010 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005011
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005012#ifdef LIBXML_XINCLUDE_ENABLED
5013 if (reader->xincctxt != NULL) {
5014 xmlXIncludeFreeContext(reader->xincctxt);
5015 reader->xincctxt = NULL;
5016 }
5017 if (options & XML_PARSE_XINCLUDE) {
5018 reader->xinclude = 1;
5019 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5020 options -= XML_PARSE_XINCLUDE;
5021 } else
5022 reader->xinclude = 0;
5023 reader->in_xinclude = 0;
5024#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005025#ifdef LIBXML_PATTERN_ENABLED
5026 if (reader->patternTab == NULL) {
5027 reader->patternNr = 0;
5028 reader->patternMax = 0;
5029 }
5030 while (reader->patternNr > 0) {
5031 reader->patternNr--;
5032 if (reader->patternTab[reader->patternNr] != NULL) {
5033 xmlFreePattern(reader->patternTab[reader->patternNr]);
5034 reader->patternTab[reader->patternNr] = NULL;
5035 }
5036 }
5037#endif
5038
Daniel Veillardc36965d2003-12-02 10:28:48 +00005039 if (options & XML_PARSE_DTDVALID)
5040 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5041
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005042 xmlCtxtUseOptions(reader->ctxt, options);
5043 if (encoding != NULL) {
5044 xmlCharEncodingHandlerPtr hdlr;
5045
5046 hdlr = xmlFindCharEncodingHandler(encoding);
5047 if (hdlr != NULL)
5048 xmlSwitchToEncoding(reader->ctxt, hdlr);
5049 }
5050 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5051 (reader->ctxt->input->filename == NULL))
5052 reader->ctxt->input->filename = (char *)
5053 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005054
5055 reader->doc = NULL;
5056
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005057 return (0);
5058}
5059
5060/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005061 * xmlTextReaderByteConsumed:
5062 * @reader: an XML reader
5063 *
5064 * This function provides the current index of the parser used
5065 * by the reader, relative to the start of the current entity.
5066 * This function actually just wraps a call to xmlBytesConsumed()
5067 * for the parser context associated with the reader.
5068 * See xmlBytesConsumed() for more information.
5069 *
5070 * Returns the index in bytes from the beginning of the entity or -1
5071 * in case the index could not be computed.
5072 */
5073long
5074xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5075 if ((reader == NULL) || (reader->ctxt == NULL))
5076 return(-1);
5077 return(xmlByteConsumed(reader->ctxt));
5078}
5079
5080
5081/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005082 * xmlReaderWalker:
5083 * @doc: a preparsed document
5084 *
5085 * Create an xmltextReader for a preparsed document.
5086 *
5087 * Returns the new reader or NULL in case of error.
5088 */
5089xmlTextReaderPtr
5090xmlReaderWalker(xmlDocPtr doc)
5091{
5092 xmlTextReaderPtr ret;
5093
5094 if (doc == NULL)
5095 return(NULL);
5096
5097 ret = xmlMalloc(sizeof(xmlTextReader));
5098 if (ret == NULL) {
5099 xmlGenericError(xmlGenericErrorContext,
5100 "xmlNewTextReader : malloc failed\n");
5101 return(NULL);
5102 }
5103 memset(ret, 0, sizeof(xmlTextReader));
5104 ret->entNr = 0;
5105 ret->input = NULL;
5106 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5107 ret->node = NULL;
5108 ret->curnode = NULL;
5109 ret->base = 0;
5110 ret->cur = 0;
5111 ret->allocs = XML_TEXTREADER_CTXT;
5112 ret->doc = doc;
5113 ret->state = XML_TEXTREADER_START;
5114 ret->dict = xmlDictCreate();
5115 return(ret);
5116}
5117
5118/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005119 * xmlReaderForDoc:
5120 * @cur: a pointer to a zero terminated string
5121 * @URL: the base URL to use for the document
5122 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005123 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005124 *
5125 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005126 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005127 *
5128 * Returns the new reader or NULL in case of error.
5129 */
5130xmlTextReaderPtr
5131xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5132 int options)
5133{
5134 int len;
5135
5136 if (cur == NULL)
5137 return (NULL);
5138 len = xmlStrlen(cur);
5139
5140 return (xmlReaderForMemory
5141 ((const char *) cur, len, URL, encoding, options));
5142}
5143
5144/**
5145 * xmlReaderForFile:
5146 * @filename: a file or URL
5147 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005148 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005149 *
5150 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005151 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005152 *
5153 * Returns the new reader or NULL in case of error.
5154 */
5155xmlTextReaderPtr
5156xmlReaderForFile(const char *filename, const char *encoding, int options)
5157{
5158 xmlTextReaderPtr reader;
5159
5160 reader = xmlNewTextReaderFilename(filename);
5161 if (reader == NULL)
5162 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005163 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005164 return (reader);
5165}
5166
5167/**
5168 * xmlReaderForMemory:
5169 * @buffer: a pointer to a char array
5170 * @size: the size of the array
5171 * @URL: the base URL to use for the document
5172 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005173 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005174 *
5175 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005176 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005177 *
5178 * Returns the new reader or NULL in case of error.
5179 */
5180xmlTextReaderPtr
5181xmlReaderForMemory(const char *buffer, int size, const char *URL,
5182 const char *encoding, int options)
5183{
5184 xmlTextReaderPtr reader;
5185 xmlParserInputBufferPtr buf;
5186
Daniel Veillard21924522004-02-19 16:37:07 +00005187 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005188 XML_CHAR_ENCODING_NONE);
5189 if (buf == NULL) {
5190 return (NULL);
5191 }
5192 reader = xmlNewTextReader(buf, URL);
5193 if (reader == NULL) {
5194 xmlFreeParserInputBuffer(buf);
5195 return (NULL);
5196 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005197 reader->allocs |= XML_TEXTREADER_INPUT;
5198 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005199 return (reader);
5200}
5201
5202/**
5203 * xmlReaderForFd:
5204 * @fd: an open file descriptor
5205 * @URL: the base URL to use for the document
5206 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005207 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005208 *
5209 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005210 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005211 * NOTE that the file descriptor will not be closed when the
5212 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005213 *
5214 * Returns the new reader or NULL in case of error.
5215 */
5216xmlTextReaderPtr
5217xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5218{
5219 xmlTextReaderPtr reader;
5220 xmlParserInputBufferPtr input;
5221
5222 if (fd < 0)
5223 return (NULL);
5224
5225 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5226 if (input == NULL)
5227 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005228 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005229 reader = xmlNewTextReader(input, URL);
5230 if (reader == NULL) {
5231 xmlFreeParserInputBuffer(input);
5232 return (NULL);
5233 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005234 reader->allocs |= XML_TEXTREADER_INPUT;
5235 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005236 return (reader);
5237}
5238
5239/**
5240 * xmlReaderForIO:
5241 * @ioread: an I/O read function
5242 * @ioclose: an I/O close function
5243 * @ioctx: an I/O handler
5244 * @URL: the base URL to use for the document
5245 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005246 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005247 *
5248 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005249 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005250 *
5251 * Returns the new reader or NULL in case of error.
5252 */
5253xmlTextReaderPtr
5254xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5255 void *ioctx, const char *URL, const char *encoding,
5256 int options)
5257{
5258 xmlTextReaderPtr reader;
5259 xmlParserInputBufferPtr input;
5260
5261 if (ioread == NULL)
5262 return (NULL);
5263
5264 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5265 XML_CHAR_ENCODING_NONE);
5266 if (input == NULL)
5267 return (NULL);
5268 reader = xmlNewTextReader(input, URL);
5269 if (reader == NULL) {
5270 xmlFreeParserInputBuffer(input);
5271 return (NULL);
5272 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005273 reader->allocs |= XML_TEXTREADER_INPUT;
5274 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005275 return (reader);
5276}
5277
5278/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005279 * xmlReaderNewWalker:
5280 * @reader: an XML reader
5281 * @doc: a preparsed document
5282 *
5283 * Setup an xmltextReader to parse a preparsed XML document.
5284 * This reuses the existing @reader xmlTextReader.
5285 *
5286 * Returns 0 in case of success and -1 in case of error
5287 */
5288int
5289xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5290{
5291 if (doc == NULL)
5292 return (-1);
5293 if (reader == NULL)
5294 return (-1);
5295
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005296 if (reader->input != NULL) {
5297 xmlFreeParserInputBuffer(reader->input);
5298 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005299 if (reader->ctxt != NULL) {
5300 xmlCtxtReset(reader->ctxt);
5301 }
5302
5303 reader->entNr = 0;
5304 reader->input = NULL;
5305 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5306 reader->node = NULL;
5307 reader->curnode = NULL;
5308 reader->base = 0;
5309 reader->cur = 0;
5310 reader->allocs = XML_TEXTREADER_CTXT;
5311 reader->doc = doc;
5312 reader->state = XML_TEXTREADER_START;
5313 if (reader->dict == NULL) {
5314 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5315 reader->dict = reader->ctxt->dict;
5316 else
5317 reader->dict = xmlDictCreate();
5318 }
5319 return(0);
5320}
5321
5322/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005323 * xmlReaderNewDoc:
5324 * @reader: an XML reader
5325 * @cur: a pointer to a zero terminated string
5326 * @URL: the base URL to use for the document
5327 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005328 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005329 *
5330 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005331 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005332 * This reuses the existing @reader xmlTextReader.
5333 *
5334 * Returns 0 in case of success and -1 in case of error
5335 */
5336int
5337xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5338 const char *URL, const char *encoding, int options)
5339{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005340
5341 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005342
5343 if (cur == NULL)
5344 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005345 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005346 return (-1);
5347
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005348 len = xmlStrlen(cur);
5349 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5350 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005351}
5352
5353/**
5354 * xmlReaderNewFile:
5355 * @reader: an XML reader
5356 * @filename: a file or URL
5357 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005358 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005359 *
5360 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005361 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005362 * This reuses the existing @reader xmlTextReader.
5363 *
5364 * Returns 0 in case of success and -1 in case of error
5365 */
5366int
5367xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5368 const char *encoding, int options)
5369{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005370 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005371
5372 if (filename == NULL)
5373 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005374 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005375 return (-1);
5376
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005377 input =
5378 xmlParserInputBufferCreateFilename(filename,
5379 XML_CHAR_ENCODING_NONE);
5380 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005381 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005382 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005383}
5384
5385/**
5386 * xmlReaderNewMemory:
5387 * @reader: an XML reader
5388 * @buffer: a pointer to a char array
5389 * @size: the size of the array
5390 * @URL: the base URL to use for the document
5391 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005392 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005393 *
5394 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005395 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005396 * This reuses the existing @reader xmlTextReader.
5397 *
5398 * Returns 0 in case of success and -1 in case of error
5399 */
5400int
5401xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5402 const char *URL, const char *encoding, int options)
5403{
5404 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005405
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005406 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005407 return (-1);
5408 if (buffer == NULL)
5409 return (-1);
5410
Daniel Veillard21924522004-02-19 16:37:07 +00005411 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005412 XML_CHAR_ENCODING_NONE);
5413 if (input == NULL) {
5414 return (-1);
5415 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005416 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005417}
5418
5419/**
5420 * xmlReaderNewFd:
5421 * @reader: an XML reader
5422 * @fd: an open file descriptor
5423 * @URL: the base URL to use for the document
5424 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005425 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005426 *
5427 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005428 * NOTE that the file descriptor will not be closed when the
5429 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005430 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005431 * This reuses the existing @reader xmlTextReader.
5432 *
5433 * Returns 0 in case of success and -1 in case of error
5434 */
5435int
5436xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5437 const char *URL, const char *encoding, int options)
5438{
5439 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005440
5441 if (fd < 0)
5442 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005443 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005444 return (-1);
5445
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005446 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5447 if (input == NULL)
5448 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005449 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005450 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005451}
5452
5453/**
5454 * xmlReaderNewIO:
5455 * @reader: an XML reader
5456 * @ioread: an I/O read function
5457 * @ioclose: an I/O close function
5458 * @ioctx: an I/O handler
5459 * @URL: the base URL to use for the document
5460 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005461 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005462 *
5463 * Setup an xmltextReader to parse an XML document from I/O functions
5464 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005465 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005466 * This reuses the existing @reader xmlTextReader.
5467 *
5468 * Returns 0 in case of success and -1 in case of error
5469 */
5470int
5471xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5472 xmlInputCloseCallback ioclose, void *ioctx,
5473 const char *URL, const char *encoding, int options)
5474{
5475 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005476
5477 if (ioread == NULL)
5478 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005479 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005480 return (-1);
5481
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005482 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5483 XML_CHAR_ENCODING_NONE);
5484 if (input == NULL)
5485 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005486 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005487}
Daniel Veillard26f70262003-01-16 22:45:08 +00005488/************************************************************************
5489 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005490 * Utilities *
5491 * *
5492 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005493#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005494/**
5495 * xmlBase64Decode:
5496 * @in: the input buffer
5497 * @inlen: the size of the input (in), the size read from it (out)
5498 * @to: the output buffer
5499 * @tolen: the size of the output (in), the size written to (out)
5500 *
5501 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005502 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005503 *
5504 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5505 * 2 if there wasn't enough space on the output or -1 in case of error.
5506 */
5507static int
5508xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5509 unsigned char *to, unsigned long *tolen) {
5510 unsigned long incur; /* current index in in[] */
5511 unsigned long inblk; /* last block index in in[] */
5512 unsigned long outcur; /* current index in out[] */
5513 unsigned long inmax; /* size of in[] */
5514 unsigned long outmax; /* size of out[] */
5515 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005516 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005517 int nbintmp; /* number of byte in intmp[] */
5518 int is_ignore; /* cur should be ignored */
5519 int is_end = 0; /* the end of the base64 was found */
5520 int retval = 1;
5521 int i;
5522
5523 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5524 return(-1);
5525
5526 incur = 0;
5527 inblk = 0;
5528 outcur = 0;
5529 inmax = *inlen;
5530 outmax = *tolen;
5531 nbintmp = 0;
5532
5533 while (1) {
5534 if (incur >= inmax)
5535 break;
5536 cur = in[incur++];
5537 is_ignore = 0;
5538 if ((cur >= 'A') && (cur <= 'Z'))
5539 cur = cur - 'A';
5540 else if ((cur >= 'a') && (cur <= 'z'))
5541 cur = cur - 'a' + 26;
5542 else if ((cur >= '0') && (cur <= '9'))
5543 cur = cur - '0' + 52;
5544 else if (cur == '+')
5545 cur = 62;
5546 else if (cur == '/')
5547 cur = 63;
5548 else if (cur == '.')
5549 cur = 0;
5550 else if (cur == '=') /*no op , end of the base64 stream */
5551 is_end = 1;
5552 else {
5553 is_ignore = 1;
5554 if (nbintmp == 0)
5555 inblk = incur;
5556 }
5557
5558 if (!is_ignore) {
5559 int nbouttmp = 3;
5560 int is_break = 0;
5561
5562 if (is_end) {
5563 if (nbintmp == 0)
5564 break;
5565 if ((nbintmp == 1) || (nbintmp == 2))
5566 nbouttmp = 1;
5567 else
5568 nbouttmp = 2;
5569 nbintmp = 3;
5570 is_break = 1;
5571 }
5572 intmp[nbintmp++] = cur;
5573 /*
5574 * if intmp is full, push the 4byte sequence as a 3 byte
5575 * sequence out
5576 */
5577 if (nbintmp == 4) {
5578 nbintmp = 0;
5579 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5580 outtmp[1] =
5581 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5582 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5583 if (outcur + 3 >= outmax) {
5584 retval = 2;
5585 break;
5586 }
5587
5588 for (i = 0; i < nbouttmp; i++)
5589 to[outcur++] = outtmp[i];
5590 inblk = incur;
5591 }
5592
5593 if (is_break) {
5594 retval = 0;
5595 break;
5596 }
5597 }
5598 }
5599
5600 *tolen = outcur;
5601 *inlen = inblk;
5602 return (retval);
5603}
5604
5605/*
5606 * Test routine for the xmlBase64Decode function
5607 */
5608#if 0
5609int main(int argc, char **argv) {
5610 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5611 char output[100];
5612 char output2[100];
5613 char output3[100];
5614 unsigned long inlen = strlen(input);
5615 unsigned long outlen = 100;
5616 int ret;
5617 unsigned long cons, tmp, tmp2, prod;
5618
5619 /*
5620 * Direct
5621 */
5622 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5623
5624 output[outlen] = 0;
5625 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5626
5627 /*
5628 * output chunking
5629 */
5630 cons = 0;
5631 prod = 0;
5632 while (cons < inlen) {
5633 tmp = 5;
5634 tmp2 = inlen - cons;
5635
5636 printf("%ld %ld\n", cons, prod);
5637 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5638 cons += tmp2;
5639 prod += tmp;
5640 printf("%ld %ld\n", cons, prod);
5641 }
5642 output2[outlen] = 0;
5643 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5644
5645 /*
5646 * input chunking
5647 */
5648 cons = 0;
5649 prod = 0;
5650 while (cons < inlen) {
5651 tmp = 100 - prod;
5652 tmp2 = inlen - cons;
5653 if (tmp2 > 5)
5654 tmp2 = 5;
5655
5656 printf("%ld %ld\n", cons, prod);
5657 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5658 cons += tmp2;
5659 prod += tmp;
5660 printf("%ld %ld\n", cons, prod);
5661 }
5662 output3[outlen] = 0;
5663 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5664 return(0);
5665
5666}
5667#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005668#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005669#define bottom_xmlreader
5670#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005671#endif /* LIBXML_READER_ENABLED */