blob: 3fd44f3ee403c33015bb802b6bf9e456e4b6e5b0 [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard067bae52003-01-05 01:27:54 +000015 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000016 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000017#define IN_LIBXML
18#include "libxml.h"
19
Daniel Veillard81273902003-09-30 00:43:48 +000020#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000022#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023
24#ifdef HAVE_CTYPE_H
25#include <ctype.h>
26#endif
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#include <libxml/xmlmemory.h>
32#include <libxml/xmlIO.h>
33#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000034#include <libxml/parserInternals.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000035#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +000036#include <libxml/relaxng.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000037#include <libxml/xmlschemas.h>
38#endif
Daniel Veillard198c1bf2003-10-20 17:07:41 +000039#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000040#ifdef LIBXML_XINCLUDE_ENABLED
41#include <libxml/xinclude.h>
42#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000046
47/* #define DEBUG_CALLBACKS */
48/* #define DEBUG_READER */
49
50/**
51 * TODO:
52 *
53 * macro to flag unimplemented blocks
54 */
55#define TODO \
56 xmlGenericError(xmlGenericErrorContext, \
57 "Unimplemented block at %s:%d\n", \
58 __FILE__, __LINE__);
59
60#ifdef DEBUG_READER
61#define DUMP_READER xmlTextReaderDebug(reader);
62#else
63#define DUMP_READER
64#endif
65
Daniel Veillarda880b122003-04-21 21:36:41 +000066#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000067/************************************************************************
68 * *
69 * The parser: maps the Text Reader API on top of the existing *
70 * parsing routines building a tree *
71 * *
72 ************************************************************************/
73
74#define XML_TEXTREADER_INPUT 1
75#define XML_TEXTREADER_CTXT 2
76
77typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +000078 XML_TEXTREADER_NONE = -1,
79 XML_TEXTREADER_START= 0,
80 XML_TEXTREADER_ELEMENT= 1,
81 XML_TEXTREADER_END= 2,
82 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000083 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000084 XML_TEXTREADER_DONE= 5,
85 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000086} xmlTextReaderState;
87
Daniel Veillardf4e55762003-04-15 23:32:22 +000088typedef enum {
89 XML_TEXTREADER_NOT_VALIDATE = 0,
90 XML_TEXTREADER_VALIDATE_DTD = 1,
Daniel Veillardf10ae122005-07-10 19:03:16 +000091 XML_TEXTREADER_VALIDATE_RNG = 2,
92 XML_TEXTREADER_VALIDATE_XSD = 4
Daniel Veillardf4e55762003-04-15 23:32:22 +000093} xmlTextReaderValidate;
94
Daniel Veillarde1ca5032002-12-09 14:13:43 +000095struct _xmlTextReader {
96 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +000097 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +000098 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000099 int allocs; /* what structure were deallocated */
100 xmlTextReaderState state;
101 xmlParserCtxtPtr ctxt; /* the parser context */
102 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
103 xmlParserInputBufferPtr input; /* the input */
104 startElementSAXFunc startElement;/* initial SAX callbacks */
105 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000106 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000107 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000108 charactersSAXFunc characters;
109 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000110 unsigned int base; /* base of the segment in the input */
111 unsigned int cur; /* current position in the input */
112 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000113 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000114 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000115 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000117 xmlBufferPtr buffer; /* used to return const xmlChar * */
118 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000119
120 /* entity stack when traversing entities content */
121 xmlNodePtr ent; /* Current Entity Ref Node */
122 int entNr; /* Depth of the entities stack */
123 int entMax; /* Max depth of the entities stack */
124 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000125
126 /* error handling */
127 xmlTextReaderErrorFunc errorFunc; /* callback function */
128 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000129
130#ifdef LIBXML_SCHEMAS_ENABLED
131 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000132 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
133 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000134 int rngValidErrors;/* The number of errors detected */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000135 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000136 /* Handling of Schemas validation */
137 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
138 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000139 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
140 int xsdValidErrors;/* The number of errors detected */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000141 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000142#endif
143#ifdef LIBXML_XINCLUDE_ENABLED
144 /* Handling of XInclude processing */
145 int xinclude; /* is xinclude asked for */
146 const xmlChar * xinclude_name; /* the xinclude name from dict */
147 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
148 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000149#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000150#ifdef LIBXML_PATTERN_ENABLED
151 int patternNr; /* number of preserve patterns */
152 int patternMax; /* max preserve patterns */
153 xmlPatternPtr *patternTab; /* array of preserve patterns */
154#endif
155 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000156 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000157 /* Structured error handling */
158 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000159};
160
Daniel Veillarde8039df2003-10-27 11:25:13 +0000161#define NODE_IS_EMPTY 0x1
162#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000163#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000164
Daniel Veillarde72c5082003-09-19 12:44:05 +0000165/**
166 * CONSTSTR:
167 *
168 * Macro used to return an interned string
169 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000170#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
171#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
172
173static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
174static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000175
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000176/************************************************************************
177 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000178 * Our own version of the freeing routines as we recycle nodes *
179 * *
180 ************************************************************************/
181/**
182 * DICT_FREE:
183 * @str: a string
184 *
185 * Free a string if it is not owned by the "dict" dictionnary in the
186 * current scope
187 */
188#define DICT_FREE(str) \
189 if ((str) && ((!dict) || \
190 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
191 xmlFree((char *)(str));
192
193static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
194static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
195
196/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000197 * xmlFreeID:
198 * @not: A id
199 *
200 * Deallocate the memory used by an id definition
201 */
202static void
203xmlFreeID(xmlIDPtr id) {
204 xmlDictPtr dict = NULL;
205
206 if (id == NULL) return;
207
208 if (id->doc != NULL)
209 dict = id->doc->dict;
210
211 if (id->value != NULL)
212 DICT_FREE(id->value)
213 xmlFree(id);
214}
215
216/**
217 * xmlTextReaderRemoveID:
218 * @doc: the document
219 * @attr: the attribute
220 *
221 * Remove the given attribute from the ID table maintained internally.
222 *
223 * Returns -1 if the lookup failed and 0 otherwise
224 */
225static int
226xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
227 xmlIDTablePtr table;
228 xmlIDPtr id;
229 xmlChar *ID;
230
231 if (doc == NULL) return(-1);
232 if (attr == NULL) return(-1);
233 table = (xmlIDTablePtr) doc->ids;
234 if (table == NULL)
235 return(-1);
236
237 if (attr == NULL)
238 return(-1);
239 ID = xmlNodeListGetString(doc, attr->children, 1);
240 if (ID == NULL)
241 return(-1);
242 id = xmlHashLookup(table, ID);
243 xmlFree(ID);
244 if (id == NULL || id->attr != attr) {
245 return(-1);
246 }
247 id->name = attr->name;
248 id->attr = NULL;
249 return(0);
250}
251
252/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000253 * xmlTextReaderFreeProp:
254 * @reader: the xmlTextReaderPtr used
255 * @cur: the node
256 *
257 * Free a node.
258 */
259static void
260xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
261 xmlDictPtr dict;
262
263 dict = reader->ctxt->dict;
264 if (cur == NULL) return;
265
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000266 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
267 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
268
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000269 /* Check for ID removal -> leading to invalid references ! */
270 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
271 ((cur->parent->doc->intSubset != NULL) ||
272 (cur->parent->doc->extSubset != NULL))) {
273 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000274 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000275 }
276 if (cur->children != NULL)
277 xmlTextReaderFreeNodeList(reader, cur->children);
278
279 DICT_FREE(cur->name);
280 if ((reader != NULL) && (reader->ctxt != NULL) &&
281 (reader->ctxt->freeAttrsNr < 100)) {
282 cur->next = reader->ctxt->freeAttrs;
283 reader->ctxt->freeAttrs = cur;
284 reader->ctxt->freeAttrsNr++;
285 } else {
286 xmlFree(cur);
287 }
288}
289
290/**
291 * xmlTextReaderFreePropList:
292 * @reader: the xmlTextReaderPtr used
293 * @cur: the first property in the list
294 *
295 * Free a property and all its siblings, all the children are freed too.
296 */
297static void
298xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
299 xmlAttrPtr next;
300 if (cur == NULL) return;
301 while (cur != NULL) {
302 next = cur->next;
303 xmlTextReaderFreeProp(reader, cur);
304 cur = next;
305 }
306}
307
308/**
309 * xmlTextReaderFreeNodeList:
310 * @reader: the xmlTextReaderPtr used
311 * @cur: the first node in the list
312 *
313 * Free a node and all its siblings, this is a recursive behaviour, all
314 * the children are freed too.
315 */
316static void
317xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
318 xmlNodePtr next;
319 xmlDictPtr dict;
320
321 dict = reader->ctxt->dict;
322 if (cur == NULL) return;
323 if (cur->type == XML_NAMESPACE_DECL) {
324 xmlFreeNsList((xmlNsPtr) cur);
325 return;
326 }
327 if ((cur->type == XML_DOCUMENT_NODE) ||
328 (cur->type == XML_HTML_DOCUMENT_NODE)) {
329 xmlFreeDoc((xmlDocPtr) cur);
330 return;
331 }
332 while (cur != NULL) {
333 next = cur->next;
334 /* unroll to speed up freeing the document */
335 if (cur->type != XML_DTD_NODE) {
336
337 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000338 (cur->type != XML_ENTITY_REF_NODE)) {
339 if (cur->children->parent == cur)
340 xmlTextReaderFreeNodeList(reader, cur->children);
341 cur->children = NULL;
342 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000343
344 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
345 xmlDeregisterNodeDefaultValue(cur);
346
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000347 if (((cur->type == XML_ELEMENT_NODE) ||
348 (cur->type == XML_XINCLUDE_START) ||
349 (cur->type == XML_XINCLUDE_END)) &&
350 (cur->properties != NULL))
351 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000352 if ((cur->content != (xmlChar *) &(cur->properties)) &&
353 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000354 (cur->type != XML_XINCLUDE_START) &&
355 (cur->type != XML_XINCLUDE_END) &&
356 (cur->type != XML_ENTITY_REF_NODE)) {
357 DICT_FREE(cur->content);
358 }
359 if (((cur->type == XML_ELEMENT_NODE) ||
360 (cur->type == XML_XINCLUDE_START) ||
361 (cur->type == XML_XINCLUDE_END)) &&
362 (cur->nsDef != NULL))
363 xmlFreeNsList(cur->nsDef);
364
365 /*
366 * we don't free element names here they are interned now
367 */
368 if ((cur->type != XML_TEXT_NODE) &&
369 (cur->type != XML_COMMENT_NODE))
370 DICT_FREE(cur->name);
371 if (((cur->type == XML_ELEMENT_NODE) ||
372 (cur->type == XML_TEXT_NODE)) &&
373 (reader != NULL) && (reader->ctxt != NULL) &&
374 (reader->ctxt->freeElemsNr < 100)) {
375 cur->next = reader->ctxt->freeElems;
376 reader->ctxt->freeElems = cur;
377 reader->ctxt->freeElemsNr++;
378 } else {
379 xmlFree(cur);
380 }
381 }
382 cur = next;
383 }
384}
385
386/**
387 * xmlTextReaderFreeNode:
388 * @reader: the xmlTextReaderPtr used
389 * @cur: the node
390 *
391 * Free a node, this is a recursive behaviour, all the children are freed too.
392 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
393 */
394static void
395xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
396 xmlDictPtr dict;
397
398 dict = reader->ctxt->dict;
399 if (cur->type == XML_DTD_NODE) {
400 xmlFreeDtd((xmlDtdPtr) cur);
401 return;
402 }
403 if (cur->type == XML_NAMESPACE_DECL) {
404 xmlFreeNs((xmlNsPtr) cur);
405 return;
406 }
407 if (cur->type == XML_ATTRIBUTE_NODE) {
408 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
409 return;
410 }
411
412 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000413 (cur->type != XML_ENTITY_REF_NODE)) {
414 if (cur->children->parent == cur)
415 xmlTextReaderFreeNodeList(reader, cur->children);
416 cur->children = NULL;
417 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000418
419 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
420 xmlDeregisterNodeDefaultValue(cur);
421
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000422 if (((cur->type == XML_ELEMENT_NODE) ||
423 (cur->type == XML_XINCLUDE_START) ||
424 (cur->type == XML_XINCLUDE_END)) &&
425 (cur->properties != NULL))
426 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000427 if ((cur->content != (xmlChar *) &(cur->properties)) &&
428 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000429 (cur->type != XML_XINCLUDE_START) &&
430 (cur->type != XML_XINCLUDE_END) &&
431 (cur->type != XML_ENTITY_REF_NODE)) {
432 DICT_FREE(cur->content);
433 }
434 if (((cur->type == XML_ELEMENT_NODE) ||
435 (cur->type == XML_XINCLUDE_START) ||
436 (cur->type == XML_XINCLUDE_END)) &&
437 (cur->nsDef != NULL))
438 xmlFreeNsList(cur->nsDef);
439
440 /*
441 * we don't free names here they are interned now
442 */
443 if ((cur->type != XML_TEXT_NODE) &&
444 (cur->type != XML_COMMENT_NODE))
445 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000446
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000447 if (((cur->type == XML_ELEMENT_NODE) ||
448 (cur->type == XML_TEXT_NODE)) &&
449 (reader != NULL) && (reader->ctxt != NULL) &&
450 (reader->ctxt->freeElemsNr < 100)) {
451 cur->next = reader->ctxt->freeElems;
452 reader->ctxt->freeElems = cur;
453 reader->ctxt->freeElemsNr++;
454 } else {
455 xmlFree(cur);
456 }
457}
458
459/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000460 * xmlTextReaderFreeIDTable:
461 * @table: An id table
462 *
463 * Deallocate the memory used by an ID hash table.
464 */
William M. Brack60f394e2003-11-16 06:25:42 +0000465static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000466xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
467 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
468}
469
470/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000471 * xmlTextReaderFreeDoc:
472 * @reader: the xmlTextReaderPtr used
473 * @cur: pointer to the document
474 *
475 * Free up all the structures used by a document, tree included.
476 */
477static void
478xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
479 xmlDtdPtr extSubset, intSubset;
480
481 if (cur == NULL) return;
482
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000483 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
484 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
485
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000486 /*
487 * Do this before freeing the children list to avoid ID lookups
488 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000489 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000490 cur->ids = NULL;
491 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
492 cur->refs = NULL;
493 extSubset = cur->extSubset;
494 intSubset = cur->intSubset;
495 if (intSubset == extSubset)
496 extSubset = NULL;
497 if (extSubset != NULL) {
498 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
499 cur->extSubset = NULL;
500 xmlFreeDtd(extSubset);
501 }
502 if (intSubset != NULL) {
503 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
504 cur->intSubset = NULL;
505 xmlFreeDtd(intSubset);
506 }
507
508 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
509
510 if (cur->version != NULL) xmlFree((char *) cur->version);
511 if (cur->name != NULL) xmlFree((char *) cur->name);
512 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
513 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
514 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000515 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000516
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000517 xmlFree(cur);
518}
519
520/************************************************************************
521 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000522 * The reader core parser *
523 * *
524 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000525#ifdef DEBUG_READER
526static void
527xmlTextReaderDebug(xmlTextReaderPtr reader) {
528 if ((reader == NULL) || (reader->ctxt == NULL)) {
529 fprintf(stderr, "xmlTextReader NULL\n");
530 return;
531 }
532 fprintf(stderr, "xmlTextReader: state %d depth %d ",
533 reader->state, reader->depth);
534 if (reader->node == NULL) {
535 fprintf(stderr, "node = NULL\n");
536 } else {
537 fprintf(stderr, "node %s\n", reader->node->name);
538 }
539 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
540 reader->base, reader->cur, reader->ctxt->nodeNr);
541 if (reader->input->buffer == NULL) {
542 fprintf(stderr, "buffer is NULL\n");
543 } else {
544#ifdef LIBXML_DEBUG_ENABLED
545 xmlDebugDumpString(stderr,
546 &reader->input->buffer->content[reader->cur]);
547#endif
548 fprintf(stderr, "\n");
549 }
550}
551#endif
552
553/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000554 * xmlTextReaderEntPush:
555 * @reader: the xmlTextReaderPtr used
556 * @value: the entity reference node
557 *
558 * Pushes a new entity reference node on top of the entities stack
559 *
560 * Returns 0 in case of error, the index in the stack otherwise
561 */
562static int
563xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
564{
565 if (reader->entMax <= 0) {
566 reader->entMax = 10;
567 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
568 sizeof(reader->entTab[0]));
569 if (reader->entTab == NULL) {
570 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
571 return (0);
572 }
573 }
574 if (reader->entNr >= reader->entMax) {
575 reader->entMax *= 2;
576 reader->entTab =
577 (xmlNodePtr *) xmlRealloc(reader->entTab,
578 reader->entMax *
579 sizeof(reader->entTab[0]));
580 if (reader->entTab == NULL) {
581 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
582 return (0);
583 }
584 }
585 reader->entTab[reader->entNr] = value;
586 reader->ent = value;
587 return (reader->entNr++);
588}
589
590/**
591 * xmlTextReaderEntPop:
592 * @reader: the xmlTextReaderPtr used
593 *
594 * Pops the top element entity from the entities stack
595 *
596 * Returns the entity just removed
597 */
598static xmlNodePtr
599xmlTextReaderEntPop(xmlTextReaderPtr reader)
600{
601 xmlNodePtr ret;
602
603 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000604 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000605 reader->entNr--;
606 if (reader->entNr > 0)
607 reader->ent = reader->entTab[reader->entNr - 1];
608 else
609 reader->ent = NULL;
610 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000611 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000612 return (ret);
613}
614
615/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000616 * xmlTextReaderStartElement:
617 * @ctx: the user data (XML parser context)
618 * @fullname: The element name, including namespace prefix
619 * @atts: An array of name/value attributes pairs, NULL terminated
620 *
621 * called when an opening tag has been processed.
622 */
623static void
624xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
625 const xmlChar **atts) {
626 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
627 xmlTextReaderPtr reader = ctxt->_private;
628
629#ifdef DEBUG_CALLBACKS
630 printf("xmlTextReaderStartElement(%s)\n", fullname);
631#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000632 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000633 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000634 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
635 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
636 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000637 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000638 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000639 if (reader != NULL)
640 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000641}
642
643/**
644 * xmlTextReaderEndElement:
645 * @ctx: the user data (XML parser context)
646 * @fullname: The element name, including namespace prefix
647 *
648 * called when an ending tag has been processed.
649 */
650static void
651xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
652 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
653 xmlTextReaderPtr reader = ctxt->_private;
654
655#ifdef DEBUG_CALLBACKS
656 printf("xmlTextReaderEndElement(%s)\n", fullname);
657#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000659 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000660 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000661}
662
663/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000664 * xmlTextReaderStartElementNs:
665 * @ctx: the user data (XML parser context)
666 * @localname: the local name of the element
667 * @prefix: the element namespace prefix if available
668 * @URI: the element namespace name if available
669 * @nb_namespaces: number of namespace definitions on that node
670 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
671 * @nb_attributes: the number of attributes on that node
672 * nb_defaulted: the number of defaulted attributes.
673 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
674 * attribute values.
675 *
676 * called when an opening tag has been processed.
677 */
678static void
679xmlTextReaderStartElementNs(void *ctx,
680 const xmlChar *localname,
681 const xmlChar *prefix,
682 const xmlChar *URI,
683 int nb_namespaces,
684 const xmlChar **namespaces,
685 int nb_attributes,
686 int nb_defaulted,
687 const xmlChar **attributes)
688{
689 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
690 xmlTextReaderPtr reader = ctxt->_private;
691
692#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000693 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000694#endif
695 if ((reader != NULL) && (reader->startElementNs != NULL)) {
696 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
697 namespaces, nb_attributes, nb_defaulted,
698 attributes);
699 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
700 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
701 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000702 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000703 }
704 if (reader != NULL)
705 reader->state = XML_TEXTREADER_ELEMENT;
706}
707
708/**
709 * xmlTextReaderEndElementNs:
710 * @ctx: the user data (XML parser context)
711 * @localname: the local name of the element
712 * @prefix: the element namespace prefix if available
713 * @URI: the element namespace name if available
714 *
715 * called when an ending tag has been processed.
716 */
717static void
718xmlTextReaderEndElementNs(void *ctx,
719 const xmlChar * localname,
720 const xmlChar * prefix,
721 const xmlChar * URI)
722{
723 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
724 xmlTextReaderPtr reader = ctxt->_private;
725
726#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000727 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000728#endif
729 if ((reader != NULL) && (reader->endElementNs != NULL)) {
730 reader->endElementNs(ctx, localname, prefix, URI);
731 }
732}
733
734
735/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000736 * xmlTextReaderCharacters:
737 * @ctx: the user data (XML parser context)
738 * @ch: a xmlChar string
739 * @len: the number of xmlChar
740 *
741 * receiving some chars from the parser.
742 */
743static void
744xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
745{
746 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
747 xmlTextReaderPtr reader = ctxt->_private;
748
749#ifdef DEBUG_CALLBACKS
750 printf("xmlTextReaderCharacters()\n");
751#endif
752 if ((reader != NULL) && (reader->characters != NULL)) {
753 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000754 }
755}
756
757/**
758 * xmlTextReaderCDataBlock:
759 * @ctx: the user data (XML parser context)
760 * @value: The pcdata content
761 * @len: the block length
762 *
763 * called when a pcdata block has been parsed
764 */
765static void
766xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
767{
768 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
769 xmlTextReaderPtr reader = ctxt->_private;
770
771#ifdef DEBUG_CALLBACKS
772 printf("xmlTextReaderCDataBlock()\n");
773#endif
774 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
775 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000776 }
777}
778
779/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000780 * xmlTextReaderPushData:
781 * @reader: the xmlTextReaderPtr used
782 *
783 * Push data down the progressive parser until a significant callback
784 * got raised.
785 *
786 * Returns -1 in case of failure, 0 otherwise
787 */
788static int
789xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000790 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000791 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000792 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000793
794 if ((reader->input == NULL) || (reader->input->buffer == NULL))
795 return(-1);
796
Daniel Veillardea7751d2002-12-20 00:16:24 +0000797 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 reader->state = XML_TEXTREADER_NONE;
799 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000800
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000801 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000802 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000803 /*
804 * Refill the buffer unless we are at the end of the stream
805 */
806 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
807 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000808 if ((val == 0) &&
809 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
810 if (inbuf->use == reader->cur) {
811 reader->mode = XML_TEXTREADER_MODE_EOF;
812 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000813 }
814 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000815 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000816 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000817 if ((oldstate != XML_TEXTREADER_START) ||
818 (reader->ctxt->myDoc != NULL))
819 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000820 } else if (val == 0) {
821 /* mark the end of the stream and process the remains */
822 reader->mode = XML_TEXTREADER_MODE_EOF;
823 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000824 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000825
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000826 } else
827 break;
828 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000829 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 * parse by block of CHUNK_SIZE bytes, various tests show that
831 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000832 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000833 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000834 val = xmlParseChunk(reader->ctxt,
835 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000836 CHUNK_SIZE, 0);
837 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000838 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000840 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000841 s = inbuf->use - reader->cur;
842 val = xmlParseChunk(reader->ctxt,
843 (const char *) &inbuf->content[reader->cur],
844 s, 0);
845 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000846 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000847 return(-1);
848 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000849 }
850 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000851
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000852 /*
853 * Discard the consumed input when needed and possible
854 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000855 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000856 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
857 if ((reader->cur >= 4096) &&
858 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
859 val = xmlBufferShrink(inbuf, reader->cur);
860 if (val >= 0) {
861 reader->cur -= val;
862 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000863 }
864 }
865 }
866
867 /*
868 * At the end of the stream signal that the work is done to the Push
869 * parser.
870 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000871 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000872 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000873 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000874 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000875 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000876 s, 1);
877 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000878 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000879 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000880 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000881 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000882 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000883 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000884 return(0);
885}
886
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000887#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000888/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000889 * xmlTextReaderValidatePush:
890 * @reader: the xmlTextReaderPtr used
891 *
892 * Push the current node for validation
893 */
894static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000895xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000896 xmlNodePtr node = reader->node;
897
Daniel Veillardf54cd532004-02-25 11:52:31 +0000898#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000899 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
900 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
901 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
902 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
903 reader->ctxt->myDoc, node, node->name);
904 } else {
905 /* TODO use the BuildQName interface */
906 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000907
Daniel Veillardf4e55762003-04-15 23:32:22 +0000908 qname = xmlStrdup(node->ns->prefix);
909 qname = xmlStrcat(qname, BAD_CAST ":");
910 qname = xmlStrcat(qname, node->name);
911 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
912 reader->ctxt->myDoc, node, qname);
913 if (qname != NULL)
914 xmlFree(qname);
915 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000916 }
917#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000918#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000919 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000920 (reader->rngValidCtxt != NULL)) {
921 int ret;
922
923 if (reader->rngFullNode != NULL) return;
924 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
925 reader->ctxt->myDoc,
926 node);
927 if (ret == 0) {
928 /*
929 * this element requires a full tree
930 */
931 node = xmlTextReaderExpand(reader);
932 if (node == NULL) {
933printf("Expand failed !\n");
934 ret = -1;
935 } else {
936 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
937 reader->ctxt->myDoc,
938 node);
939 reader->rngFullNode = node;
940 }
941 }
942 if (ret != 1)
943 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000944 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000945#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000946}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000947
948/**
949 * xmlTextReaderValidateCData:
950 * @reader: the xmlTextReaderPtr used
951 * @data: pointer to the CData
952 * @len: lenght of the CData block in bytes.
953 *
954 * Push some CData for validation
955 */
956static void
957xmlTextReaderValidateCData(xmlTextReaderPtr reader,
958 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000959#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000960 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
961 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
962 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
963 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000964 }
965#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000966#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000967 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000968 (reader->rngValidCtxt != NULL)) {
969 int ret;
970
971 if (reader->rngFullNode != NULL) return;
972 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
973 if (ret != 1)
974 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000975 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000976#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000977}
978
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000979/**
980 * xmlTextReaderValidatePop:
981 * @reader: the xmlTextReaderPtr used
982 *
983 * Pop the current node from validation
984 */
985static void
986xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
987 xmlNodePtr node = reader->node;
988
Daniel Veillardf54cd532004-02-25 11:52:31 +0000989#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000990 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
991 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
992 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
993 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
994 reader->ctxt->myDoc, node, node->name);
995 } else {
996 /* TODO use the BuildQName interface */
997 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000998
Daniel Veillardf4e55762003-04-15 23:32:22 +0000999 qname = xmlStrdup(node->ns->prefix);
1000 qname = xmlStrcat(qname, BAD_CAST ":");
1001 qname = xmlStrcat(qname, node->name);
1002 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1003 reader->ctxt->myDoc, node, qname);
1004 if (qname != NULL)
1005 xmlFree(qname);
1006 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007 }
1008#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001009#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001010 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001011 (reader->rngValidCtxt != NULL)) {
1012 int ret;
1013
1014 if (reader->rngFullNode != NULL) {
1015 if (node == reader->rngFullNode)
1016 reader->rngFullNode = NULL;
1017 return;
1018 }
1019 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1020 reader->ctxt->myDoc,
1021 node);
1022 if (ret != 1)
1023 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001024 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001025#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001026}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001027
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001028/**
1029 * xmlTextReaderValidateEntity:
1030 * @reader: the xmlTextReaderPtr used
1031 *
1032 * Handle the validation when an entity reference is encountered and
1033 * entity substitution is not activated. As a result the parser interface
1034 * must walk through the entity and do the validation calls
1035 */
1036static void
1037xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1038 xmlNodePtr oldnode = reader->node;
1039 xmlNodePtr node = reader->node;
1040 xmlParserCtxtPtr ctxt = reader->ctxt;
1041
1042 do {
1043 if (node->type == XML_ENTITY_REF_NODE) {
1044 /*
1045 * Case where the underlying tree is not availble, lookup the entity
1046 * and walk it.
1047 */
1048 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1049 (ctxt->sax->getEntity != NULL)) {
1050 node->children = (xmlNodePtr)
1051 ctxt->sax->getEntity(ctxt, node->name);
1052 }
1053
1054 if ((node->children != NULL) &&
1055 (node->children->type == XML_ENTITY_DECL) &&
1056 (node->children->children != NULL)) {
1057 xmlTextReaderEntPush(reader, node);
1058 node = node->children->children;
1059 continue;
1060 } else {
1061 /*
1062 * The error has probably be raised already.
1063 */
1064 if (node == oldnode)
1065 break;
1066 node = node->next;
1067 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001068#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001069 } else if (node->type == XML_ELEMENT_NODE) {
1070 reader->node = node;
1071 xmlTextReaderValidatePush(reader);
1072 } else if ((node->type == XML_TEXT_NODE) ||
1073 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001074 xmlTextReaderValidateCData(reader, node->content,
1075 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001076#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001077 }
1078
1079 /*
1080 * go to next node
1081 */
1082 if (node->children != NULL) {
1083 node = node->children;
1084 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001085 } else if (node->type == XML_ELEMENT_NODE) {
1086 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001087 }
1088 if (node->next != NULL) {
1089 node = node->next;
1090 continue;
1091 }
1092 do {
1093 node = node->parent;
1094 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001095 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 if (reader->entNr == 0) {
1097 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001098 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001099 xmlUnlinkNode(tmp);
1100 xmlTextReaderFreeNode(reader, tmp);
1101 } else
1102 break;
1103 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001104 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001105 reader->node = node;
1106 xmlTextReaderValidatePop(reader);
1107 }
1108 if ((node->type == XML_ENTITY_DECL) &&
1109 (reader->ent != NULL) && (reader->ent->children == node)) {
1110 node = xmlTextReaderEntPop(reader);
1111 }
1112 if (node == oldnode)
1113 break;
1114 if (node->next != NULL) {
1115 node = node->next;
1116 break;
1117 }
1118 } while ((node != NULL) && (node != oldnode));
1119 } while ((node != NULL) && (node != oldnode));
1120 reader->node = oldnode;
1121}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001122#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001123
1124
1125/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001126 * xmlTextReaderGetSuccessor:
1127 * @cur: the current node
1128 *
1129 * Get the successor of a node if available.
1130 *
1131 * Returns the successor node or NULL
1132 */
1133static xmlNodePtr
1134xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1135 if (cur == NULL) return(NULL) ; /* ERROR */
1136 if (cur->next != NULL) return(cur->next) ;
1137 do {
1138 cur = cur->parent;
1139 if (cur == NULL) return(NULL);
1140 if (cur->next != NULL) return(cur->next);
1141 } while (cur != NULL);
1142 return(cur);
1143}
1144
1145/**
1146 * xmlTextReaderDoExpand:
1147 * @reader: the xmlTextReaderPtr used
1148 *
1149 * Makes sure that the current node is fully read as well as all its
1150 * descendant. It means the full DOM subtree must be available at the
1151 * end of the call.
1152 *
1153 * Returns 1 if the node was expanded successfully, 0 if there is no more
1154 * nodes to read, or -1 in case of error
1155 */
1156static int
1157xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1158 int val;
1159
1160 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1161 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001162 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001163 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1164
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001165 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1166 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001167 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001168 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001169 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1170 return(1);
1171 val = xmlTextReaderPushData(reader);
1172 if (val < 0)
1173 return(-1);
1174 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1175 return(1);
1176}
1177
1178/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001179 * xmlTextReaderCollectSiblings:
1180 * @node: the first child
1181 *
1182 * Traverse depth-first through all sibling nodes and their children
1183 * nodes and concatenate their content. This is an auxiliary function
1184 * to xmlTextReaderReadString.
1185 *
1186 * Returns a string containing the content, or NULL in case of error.
1187 */
1188static xmlChar *
1189xmlTextReaderCollectSiblings(xmlNodePtr node)
1190{
1191 xmlBufferPtr buffer;
1192 xmlChar *ret;
1193
1194 buffer = xmlBufferCreate();
1195 if (buffer == NULL)
1196 return NULL;
1197
1198 for ( ; node != NULL; node = node->next) {
1199 switch (node->type) {
1200 case XML_TEXT_NODE:
1201 case XML_CDATA_SECTION_NODE:
1202 xmlBufferCat(buffer, node->content);
1203 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001204 case XML_ELEMENT_NODE: {
1205 xmlChar *tmp;
1206
1207 tmp = xmlTextReaderCollectSiblings(node->children);
1208 xmlBufferCat(buffer, tmp);
1209 xmlFree(tmp);
1210 break;
1211 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001212 default:
1213 break;
1214 }
1215 }
1216 ret = buffer->content;
1217 buffer->content = NULL;
1218 xmlBufferFree(buffer);
1219 return(ret);
1220}
1221
1222/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001223 * xmlTextReaderRead:
1224 * @reader: the xmlTextReaderPtr used
1225 *
1226 * Moves the position of the current instance to the next node in
1227 * the stream, exposing its properties.
1228 *
1229 * Returns 1 if the node was read successfully, 0 if there is no more
1230 * nodes to read, or -1 in case of error
1231 */
1232int
1233xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001234 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001235 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001236 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001237
William M. Brack1af55582004-07-22 17:18:00 +00001238
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001239 if (reader == NULL)
1240 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001241 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001242 if (reader->doc != NULL)
1243 return(xmlTextReaderReadTree(reader));
1244 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001245 return(-1);
1246 if (reader->ctxt->wellFormed != 1)
1247 return(-1);
1248
1249#ifdef DEBUG_READER
1250 fprintf(stderr, "\nREAD ");
1251 DUMP_READER
1252#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001253 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1254 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001255 /*
1256 * Initial state
1257 */
1258 do {
1259 val = xmlTextReaderPushData(reader);
1260 if (val < 0)
1261 return(-1);
1262 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001263 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1264 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001265 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001266 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001267 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001268 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001269 if (reader->node == NULL)
1270 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001271 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001273 if (reader->ctxt->myDoc != NULL) {
1274 reader->node = reader->ctxt->myDoc->children;
1275 }
1276 if (reader->node == NULL)
1277 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001278 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001279 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001280 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001281 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001282 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001283 }
1284 oldstate = reader->state;
1285 olddepth = reader->ctxt->nodeNr;
1286 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001287
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001289 if (reader->node == NULL) {
1290 if (reader->mode == XML_TEXTREADER_DONE)
1291 return(0);
1292 else
1293 return(-1);
1294 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001295
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001296 /*
1297 * If we are not backtracking on ancestors or examined nodes,
1298 * that the parser didn't finished or that we arent at the end
1299 * of stream, continue processing.
1300 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001301 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001302 (reader->ctxt->nodeNr == olddepth) &&
1303 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001304 (reader->node->children == NULL) ||
1305 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001306 ((reader->node->children != NULL) &&
1307 (reader->node->children->type == XML_TEXT_NODE) &&
1308 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001309 (reader->node->type == XML_DTD_NODE) ||
1310 (reader->node->type == XML_DOCUMENT_NODE) ||
1311 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001312 ((reader->ctxt->node == NULL) ||
1313 (reader->ctxt->node == reader->node) ||
1314 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001315 (reader->ctxt->instate != XML_PARSER_EOF)) {
1316 val = xmlTextReaderPushData(reader);
1317 if (val < 0)
1318 return(-1);
1319 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001320 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001321 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001323 if ((reader->node->children != NULL) &&
1324 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001325 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001326 (reader->node->type != XML_DTD_NODE)) {
1327 reader->node = reader->node->children;
1328 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001329 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001330 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 }
1332 }
1333 if (reader->node->next != NULL) {
1334 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001335 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001336 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001337 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1338#ifdef LIBXML_XINCLUDE_ENABLED
1339 && (reader->in_xinclude <= 0)
1340#endif
1341 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001342 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001343 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001345#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001346 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001347 (reader->node->type == XML_ELEMENT_NODE))
1348 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001349#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001350 if ((reader->preserves > 0) &&
1351 (reader->node->extra & NODE_IS_SPRESERVED))
1352 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001353 reader->node = reader->node->next;
1354 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001355
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001356 /*
1357 * Cleanup of the old node
1358 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001359 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001360#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001361 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001362#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001363 (reader->entNr == 0) &&
1364 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001365 (reader->node->prev->type != XML_DTD_NODE) &&
1366 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001367 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001368 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001369 xmlUnlinkNode(tmp);
1370 xmlTextReaderFreeNode(reader, tmp);
1371 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001372 }
1373
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001374 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001375 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001376 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001377 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001378 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001379 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001380 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001381 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001382 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001383#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001384 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001385 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001386#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001387 if ((reader->preserves > 0) &&
1388 (reader->node->extra & NODE_IS_SPRESERVED))
1389 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001390 reader->node = reader->node->parent;
1391 if ((reader->node == NULL) ||
1392 (reader->node->type == XML_DOCUMENT_NODE) ||
1393#ifdef LIBXML_DOCB_ENABLED
1394 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1395#endif
1396 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001397 if (reader->mode != XML_TEXTREADER_DONE) {
1398 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1399 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001400 if (val != 0)
1401 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001402 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001403 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001404 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001405
1406 /*
1407 * Cleanup of the old node
1408 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001409 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001410#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001411 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001412#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001413 (reader->entNr == 0) &&
1414 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001415 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001416 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001417 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001418 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001419 }
1420
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001421 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001422 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001423 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001424#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001425 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001426#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001427 (reader->entNr == 0) &&
1428 (reader->node->last != NULL) &&
1429 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1430 xmlNodePtr tmp = reader->node->last;
1431 xmlUnlinkNode(tmp);
1432 xmlTextReaderFreeNode(reader, tmp);
1433 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001434 reader->depth--;
1435 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001436
1437node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001438 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001439
1440 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001441 * If we are in the middle of a piece of CDATA make sure it's finished
1442 */
1443 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001444 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001445 ((reader->node->type == XML_TEXT_NODE) ||
1446 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001447 if (xmlTextReaderExpand(reader) == NULL)
1448 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001449 }
1450
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001451#ifdef LIBXML_XINCLUDE_ENABLED
1452 /*
1453 * Handle XInclude if asked for
1454 */
1455 if ((reader->xinclude) && (reader->node != NULL) &&
1456 (reader->node->type == XML_ELEMENT_NODE) &&
1457 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001458 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1459 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001460 if (reader->xincctxt == NULL) {
1461 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001462 xmlXIncludeSetFlags(reader->xincctxt,
1463 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001464 }
1465 /*
1466 * expand that node and process it
1467 */
William M. Brack42331a92004-07-29 07:07:16 +00001468 if (xmlTextReaderExpand(reader) == NULL)
1469 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001470 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1471 }
1472 if (reader->node->type == XML_XINCLUDE_START) {
1473 reader->in_xinclude++;
1474 goto get_next_node;
1475 }
1476 if (reader->node->type == XML_XINCLUDE_END) {
1477 reader->in_xinclude--;
1478 goto get_next_node;
1479 }
1480#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001481 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001482 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001483 */
1484 if ((reader->node != NULL) &&
1485 (reader->node->type == XML_ENTITY_REF_NODE) &&
1486 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1487 /*
1488 * Case where the underlying tree is not availble, lookup the entity
1489 * and walk it.
1490 */
1491 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1492 (reader->ctxt->sax->getEntity != NULL)) {
1493 reader->node->children = (xmlNodePtr)
1494 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1495 }
1496
1497 if ((reader->node->children != NULL) &&
1498 (reader->node->children->type == XML_ENTITY_DECL) &&
1499 (reader->node->children->children != NULL)) {
1500 xmlTextReaderEntPush(reader, reader->node);
1501 reader->node = reader->node->children->children;
1502 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001503#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001504 } else if ((reader->node != NULL) &&
1505 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001506 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001507 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001508#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001509 }
1510 if ((reader->node != NULL) &&
1511 (reader->node->type == XML_ENTITY_DECL) &&
1512 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1513 reader->node = xmlTextReaderEntPop(reader);
1514 reader->depth++;
1515 goto get_next_node;
1516 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001517#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001518 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001519 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001520
1521 if ((node->type == XML_ELEMENT_NODE) &&
1522 ((reader->state != XML_TEXTREADER_END) &&
1523 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1524 xmlTextReaderValidatePush(reader);
1525 } else if ((node->type == XML_TEXT_NODE) ||
1526 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001527 xmlTextReaderValidateCData(reader, node->content,
1528 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001529 }
1530 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001531#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001532#ifdef LIBXML_PATTERN_ENABLED
1533 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1534 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1535 int i;
1536 for (i = 0;i < reader->patternNr;i++) {
1537 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1538 xmlTextReaderPreserve(reader);
1539 break;
1540 }
1541 }
1542 }
1543#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001544#ifdef LIBXML_SCHEMAS_ENABLED
1545 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1546 (reader->xsdValidErrors == 0) &&
1547 (reader->xsdValidCtxt != NULL)) {
1548 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1549 }
1550#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001551 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001552node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001553 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001554 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001555}
1556
Daniel Veillard67df8092002-12-16 22:04:11 +00001557/**
1558 * xmlTextReaderReadState:
1559 * @reader: the xmlTextReaderPtr used
1560 *
1561 * Gets the read state of the reader.
1562 *
1563 * Returns the state value, or -1 in case of error
1564 */
1565int
1566xmlTextReaderReadState(xmlTextReaderPtr reader) {
1567 if (reader == NULL)
1568 return(-1);
1569 return(reader->mode);
1570}
1571
1572/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001573 * xmlTextReaderExpand:
1574 * @reader: the xmlTextReaderPtr used
1575 *
1576 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001577 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001578 *
1579 * Returns a node pointer valid until the next xmlTextReaderRead() call
1580 * or NULL in case of error.
1581 */
1582xmlNodePtr
1583xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001584 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001585 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001586 if (reader->doc != NULL)
1587 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001588 if (reader->ctxt == NULL)
1589 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001590 if (xmlTextReaderDoExpand(reader) < 0)
1591 return(NULL);
1592 return(reader->node);
1593}
1594
1595/**
1596 * xmlTextReaderNext:
1597 * @reader: the xmlTextReaderPtr used
1598 *
1599 * Skip to the node following the current one in document order while
1600 * avoiding the subtree if any.
1601 *
1602 * Returns 1 if the node was read successfully, 0 if there is no more
1603 * nodes to read, or -1 in case of error
1604 */
1605int
1606xmlTextReaderNext(xmlTextReaderPtr reader) {
1607 int ret;
1608 xmlNodePtr cur;
1609
1610 if (reader == NULL)
1611 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001612 if (reader->doc != NULL)
1613 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001614 cur = reader->node;
1615 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1616 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001617 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001618 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001619 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001620 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001621 do {
1622 ret = xmlTextReaderRead(reader);
1623 if (ret != 1)
1624 return(ret);
1625 } while (reader->node != cur);
1626 return(xmlTextReaderRead(reader));
1627}
1628
1629/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001630 * xmlTextReaderReadInnerXml:
1631 * @reader: the xmlTextReaderPtr used
1632 *
1633 * Reads the contents of the current node, including child nodes and markup.
1634 *
1635 * Returns a string containing the XML content, or NULL if the current node
1636 * is neither an element nor attribute, or has no child nodes. The
1637 * string must be deallocated by the caller.
1638 */
1639xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001640xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1641{
1642 xmlChar *resbuf;
1643 xmlNodePtr node, cur_node;
1644 xmlBufferPtr buff, buff2;
1645 xmlDocPtr doc;
1646
1647 if (xmlTextReaderExpand(reader) == NULL) {
1648 return NULL;
1649 }
1650 doc = reader->doc;
1651 buff = xmlBufferCreate();
1652 for (cur_node = reader->node->children; cur_node != NULL;
1653 cur_node = cur_node->next) {
1654 node = xmlDocCopyNode(cur_node, doc, 1);
1655 buff2 = xmlBufferCreate();
1656 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1657 xmlFreeNode(node);
1658 xmlBufferFree(buff2);
1659 xmlBufferFree(buff);
1660 return NULL;
1661 }
1662 xmlBufferCat(buff, buff2->content);
1663 xmlFreeNode(node);
1664 xmlBufferFree(buff2);
1665 }
1666 resbuf = buff->content;
1667 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001668}
1669
1670/**
1671 * xmlTextReaderReadOuterXml:
1672 * @reader: the xmlTextReaderPtr used
1673 *
1674 * Reads the contents of the current node, including child nodes and markup.
1675 *
1676 * Returns a string containing the XML content, or NULL if the current node
1677 * is neither an element nor attribute, or has no child nodes. The
1678 * string must be deallocated by the caller.
1679 */
1680xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001681xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1682{
1683 xmlChar *resbuf;
1684 xmlNodePtr node;
1685 xmlBufferPtr buff;
1686 xmlDocPtr doc;
1687
1688 node = reader->node;
1689 doc = reader->doc;
1690 if (xmlTextReaderExpand(reader) == NULL) {
1691 return NULL;
1692 }
1693 node = xmlDocCopyNode(node, doc, 1);
1694 buff = xmlBufferCreate();
1695 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1696 xmlFreeNode(node);
1697 xmlBufferFree(buff);
1698 return NULL;
1699 }
1700
1701 resbuf = buff->content;
1702 buff->content = NULL;
1703
1704 xmlFreeNode(node);
1705 xmlBufferFree(buff);
1706 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001707}
1708
1709/**
1710 * xmlTextReaderReadString:
1711 * @reader: the xmlTextReaderPtr used
1712 *
1713 * Reads the contents of an element or a text node as a string.
1714 *
1715 * Returns a string containing the contents of the Element or Text node,
1716 * or NULL if the reader is positioned on any other type of node.
1717 * The string must be deallocated by the caller.
1718 */
1719xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001720xmlTextReaderReadString(xmlTextReaderPtr reader)
1721{
1722 xmlNodePtr node;
1723
1724 if ((reader == NULL) || (reader->node == NULL))
1725 return(NULL);
1726
1727 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1728 switch (node->type) {
1729 case XML_TEXT_NODE:
1730 if (node->content != NULL)
1731 return(xmlStrdup(node->content));
1732 break;
1733 case XML_ELEMENT_NODE:
1734 if (xmlTextReaderDoExpand(reader) != -1) {
1735 return xmlTextReaderCollectSiblings(node->children);
1736 }
1737 case XML_ATTRIBUTE_NODE:
1738 TODO
1739 break;
1740 default:
1741 break;
1742 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001743 return(NULL);
1744}
1745
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001746#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001747/**
1748 * xmlTextReaderReadBase64:
1749 * @reader: the xmlTextReaderPtr used
1750 * @array: a byte array to store the content.
1751 * @offset: the zero-based index into array where the method should
1752 * begin to write.
1753 * @len: the number of bytes to write.
1754 *
1755 * Reads and decodes the Base64 encoded contents of an element and
1756 * stores the result in a byte buffer.
1757 *
1758 * Returns the number of bytes written to array, or zero if the current
1759 * instance is not positioned on an element or -1 in case of error.
1760 */
1761int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001762xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1763 unsigned char *array ATTRIBUTE_UNUSED,
1764 int offset ATTRIBUTE_UNUSED,
1765 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001766 if ((reader == NULL) || (reader->ctxt == NULL))
1767 return(-1);
1768 if (reader->ctxt->wellFormed != 1)
1769 return(-1);
1770
1771 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1772 return(0);
1773 TODO
1774 return(0);
1775}
1776
1777/**
1778 * xmlTextReaderReadBinHex:
1779 * @reader: the xmlTextReaderPtr used
1780 * @array: a byte array to store the content.
1781 * @offset: the zero-based index into array where the method should
1782 * begin to write.
1783 * @len: the number of bytes to write.
1784 *
1785 * Reads and decodes the BinHex encoded contents of an element and
1786 * stores the result in a byte buffer.
1787 *
1788 * Returns the number of bytes written to array, or zero if the current
1789 * instance is not positioned on an element or -1 in case of error.
1790 */
1791int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001792xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1793 unsigned char *array ATTRIBUTE_UNUSED,
1794 int offset ATTRIBUTE_UNUSED,
1795 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001796 if ((reader == NULL) || (reader->ctxt == NULL))
1797 return(-1);
1798 if (reader->ctxt->wellFormed != 1)
1799 return(-1);
1800
1801 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1802 return(0);
1803 TODO
1804 return(0);
1805}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001806#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001807
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001808/************************************************************************
1809 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001810 * Operating on a preparsed tree *
1811 * *
1812 ************************************************************************/
1813static int
1814xmlTextReaderNextTree(xmlTextReaderPtr reader)
1815{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001816 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001817 return(-1);
1818
1819 if (reader->state == XML_TEXTREADER_END)
1820 return(0);
1821
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001822 if (reader->node == NULL) {
1823 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001824 reader->state = XML_TEXTREADER_END;
1825 return(0);
1826 }
1827
1828 reader->node = reader->doc->children;
1829 reader->state = XML_TEXTREADER_START;
1830 return(1);
1831 }
1832
1833 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1834 if (reader->node->children != 0) {
1835 reader->node = reader->node->children;
1836 reader->depth++;
1837 reader->state = XML_TEXTREADER_START;
1838 return(1);
1839 }
1840
1841 if ((reader->node->type == XML_ELEMENT_NODE) ||
1842 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1843 reader->state = XML_TEXTREADER_BACKTRACK;
1844 return(1);
1845 }
1846 }
1847
1848 if (reader->node->next != 0) {
1849 reader->node = reader->node->next;
1850 reader->state = XML_TEXTREADER_START;
1851 return(1);
1852 }
1853
1854 if (reader->node->parent != 0) {
1855 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1856 reader->state = XML_TEXTREADER_END;
1857 return(0);
1858 }
1859
1860 reader->node = reader->node->parent;
1861 reader->depth--;
1862 reader->state = XML_TEXTREADER_BACKTRACK;
1863 return(1);
1864 }
1865
1866 reader->state = XML_TEXTREADER_END;
1867
1868 return(1);
1869}
1870
1871/**
1872 * xmlTextReaderReadTree:
1873 * @reader: the xmlTextReaderPtr used
1874 *
1875 * Moves the position of the current instance to the next node in
1876 * the stream, exposing its properties.
1877 *
1878 * Returns 1 if the node was read successfully, 0 if there is no more
1879 * nodes to read, or -1 in case of error
1880 */
1881static int
1882xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1883 if (reader->state == XML_TEXTREADER_END)
1884 return(0);
1885
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001886next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001887 if (reader->node == NULL) {
1888 if (reader->doc->children == NULL) {
1889 reader->state = XML_TEXTREADER_END;
1890 return(0);
1891 }
1892
1893 reader->node = reader->doc->children;
1894 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001895 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001896 }
1897
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001898 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1899 (reader->node->type != XML_DTD_NODE) &&
1900 (reader->node->type != XML_XINCLUDE_START) &&
1901 (reader->node->type != XML_ENTITY_REF_NODE)) {
1902 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 reader->node = reader->node->children;
1904 reader->depth++;
1905 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001906 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001907 }
1908
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001909 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001911 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001912 }
1913 }
1914
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001915 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001916 reader->node = reader->node->next;
1917 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001918 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001919 }
1920
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001921 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001922 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1923 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1924 reader->state = XML_TEXTREADER_END;
1925 return(0);
1926 }
1927
1928 reader->node = reader->node->parent;
1929 reader->depth--;
1930 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001931 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 }
1933
1934 reader->state = XML_TEXTREADER_END;
1935
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001936found_node:
1937 if ((reader->node->type == XML_XINCLUDE_START) ||
1938 (reader->node->type == XML_XINCLUDE_END))
1939 goto next_node;
1940
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001941 return(1);
1942}
1943
1944/**
William M. Brackb1d53162003-11-18 06:54:40 +00001945 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001946 * @reader: the xmlTextReaderPtr used
1947 *
1948 * Skip to the node following the current one in document order while
1949 * avoiding the subtree if any.
1950 * Currently implemented only for Readers built on a document
1951 *
1952 * Returns 1 if the node was read successfully, 0 if there is no more
1953 * nodes to read, or -1 in case of error
1954 */
1955int
1956xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1957 if (reader == NULL)
1958 return(-1);
1959 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001960 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001961 return(-1);
1962 }
1963
1964 if (reader->state == XML_TEXTREADER_END)
1965 return(0);
1966
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001967 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001968 return(xmlTextReaderNextTree(reader));
1969
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001970 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001971 reader->node = reader->node->next;
1972 reader->state = XML_TEXTREADER_START;
1973 return(1);
1974 }
1975
1976 return(0);
1977}
1978
1979/************************************************************************
1980 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001981 * Constructor and destructors *
1982 * *
1983 ************************************************************************/
1984/**
1985 * xmlNewTextReader:
1986 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001987 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001988 *
1989 * Create an xmlTextReader structure fed with @input
1990 *
1991 * Returns the new xmlTextReaderPtr or NULL in case of error
1992 */
1993xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001994xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001995 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001996
1997 if (input == NULL)
1998 return(NULL);
1999 ret = xmlMalloc(sizeof(xmlTextReader));
2000 if (ret == NULL) {
2001 xmlGenericError(xmlGenericErrorContext,
2002 "xmlNewTextReader : malloc failed\n");
2003 return(NULL);
2004 }
2005 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002006 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002007 ret->entTab = NULL;
2008 ret->entMax = 0;
2009 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002010 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002011 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002012 if (ret->buffer == NULL) {
2013 xmlFree(ret);
2014 xmlGenericError(xmlGenericErrorContext,
2015 "xmlNewTextReader : malloc failed\n");
2016 return(NULL);
2017 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2019 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002020 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002021 xmlFree(ret);
2022 xmlGenericError(xmlGenericErrorContext,
2023 "xmlNewTextReader : malloc failed\n");
2024 return(NULL);
2025 }
Daniel Veillard81273902003-09-30 00:43:48 +00002026 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002027 ret->startElement = ret->sax->startElement;
2028 ret->sax->startElement = xmlTextReaderStartElement;
2029 ret->endElement = ret->sax->endElement;
2030 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002031#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002032 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002033#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002034 ret->startElementNs = ret->sax->startElementNs;
2035 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2036 ret->endElementNs = ret->sax->endElementNs;
2037 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002038#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002039 } else {
2040 ret->startElementNs = NULL;
2041 ret->endElementNs = NULL;
2042 }
Daniel Veillard81273902003-09-30 00:43:48 +00002043#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002044 ret->characters = ret->sax->characters;
2045 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002046 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002047 ret->cdataBlock = ret->sax->cdataBlock;
2048 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002049
Daniel Veillard67df8092002-12-16 22:04:11 +00002050 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002051 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002052 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002053 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002054 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002055 }
2056 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002057 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002058 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002059 ret->base = 0;
2060 ret->cur = 4;
2061 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002062 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002063 ret->base = 0;
2064 ret->cur = 0;
2065 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002066
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002067 if (ret->ctxt == NULL) {
2068 xmlGenericError(xmlGenericErrorContext,
2069 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002070 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002071 xmlFree(ret->sax);
2072 xmlFree(ret);
2073 return(NULL);
2074 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002075 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002076 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002077 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002078 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002079 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002080 /*
2081 * use the parser dictionnary to allocate all elements and attributes names
2082 */
2083 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002084 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002085#ifdef LIBXML_XINCLUDE_ENABLED
2086 ret->xinclude = 0;
2087#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002088#ifdef LIBXML_PATTERN_ENABLED
2089 ret->patternMax = 0;
2090 ret->patternTab = NULL;
2091#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002092 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002093}
2094
2095/**
2096 * xmlNewTextReaderFilename:
2097 * @URI: the URI of the resource to process
2098 *
2099 * Create an xmlTextReader structure fed with the resource at @URI
2100 *
2101 * Returns the new xmlTextReaderPtr or NULL in case of error
2102 */
2103xmlTextReaderPtr
2104xmlNewTextReaderFilename(const char *URI) {
2105 xmlParserInputBufferPtr input;
2106 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002107 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002108
2109 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2110 if (input == NULL)
2111 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002112 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002113 if (ret == NULL) {
2114 xmlFreeParserInputBuffer(input);
2115 return(NULL);
2116 }
2117 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002118 if (ret->ctxt->directory == NULL)
2119 directory = xmlParserGetDirectory(URI);
2120 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2121 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2122 if (directory != NULL)
2123 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002124 return(ret);
2125}
2126
2127/**
2128 * xmlFreeTextReader:
2129 * @reader: the xmlTextReaderPtr
2130 *
2131 * Deallocate all the resources associated to the reader
2132 */
2133void
2134xmlFreeTextReader(xmlTextReaderPtr reader) {
2135 if (reader == NULL)
2136 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002137#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002138 if (reader->rngSchemas != NULL) {
2139 xmlRelaxNGFree(reader->rngSchemas);
2140 reader->rngSchemas = NULL;
2141 }
2142 if (reader->rngValidCtxt != NULL) {
2143 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2144 reader->rngValidCtxt = NULL;
2145 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002146 if (reader->xsdPlug != NULL) {
2147 xmlSchemaSAXUnplug(reader->xsdPlug);
2148 reader->xsdPlug = NULL;
2149 }
2150 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002151 if (! reader->xsdPreserveCtxt)
2152 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002153 reader->xsdValidCtxt = NULL;
2154 }
2155 if (reader->xsdSchemas != NULL) {
2156 xmlSchemaFree(reader->xsdSchemas);
2157 reader->xsdSchemas = NULL;
2158 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002159#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002160#ifdef LIBXML_XINCLUDE_ENABLED
2161 if (reader->xincctxt != NULL)
2162 xmlXIncludeFreeContext(reader->xincctxt);
2163#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002164#ifdef LIBXML_PATTERN_ENABLED
2165 if (reader->patternTab != NULL) {
2166 int i;
2167 for (i = 0;i < reader->patternNr;i++) {
2168 if (reader->patternTab[i] != NULL)
2169 xmlFreePattern(reader->patternTab[i]);
2170 }
2171 xmlFree(reader->patternTab);
2172 }
2173#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002174 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002175 if (reader->dict == reader->ctxt->dict)
2176 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002177 if (reader->ctxt->myDoc != NULL) {
2178 if (reader->preserve == 0)
2179 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2180 reader->ctxt->myDoc = NULL;
2181 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002182 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2183 (reader->ctxt->vctxt.vstateMax > 0)){
2184 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002185 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002186 reader->ctxt->vctxt.vstateMax = 0;
2187 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002188 if (reader->allocs & XML_TEXTREADER_CTXT)
2189 xmlFreeParserCtxt(reader->ctxt);
2190 }
2191 if (reader->sax != NULL)
2192 xmlFree(reader->sax);
2193 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2194 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002195 if (reader->faketext != NULL) {
2196 xmlFreeNode(reader->faketext);
2197 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002198 if (reader->buffer != NULL)
2199 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002200 if (reader->entTab != NULL)
2201 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002202 if (reader->dict != NULL)
2203 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002204 xmlFree(reader);
2205}
2206
2207/************************************************************************
2208 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002209 * Methods for XmlTextReader *
2210 * *
2211 ************************************************************************/
2212/**
2213 * xmlTextReaderClose:
2214 * @reader: the xmlTextReaderPtr used
2215 *
2216 * This method releases any resources allocated by the current instance
2217 * changes the state to Closed and close any underlying input.
2218 *
2219 * Returns 0 or -1 in case of error
2220 */
2221int
2222xmlTextReaderClose(xmlTextReaderPtr reader) {
2223 if (reader == NULL)
2224 return(-1);
2225 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002226 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002227 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2228 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002229 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002230 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002231 if (reader->preserve == 0)
2232 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002233 reader->ctxt->myDoc = NULL;
2234 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002235 }
2236 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2237 xmlFreeParserInputBuffer(reader->input);
2238 reader->allocs -= XML_TEXTREADER_INPUT;
2239 }
2240 return(0);
2241}
2242
2243/**
2244 * xmlTextReaderGetAttributeNo:
2245 * @reader: the xmlTextReaderPtr used
2246 * @no: the zero-based index of the attribute relative to the containing element
2247 *
2248 * Provides the value of the attribute with the specified index relative
2249 * to the containing element.
2250 *
2251 * Returns a string containing the value of the specified attribute, or NULL
2252 * in case of error. The string must be deallocated by the caller.
2253 */
2254xmlChar *
2255xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2256 xmlChar *ret;
2257 int i;
2258 xmlAttrPtr cur;
2259 xmlNsPtr ns;
2260
2261 if (reader == NULL)
2262 return(NULL);
2263 if (reader->node == NULL)
2264 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002265 if (reader->curnode != NULL)
2266 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002267 /* TODO: handle the xmlDecl */
2268 if (reader->node->type != XML_ELEMENT_NODE)
2269 return(NULL);
2270
2271 ns = reader->node->nsDef;
2272 for (i = 0;(i < no) && (ns != NULL);i++) {
2273 ns = ns->next;
2274 }
2275 if (ns != NULL)
2276 return(xmlStrdup(ns->href));
2277
2278 cur = reader->node->properties;
2279 if (cur == NULL)
2280 return(NULL);
2281 for (;i < no;i++) {
2282 cur = cur->next;
2283 if (cur == NULL)
2284 return(NULL);
2285 }
2286 /* TODO walk the DTD if present */
2287
2288 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2289 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2290 return(ret);
2291}
2292
2293/**
2294 * xmlTextReaderGetAttribute:
2295 * @reader: the xmlTextReaderPtr used
2296 * @name: the qualified name of the attribute.
2297 *
2298 * Provides the value of the attribute with the specified qualified name.
2299 *
2300 * Returns a string containing the value of the specified attribute, or NULL
2301 * in case of error. The string must be deallocated by the caller.
2302 */
2303xmlChar *
2304xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2305 xmlChar *prefix = NULL;
2306 xmlChar *localname;
2307 xmlNsPtr ns;
2308 xmlChar *ret = NULL;
2309
2310 if ((reader == NULL) || (name == NULL))
2311 return(NULL);
2312 if (reader->node == NULL)
2313 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002314 if (reader->curnode != NULL)
2315 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002316
2317 /* TODO: handle the xmlDecl */
2318 if (reader->node->type != XML_ELEMENT_NODE)
2319 return(NULL);
2320
2321 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002322 if (localname == NULL) {
2323 /*
2324 * Namespace default decl
2325 */
2326 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2327 ns = reader->node->nsDef;
2328 while (ns != NULL) {
2329 if (ns->prefix == NULL) {
2330 return(xmlStrdup(ns->href));
2331 }
2332 ns = ns->next;
2333 }
2334 return NULL;
2335 }
2336 return(xmlGetNoNsProp(reader->node, name));
2337 }
2338
2339 /*
2340 * Namespace default decl
2341 */
2342 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2343 ns = reader->node->nsDef;
2344 while (ns != NULL) {
2345 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2346 ret = xmlStrdup(ns->href);
2347 break;
2348 }
2349 ns = ns->next;
2350 }
2351 } else {
2352 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2353 if (ns != NULL)
2354 ret = xmlGetNsProp(reader->node, localname, ns->href);
2355 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002356
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002357 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002358 if (prefix != NULL)
2359 xmlFree(prefix);
2360 return(ret);
2361}
2362
2363
2364/**
2365 * xmlTextReaderGetAttributeNs:
2366 * @reader: the xmlTextReaderPtr used
2367 * @localName: the local name of the attribute.
2368 * @namespaceURI: the namespace URI of the attribute.
2369 *
2370 * Provides the value of the specified attribute
2371 *
2372 * Returns a string containing the value of the specified attribute, or NULL
2373 * in case of error. The string must be deallocated by the caller.
2374 */
2375xmlChar *
2376xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2377 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002378 xmlChar *prefix = NULL;
2379 xmlNsPtr ns;
2380
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002381 if ((reader == NULL) || (localName == NULL))
2382 return(NULL);
2383 if (reader->node == NULL)
2384 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002385 if (reader->curnode != NULL)
2386 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002387
2388 /* TODO: handle the xmlDecl */
2389 if (reader->node->type != XML_ELEMENT_NODE)
2390 return(NULL);
2391
Daniel Veillard45b97e72005-08-20 21:14:28 +00002392 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2393 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2394 prefix = BAD_CAST localName;
2395 }
2396 ns = reader->node->nsDef;
2397 while (ns != NULL) {
2398 if ((prefix == NULL && ns->prefix == NULL) ||
2399 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2400 return xmlStrdup(ns->href);
2401 }
2402 ns = ns->next;
2403 }
2404 return NULL;
2405 }
2406
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002407 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2408}
2409
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002410/**
2411 * xmlTextReaderGetRemainder:
2412 * @reader: the xmlTextReaderPtr used
2413 *
2414 * Method to get the remainder of the buffered XML. this method stops the
2415 * parser, set its state to End Of File and return the input stream with
2416 * what is left that the parser did not use.
2417 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002418 * The implementation is not good, the parser certainly procgressed past
2419 * what's left in reader->input, and there is an allocation problem. Best
2420 * would be to rewrite it differently.
2421 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002422 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2423 * in case of error.
2424 */
2425xmlParserInputBufferPtr
2426xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2427 xmlParserInputBufferPtr ret = NULL;
2428
2429 if (reader == NULL)
2430 return(NULL);
2431 if (reader->node == NULL)
2432 return(NULL);
2433
2434 reader->node = NULL;
2435 reader->curnode = NULL;
2436 reader->mode = XML_TEXTREADER_MODE_EOF;
2437 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002438 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002439 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002440 if (reader->preserve == 0)
2441 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002442 reader->ctxt->myDoc = NULL;
2443 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002444 }
2445 if (reader->allocs & XML_TEXTREADER_INPUT) {
2446 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002447 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002448 reader->allocs -= XML_TEXTREADER_INPUT;
2449 } else {
2450 /*
2451 * Hum, one may need to duplicate the data structure because
2452 * without reference counting the input may be freed twice:
2453 * - by the layer which allocated it.
2454 * - by the layer to which would have been returned to.
2455 */
2456 TODO
2457 return(NULL);
2458 }
2459 return(ret);
2460}
2461
2462/**
2463 * xmlTextReaderLookupNamespace:
2464 * @reader: the xmlTextReaderPtr used
2465 * @prefix: the prefix whose namespace URI is to be resolved. To return
2466 * the default namespace, specify NULL
2467 *
2468 * Resolves a namespace prefix in the scope of the current element.
2469 *
2470 * Returns a string containing the namespace URI to which the prefix maps
2471 * or NULL in case of error. The string must be deallocated by the caller.
2472 */
2473xmlChar *
2474xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2475 xmlNsPtr ns;
2476
2477 if (reader == NULL)
2478 return(NULL);
2479 if (reader->node == NULL)
2480 return(NULL);
2481
2482 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2483 if (ns == NULL)
2484 return(NULL);
2485 return(xmlStrdup(ns->href));
2486}
2487
2488/**
2489 * xmlTextReaderMoveToAttributeNo:
2490 * @reader: the xmlTextReaderPtr used
2491 * @no: the zero-based index of the attribute relative to the containing
2492 * element.
2493 *
2494 * Moves the position of the current instance to the attribute with
2495 * the specified index relative to the containing element.
2496 *
2497 * Returns 1 in case of success, -1 in case of error, 0 if not found
2498 */
2499int
2500xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2501 int i;
2502 xmlAttrPtr cur;
2503 xmlNsPtr ns;
2504
2505 if (reader == NULL)
2506 return(-1);
2507 if (reader->node == NULL)
2508 return(-1);
2509 /* TODO: handle the xmlDecl */
2510 if (reader->node->type != XML_ELEMENT_NODE)
2511 return(-1);
2512
2513 reader->curnode = NULL;
2514
2515 ns = reader->node->nsDef;
2516 for (i = 0;(i < no) && (ns != NULL);i++) {
2517 ns = ns->next;
2518 }
2519 if (ns != NULL) {
2520 reader->curnode = (xmlNodePtr) ns;
2521 return(1);
2522 }
2523
2524 cur = reader->node->properties;
2525 if (cur == NULL)
2526 return(0);
2527 for (;i < no;i++) {
2528 cur = cur->next;
2529 if (cur == NULL)
2530 return(0);
2531 }
2532 /* TODO walk the DTD if present */
2533
2534 reader->curnode = (xmlNodePtr) cur;
2535 return(1);
2536}
2537
2538/**
2539 * xmlTextReaderMoveToAttribute:
2540 * @reader: the xmlTextReaderPtr used
2541 * @name: the qualified name of the attribute.
2542 *
2543 * Moves the position of the current instance to the attribute with
2544 * the specified qualified name.
2545 *
2546 * Returns 1 in case of success, -1 in case of error, 0 if not found
2547 */
2548int
2549xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2550 xmlChar *prefix = NULL;
2551 xmlChar *localname;
2552 xmlNsPtr ns;
2553 xmlAttrPtr prop;
2554
2555 if ((reader == NULL) || (name == NULL))
2556 return(-1);
2557 if (reader->node == NULL)
2558 return(-1);
2559
2560 /* TODO: handle the xmlDecl */
2561 if (reader->node->type != XML_ELEMENT_NODE)
2562 return(0);
2563
2564 localname = xmlSplitQName2(name, &prefix);
2565 if (localname == NULL) {
2566 /*
2567 * Namespace default decl
2568 */
2569 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2570 ns = reader->node->nsDef;
2571 while (ns != NULL) {
2572 if (ns->prefix == NULL) {
2573 reader->curnode = (xmlNodePtr) ns;
2574 return(1);
2575 }
2576 ns = ns->next;
2577 }
2578 return(0);
2579 }
2580
2581 prop = reader->node->properties;
2582 while (prop != NULL) {
2583 /*
2584 * One need to have
2585 * - same attribute names
2586 * - and the attribute carrying that namespace
2587 */
2588 if ((xmlStrEqual(prop->name, name)) &&
2589 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2590 reader->curnode = (xmlNodePtr) prop;
2591 return(1);
2592 }
2593 prop = prop->next;
2594 }
2595 return(0);
2596 }
2597
2598 /*
2599 * Namespace default decl
2600 */
2601 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2602 ns = reader->node->nsDef;
2603 while (ns != NULL) {
2604 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2605 reader->curnode = (xmlNodePtr) ns;
2606 goto found;
2607 }
2608 ns = ns->next;
2609 }
2610 goto not_found;
2611 }
2612 prop = reader->node->properties;
2613 while (prop != NULL) {
2614 /*
2615 * One need to have
2616 * - same attribute names
2617 * - and the attribute carrying that namespace
2618 */
2619 if ((xmlStrEqual(prop->name, localname)) &&
2620 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2621 reader->curnode = (xmlNodePtr) prop;
2622 goto found;
2623 }
2624 prop = prop->next;
2625 }
2626not_found:
2627 if (localname != NULL)
2628 xmlFree(localname);
2629 if (prefix != NULL)
2630 xmlFree(prefix);
2631 return(0);
2632
2633found:
2634 if (localname != NULL)
2635 xmlFree(localname);
2636 if (prefix != NULL)
2637 xmlFree(prefix);
2638 return(1);
2639}
2640
2641/**
2642 * xmlTextReaderMoveToAttributeNs:
2643 * @reader: the xmlTextReaderPtr used
2644 * @localName: the local name of the attribute.
2645 * @namespaceURI: the namespace URI of the attribute.
2646 *
2647 * Moves the position of the current instance to the attribute with the
2648 * specified local name and namespace URI.
2649 *
2650 * Returns 1 in case of success, -1 in case of error, 0 if not found
2651 */
2652int
2653xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2654 const xmlChar *localName, const xmlChar *namespaceURI) {
2655 xmlAttrPtr prop;
2656 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002657 xmlNsPtr ns;
2658 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002659
2660 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2661 return(-1);
2662 if (reader->node == NULL)
2663 return(-1);
2664 if (reader->node->type != XML_ELEMENT_NODE)
2665 return(0);
2666 node = reader->node;
2667
Daniel Veillard45b97e72005-08-20 21:14:28 +00002668 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2669 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2670 prefix = BAD_CAST localName;
2671 }
2672 ns = reader->node->nsDef;
2673 while (ns != NULL) {
2674 if ((prefix == NULL && ns->prefix == NULL) ||
2675 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2676 reader->curnode = (xmlNodePtr) ns;
2677 return(1);
2678 }
2679 ns = ns->next;
2680 }
2681 return(0);
2682 }
2683
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002684 prop = node->properties;
2685 while (prop != NULL) {
2686 /*
2687 * One need to have
2688 * - same attribute names
2689 * - and the attribute carrying that namespace
2690 */
2691 if (xmlStrEqual(prop->name, localName) &&
2692 ((prop->ns != NULL) &&
2693 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2694 reader->curnode = (xmlNodePtr) prop;
2695 return(1);
2696 }
2697 prop = prop->next;
2698 }
2699 return(0);
2700}
2701
2702/**
2703 * xmlTextReaderMoveToFirstAttribute:
2704 * @reader: the xmlTextReaderPtr used
2705 *
2706 * Moves the position of the current instance to the first attribute
2707 * associated with the current node.
2708 *
2709 * Returns 1 in case of success, -1 in case of error, 0 if not found
2710 */
2711int
2712xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2713 if (reader == NULL)
2714 return(-1);
2715 if (reader->node == NULL)
2716 return(-1);
2717 if (reader->node->type != XML_ELEMENT_NODE)
2718 return(0);
2719
2720 if (reader->node->nsDef != NULL) {
2721 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2722 return(1);
2723 }
2724 if (reader->node->properties != NULL) {
2725 reader->curnode = (xmlNodePtr) reader->node->properties;
2726 return(1);
2727 }
2728 return(0);
2729}
2730
2731/**
2732 * xmlTextReaderMoveToNextAttribute:
2733 * @reader: the xmlTextReaderPtr used
2734 *
2735 * Moves the position of the current instance to the next attribute
2736 * associated with the current node.
2737 *
2738 * Returns 1 in case of success, -1 in case of error, 0 if not found
2739 */
2740int
2741xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2742 if (reader == NULL)
2743 return(-1);
2744 if (reader->node == NULL)
2745 return(-1);
2746 if (reader->node->type != XML_ELEMENT_NODE)
2747 return(0);
2748 if (reader->curnode == NULL)
2749 return(xmlTextReaderMoveToFirstAttribute(reader));
2750
2751 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2752 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2753 if (ns->next != NULL) {
2754 reader->curnode = (xmlNodePtr) ns->next;
2755 return(1);
2756 }
2757 if (reader->node->properties != NULL) {
2758 reader->curnode = (xmlNodePtr) reader->node->properties;
2759 return(1);
2760 }
2761 return(0);
2762 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2763 (reader->curnode->next != NULL)) {
2764 reader->curnode = reader->curnode->next;
2765 return(1);
2766 }
2767 return(0);
2768}
2769
2770/**
2771 * xmlTextReaderMoveToElement:
2772 * @reader: the xmlTextReaderPtr used
2773 *
2774 * Moves the position of the current instance to the node that
2775 * contains the current Attribute node.
2776 *
2777 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2778 */
2779int
2780xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2781 if (reader == NULL)
2782 return(-1);
2783 if (reader->node == NULL)
2784 return(-1);
2785 if (reader->node->type != XML_ELEMENT_NODE)
2786 return(0);
2787 if (reader->curnode != NULL) {
2788 reader->curnode = NULL;
2789 return(1);
2790 }
2791 return(0);
2792}
2793
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002794/**
2795 * xmlTextReaderReadAttributeValue:
2796 * @reader: the xmlTextReaderPtr used
2797 *
2798 * Parses an attribute value into one or more Text and EntityReference nodes.
2799 *
2800 * Returns 1 in case of success, 0 if the reader was not positionned on an
2801 * ttribute node or all the attribute values have been read, or -1
2802 * in case of error.
2803 */
2804int
2805xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2806 if (reader == NULL)
2807 return(-1);
2808 if (reader->node == NULL)
2809 return(-1);
2810 if (reader->curnode == NULL)
2811 return(0);
2812 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2813 if (reader->curnode->children == NULL)
2814 return(0);
2815 reader->curnode = reader->curnode->children;
2816 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2817 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2818
2819 if (reader->faketext == NULL) {
2820 reader->faketext = xmlNewDocText(reader->node->doc,
2821 ns->href);
2822 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002823 if ((reader->faketext->content != NULL) &&
2824 (reader->faketext->content !=
2825 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002826 xmlFree(reader->faketext->content);
2827 reader->faketext->content = xmlStrdup(ns->href);
2828 }
2829 reader->curnode = reader->faketext;
2830 } else {
2831 if (reader->curnode->next == NULL)
2832 return(0);
2833 reader->curnode = reader->curnode->next;
2834 }
2835 return(1);
2836}
2837
Daniel Veillarde2811272004-10-19 09:04:23 +00002838/**
2839 * xmlTextReaderConstEncoding:
2840 * @reader: the xmlTextReaderPtr used
2841 *
2842 * Determine the encoding of the document being read.
2843 *
2844 * Returns a string containing the encoding of the document or NULL in
2845 * case of error. The string is deallocated with the reader.
2846 */
2847const xmlChar *
2848xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2849 xmlDocPtr doc = NULL;
2850 if (reader == NULL)
2851 return(NULL);
2852 if (reader->doc != NULL)
2853 doc = reader->doc;
2854 else if (reader->ctxt != NULL)
2855 doc = reader->ctxt->myDoc;
2856 if (doc == NULL)
2857 return(NULL);
2858
2859 if (doc->encoding == NULL)
2860 return(NULL);
2861 else
2862 return(CONSTSTR(doc->encoding));
2863}
2864
2865
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002866/************************************************************************
2867 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002868 * Acces API to the current node *
2869 * *
2870 ************************************************************************/
2871/**
2872 * xmlTextReaderAttributeCount:
2873 * @reader: the xmlTextReaderPtr used
2874 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002875 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002876 *
2877 * Returns 0 i no attributes, -1 in case of error or the attribute count
2878 */
2879int
2880xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2881 int ret;
2882 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002883 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002884 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002885
2886 if (reader == NULL)
2887 return(-1);
2888 if (reader->node == NULL)
2889 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002890
2891 if (reader->curnode != NULL)
2892 node = reader->curnode;
2893 else
2894 node = reader->node;
2895
2896 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002897 return(0);
2898 if ((reader->state == XML_TEXTREADER_END) ||
2899 (reader->state == XML_TEXTREADER_BACKTRACK))
2900 return(0);
2901 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002902 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002903 while (attr != NULL) {
2904 ret++;
2905 attr = attr->next;
2906 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002907 ns = node->nsDef;
2908 while (ns != NULL) {
2909 ret++;
2910 ns = ns->next;
2911 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002912 return(ret);
2913}
2914
2915/**
2916 * xmlTextReaderNodeType:
2917 * @reader: the xmlTextReaderPtr used
2918 *
2919 * Get the node type of the current node
2920 * Reference:
2921 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2922 *
2923 * Returns the xmlNodeType of the current node or -1 in case of error
2924 */
2925int
2926xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002927 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002928
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002929 if (reader == NULL)
2930 return(-1);
2931 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002932 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002933 if (reader->curnode != NULL)
2934 node = reader->curnode;
2935 else
2936 node = reader->node;
2937 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002938 case XML_ELEMENT_NODE:
2939 if ((reader->state == XML_TEXTREADER_END) ||
2940 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002941 return(XML_READER_TYPE_END_ELEMENT);
2942 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002943 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002944 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002945 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002946 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002947 if (xmlIsBlankNode(reader->node)) {
2948 if (xmlNodeGetSpacePreserve(reader->node))
2949 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2950 else
2951 return(XML_READER_TYPE_WHITESPACE);
2952 } else {
2953 return(XML_READER_TYPE_TEXT);
2954 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002955 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002956 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002957 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002958 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002959 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002960 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002962 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002963 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002964 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002965 case XML_DOCUMENT_NODE:
2966 case XML_HTML_DOCUMENT_NODE:
2967#ifdef LIBXML_DOCB_ENABLED
2968 case XML_DOCB_DOCUMENT_NODE:
2969#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002970 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002971 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002972 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002973 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002974 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002975 case XML_DOCUMENT_TYPE_NODE:
2976 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002977 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002978
2979 case XML_ELEMENT_DECL:
2980 case XML_ATTRIBUTE_DECL:
2981 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002982 case XML_XINCLUDE_START:
2983 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002984 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985 }
2986 return(-1);
2987}
2988
2989/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002990 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002991 * @reader: the xmlTextReaderPtr used
2992 *
2993 * Check if the current node is empty
2994 *
2995 * Returns 1 if empty, 0 if not and -1 in case of error
2996 */
2997int
2998xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2999 if ((reader == NULL) || (reader->node == NULL))
3000 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003001 if (reader->node->type != XML_ELEMENT_NODE)
3002 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003003 if (reader->curnode != NULL)
3004 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003005 if (reader->node->children != NULL)
3006 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003007 if (reader->state == XML_TEXTREADER_END)
3008 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003009 if (reader->doc != NULL)
3010 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003011#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003012 if (reader->in_xinclude > 0)
3013 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003014#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003015 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003016}
3017
3018/**
3019 * xmlTextReaderLocalName:
3020 * @reader: the xmlTextReaderPtr used
3021 *
3022 * The local name of the node.
3023 *
3024 * Returns the local name or NULL if not available
3025 */
3026xmlChar *
3027xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003028 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003029 if ((reader == NULL) || (reader->node == NULL))
3030 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003031 if (reader->curnode != NULL)
3032 node = reader->curnode;
3033 else
3034 node = reader->node;
3035 if (node->type == XML_NAMESPACE_DECL) {
3036 xmlNsPtr ns = (xmlNsPtr) node;
3037 if (ns->prefix == NULL)
3038 return(xmlStrdup(BAD_CAST "xmlns"));
3039 else
3040 return(xmlStrdup(ns->prefix));
3041 }
3042 if ((node->type != XML_ELEMENT_NODE) &&
3043 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003044 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003045 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046}
3047
3048/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003049 * xmlTextReaderConstLocalName:
3050 * @reader: the xmlTextReaderPtr used
3051 *
3052 * The local name of the node.
3053 *
3054 * Returns the local name or NULL if not available, the
3055 * string will be deallocated with the reader.
3056 */
3057const xmlChar *
3058xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3059 xmlNodePtr node;
3060 if ((reader == NULL) || (reader->node == NULL))
3061 return(NULL);
3062 if (reader->curnode != NULL)
3063 node = reader->curnode;
3064 else
3065 node = reader->node;
3066 if (node->type == XML_NAMESPACE_DECL) {
3067 xmlNsPtr ns = (xmlNsPtr) node;
3068 if (ns->prefix == NULL)
3069 return(CONSTSTR(BAD_CAST "xmlns"));
3070 else
3071 return(ns->prefix);
3072 }
3073 if ((node->type != XML_ELEMENT_NODE) &&
3074 (node->type != XML_ATTRIBUTE_NODE))
3075 return(xmlTextReaderConstName(reader));
3076 return(node->name);
3077}
3078
3079/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003080 * xmlTextReaderName:
3081 * @reader: the xmlTextReaderPtr used
3082 *
3083 * The qualified name of the node, equal to Prefix :LocalName.
3084 *
3085 * Returns the local name or NULL if not available
3086 */
3087xmlChar *
3088xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003089 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003090 xmlChar *ret;
3091
3092 if ((reader == NULL) || (reader->node == NULL))
3093 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003094 if (reader->curnode != NULL)
3095 node = reader->curnode;
3096 else
3097 node = reader->node;
3098 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003099 case XML_ELEMENT_NODE:
3100 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003101 if ((node->ns == NULL) ||
3102 (node->ns->prefix == NULL))
3103 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003104
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003105 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003106 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003107 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003108 return(ret);
3109 case XML_TEXT_NODE:
3110 return(xmlStrdup(BAD_CAST "#text"));
3111 case XML_CDATA_SECTION_NODE:
3112 return(xmlStrdup(BAD_CAST "#cdata-section"));
3113 case XML_ENTITY_NODE:
3114 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003115 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003116 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003117 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003118 case XML_COMMENT_NODE:
3119 return(xmlStrdup(BAD_CAST "#comment"));
3120 case XML_DOCUMENT_NODE:
3121 case XML_HTML_DOCUMENT_NODE:
3122#ifdef LIBXML_DOCB_ENABLED
3123 case XML_DOCB_DOCUMENT_NODE:
3124#endif
3125 return(xmlStrdup(BAD_CAST "#document"));
3126 case XML_DOCUMENT_FRAG_NODE:
3127 return(xmlStrdup(BAD_CAST "#document-fragment"));
3128 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003129 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003130 case XML_DOCUMENT_TYPE_NODE:
3131 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003132 return(xmlStrdup(node->name));
3133 case XML_NAMESPACE_DECL: {
3134 xmlNsPtr ns = (xmlNsPtr) node;
3135
3136 ret = xmlStrdup(BAD_CAST "xmlns");
3137 if (ns->prefix == NULL)
3138 return(ret);
3139 ret = xmlStrcat(ret, BAD_CAST ":");
3140 ret = xmlStrcat(ret, ns->prefix);
3141 return(ret);
3142 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003143
3144 case XML_ELEMENT_DECL:
3145 case XML_ATTRIBUTE_DECL:
3146 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003147 case XML_XINCLUDE_START:
3148 case XML_XINCLUDE_END:
3149 return(NULL);
3150 }
3151 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003152}
3153
3154/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003155 * xmlTextReaderConstName:
3156 * @reader: the xmlTextReaderPtr used
3157 *
3158 * The qualified name of the node, equal to Prefix :LocalName.
3159 *
3160 * Returns the local name or NULL if not available, the string is
3161 * deallocated with the reader.
3162 */
3163const xmlChar *
3164xmlTextReaderConstName(xmlTextReaderPtr reader) {
3165 xmlNodePtr node;
3166
3167 if ((reader == NULL) || (reader->node == NULL))
3168 return(NULL);
3169 if (reader->curnode != NULL)
3170 node = reader->curnode;
3171 else
3172 node = reader->node;
3173 switch (node->type) {
3174 case XML_ELEMENT_NODE:
3175 case XML_ATTRIBUTE_NODE:
3176 if ((node->ns == NULL) ||
3177 (node->ns->prefix == NULL))
3178 return(node->name);
3179 return(CONSTQSTR(node->ns->prefix, node->name));
3180 case XML_TEXT_NODE:
3181 return(CONSTSTR(BAD_CAST "#text"));
3182 case XML_CDATA_SECTION_NODE:
3183 return(CONSTSTR(BAD_CAST "#cdata-section"));
3184 case XML_ENTITY_NODE:
3185 case XML_ENTITY_REF_NODE:
3186 return(CONSTSTR(node->name));
3187 case XML_PI_NODE:
3188 return(CONSTSTR(node->name));
3189 case XML_COMMENT_NODE:
3190 return(CONSTSTR(BAD_CAST "#comment"));
3191 case XML_DOCUMENT_NODE:
3192 case XML_HTML_DOCUMENT_NODE:
3193#ifdef LIBXML_DOCB_ENABLED
3194 case XML_DOCB_DOCUMENT_NODE:
3195#endif
3196 return(CONSTSTR(BAD_CAST "#document"));
3197 case XML_DOCUMENT_FRAG_NODE:
3198 return(CONSTSTR(BAD_CAST "#document-fragment"));
3199 case XML_NOTATION_NODE:
3200 return(CONSTSTR(node->name));
3201 case XML_DOCUMENT_TYPE_NODE:
3202 case XML_DTD_NODE:
3203 return(CONSTSTR(node->name));
3204 case XML_NAMESPACE_DECL: {
3205 xmlNsPtr ns = (xmlNsPtr) node;
3206
3207 if (ns->prefix == NULL)
3208 return(CONSTSTR(BAD_CAST "xmlns"));
3209 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3210 }
3211
3212 case XML_ELEMENT_DECL:
3213 case XML_ATTRIBUTE_DECL:
3214 case XML_ENTITY_DECL:
3215 case XML_XINCLUDE_START:
3216 case XML_XINCLUDE_END:
3217 return(NULL);
3218 }
3219 return(NULL);
3220}
3221
3222/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003223 * xmlTextReaderPrefix:
3224 * @reader: the xmlTextReaderPtr used
3225 *
3226 * A shorthand reference to the namespace associated with the node.
3227 *
3228 * Returns the prefix or NULL if not available
3229 */
3230xmlChar *
3231xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003232 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003233 if ((reader == NULL) || (reader->node == NULL))
3234 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003235 if (reader->curnode != NULL)
3236 node = reader->curnode;
3237 else
3238 node = reader->node;
3239 if (node->type == XML_NAMESPACE_DECL) {
3240 xmlNsPtr ns = (xmlNsPtr) node;
3241 if (ns->prefix == NULL)
3242 return(NULL);
3243 return(xmlStrdup(BAD_CAST "xmlns"));
3244 }
3245 if ((node->type != XML_ELEMENT_NODE) &&
3246 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003247 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003248 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003249 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003250 return(NULL);
3251}
3252
3253/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003254 * xmlTextReaderConstPrefix:
3255 * @reader: the xmlTextReaderPtr used
3256 *
3257 * A shorthand reference to the namespace associated with the node.
3258 *
3259 * Returns the prefix or NULL if not available, the string is deallocated
3260 * with the reader.
3261 */
3262const xmlChar *
3263xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3264 xmlNodePtr node;
3265 if ((reader == NULL) || (reader->node == NULL))
3266 return(NULL);
3267 if (reader->curnode != NULL)
3268 node = reader->curnode;
3269 else
3270 node = reader->node;
3271 if (node->type == XML_NAMESPACE_DECL) {
3272 xmlNsPtr ns = (xmlNsPtr) node;
3273 if (ns->prefix == NULL)
3274 return(NULL);
3275 return(CONSTSTR(BAD_CAST "xmlns"));
3276 }
3277 if ((node->type != XML_ELEMENT_NODE) &&
3278 (node->type != XML_ATTRIBUTE_NODE))
3279 return(NULL);
3280 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3281 return(CONSTSTR(node->ns->prefix));
3282 return(NULL);
3283}
3284
3285/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003286 * xmlTextReaderNamespaceUri:
3287 * @reader: the xmlTextReaderPtr used
3288 *
3289 * The URI defining the namespace associated with the node.
3290 *
3291 * Returns the namespace URI or NULL if not available
3292 */
3293xmlChar *
3294xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003295 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003296 if ((reader == NULL) || (reader->node == NULL))
3297 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003298 if (reader->curnode != NULL)
3299 node = reader->curnode;
3300 else
3301 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003302 if (node->type == XML_NAMESPACE_DECL)
3303 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003304 if ((node->type != XML_ELEMENT_NODE) &&
3305 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003306 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003307 if (node->ns != NULL)
3308 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003309 return(NULL);
3310}
3311
3312/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003313 * xmlTextReaderConstNamespaceUri:
3314 * @reader: the xmlTextReaderPtr used
3315 *
3316 * The URI defining the namespace associated with the node.
3317 *
3318 * Returns the namespace URI or NULL if not available, the string
3319 * will be deallocated with the reader
3320 */
3321const xmlChar *
3322xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3323 xmlNodePtr node;
3324 if ((reader == NULL) || (reader->node == NULL))
3325 return(NULL);
3326 if (reader->curnode != NULL)
3327 node = reader->curnode;
3328 else
3329 node = reader->node;
3330 if (node->type == XML_NAMESPACE_DECL)
3331 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3332 if ((node->type != XML_ELEMENT_NODE) &&
3333 (node->type != XML_ATTRIBUTE_NODE))
3334 return(NULL);
3335 if (node->ns != NULL)
3336 return(CONSTSTR(node->ns->href));
3337 return(NULL);
3338}
3339
3340/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003341 * xmlTextReaderBaseUri:
3342 * @reader: the xmlTextReaderPtr used
3343 *
3344 * The base URI of the node.
3345 *
3346 * Returns the base URI or NULL if not available
3347 */
3348xmlChar *
3349xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3350 if ((reader == NULL) || (reader->node == NULL))
3351 return(NULL);
3352 return(xmlNodeGetBase(NULL, reader->node));
3353}
3354
3355/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003356 * xmlTextReaderConstBaseUri:
3357 * @reader: the xmlTextReaderPtr used
3358 *
3359 * The base URI of the node.
3360 *
3361 * Returns the base URI or NULL if not available, the string
3362 * will be deallocated with the reader
3363 */
3364const xmlChar *
3365xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3366 xmlChar *tmp;
3367 const xmlChar *ret;
3368
3369 if ((reader == NULL) || (reader->node == NULL))
3370 return(NULL);
3371 tmp = xmlNodeGetBase(NULL, reader->node);
3372 if (tmp == NULL)
3373 return(NULL);
3374 ret = CONSTSTR(tmp);
3375 xmlFree(tmp);
3376 return(ret);
3377}
3378
3379/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003380 * xmlTextReaderDepth:
3381 * @reader: the xmlTextReaderPtr used
3382 *
3383 * The depth of the node in the tree.
3384 *
3385 * Returns the depth or -1 in case of error
3386 */
3387int
3388xmlTextReaderDepth(xmlTextReaderPtr reader) {
3389 if (reader == NULL)
3390 return(-1);
3391 if (reader->node == NULL)
3392 return(0);
3393
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003394 if (reader->curnode != NULL) {
3395 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3396 (reader->curnode->type == XML_NAMESPACE_DECL))
3397 return(reader->depth + 1);
3398 return(reader->depth + 2);
3399 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003400 return(reader->depth);
3401}
3402
3403/**
3404 * xmlTextReaderHasAttributes:
3405 * @reader: the xmlTextReaderPtr used
3406 *
3407 * Whether the node has attributes.
3408 *
3409 * Returns 1 if true, 0 if false, and -1 in case or error
3410 */
3411int
3412xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003413 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003414 if (reader == NULL)
3415 return(-1);
3416 if (reader->node == NULL)
3417 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003418 if (reader->curnode != NULL)
3419 node = reader->curnode;
3420 else
3421 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003422
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003423 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003424 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003425 return(1);
3426 /* TODO: handle the xmlDecl */
3427 return(0);
3428}
3429
3430/**
3431 * xmlTextReaderHasValue:
3432 * @reader: the xmlTextReaderPtr used
3433 *
3434 * Whether the node can have a text value.
3435 *
3436 * Returns 1 if true, 0 if false, and -1 in case or error
3437 */
3438int
3439xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003440 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003441 if (reader == NULL)
3442 return(-1);
3443 if (reader->node == NULL)
3444 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003445 if (reader->curnode != NULL)
3446 node = reader->curnode;
3447 else
3448 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003449
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003450 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003451 case XML_ATTRIBUTE_NODE:
3452 case XML_TEXT_NODE:
3453 case XML_CDATA_SECTION_NODE:
3454 case XML_PI_NODE:
3455 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003456 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003457 return(1);
3458 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003459 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003460 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003461 return(0);
3462}
3463
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003464/**
3465 * xmlTextReaderValue:
3466 * @reader: the xmlTextReaderPtr used
3467 *
3468 * Provides the text value of the node if present
3469 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003470 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003471 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003472 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003473xmlChar *
3474xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003475 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003476 if (reader == NULL)
3477 return(NULL);
3478 if (reader->node == NULL)
3479 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003480 if (reader->curnode != NULL)
3481 node = reader->curnode;
3482 else
3483 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003484
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003485 switch (node->type) {
3486 case XML_NAMESPACE_DECL:
3487 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003488 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003489 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003490
3491 if (attr->parent != NULL)
3492 return (xmlNodeListGetString
3493 (attr->parent->doc, attr->children, 1));
3494 else
3495 return (xmlNodeListGetString(NULL, attr->children, 1));
3496 break;
3497 }
3498 case XML_TEXT_NODE:
3499 case XML_CDATA_SECTION_NODE:
3500 case XML_PI_NODE:
3501 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003502 if (node->content != NULL)
3503 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003504 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003505 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003506 }
3507 return(NULL);
3508}
3509
3510/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003511 * xmlTextReaderConstValue:
3512 * @reader: the xmlTextReaderPtr used
3513 *
3514 * Provides the text value of the node if present
3515 *
3516 * Returns the string or NULL if not available. The result will be
3517 * deallocated on the next Read() operation.
3518 */
3519const xmlChar *
3520xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3521 xmlNodePtr node;
3522 if (reader == NULL)
3523 return(NULL);
3524 if (reader->node == NULL)
3525 return(NULL);
3526 if (reader->curnode != NULL)
3527 node = reader->curnode;
3528 else
3529 node = reader->node;
3530
3531 switch (node->type) {
3532 case XML_NAMESPACE_DECL:
3533 return(((xmlNsPtr) node)->href);
3534 case XML_ATTRIBUTE_NODE:{
3535 xmlAttrPtr attr = (xmlAttrPtr) node;
3536
3537 if ((attr->children != NULL) &&
3538 (attr->children->type == XML_TEXT_NODE) &&
3539 (attr->children->next == NULL))
3540 return(attr->children->content);
3541 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003542 if (reader->buffer == NULL)
3543 reader->buffer = xmlBufferCreateSize(100);
3544 if (reader->buffer == NULL) {
3545 xmlGenericError(xmlGenericErrorContext,
3546 "xmlTextReaderSetup : malloc failed\n");
3547 return (NULL);
3548 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003549 reader->buffer->use = 0;
3550 xmlNodeBufGetContent(reader->buffer, node);
3551 return(reader->buffer->content);
3552 }
3553 break;
3554 }
3555 case XML_TEXT_NODE:
3556 case XML_CDATA_SECTION_NODE:
3557 case XML_PI_NODE:
3558 case XML_COMMENT_NODE:
3559 return(node->content);
3560 default:
3561 break;
3562 }
3563 return(NULL);
3564}
3565
3566/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003567 * xmlTextReaderIsDefault:
3568 * @reader: the xmlTextReaderPtr used
3569 *
3570 * Whether an Attribute node was generated from the default value
3571 * defined in the DTD or schema.
3572 *
3573 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3574 */
3575int
3576xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3577 if (reader == NULL)
3578 return(-1);
3579 return(0);
3580}
3581
3582/**
3583 * xmlTextReaderQuoteChar:
3584 * @reader: the xmlTextReaderPtr used
3585 *
3586 * The quotation mark character used to enclose the value of an attribute.
3587 *
3588 * Returns " or ' and -1 in case of error
3589 */
3590int
3591xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3592 if (reader == NULL)
3593 return(-1);
3594 /* TODO maybe lookup the attribute value for " first */
3595 return((int) '"');
3596}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003597
3598/**
3599 * xmlTextReaderXmlLang:
3600 * @reader: the xmlTextReaderPtr used
3601 *
3602 * The xml:lang scope within which the node resides.
3603 *
3604 * Returns the xml:lang value or NULL if none exists.
3605 */
3606xmlChar *
3607xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3608 if (reader == NULL)
3609 return(NULL);
3610 if (reader->node == NULL)
3611 return(NULL);
3612 return(xmlNodeGetLang(reader->node));
3613}
3614
Daniel Veillard67df8092002-12-16 22:04:11 +00003615/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003616 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003617 * @reader: the xmlTextReaderPtr used
3618 *
3619 * The xml:lang scope within which the node resides.
3620 *
3621 * Returns the xml:lang value or NULL if none exists.
3622 */
3623const xmlChar *
3624xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3625 xmlChar *tmp;
3626 const xmlChar *ret;
3627
3628 if (reader == NULL)
3629 return(NULL);
3630 if (reader->node == NULL)
3631 return(NULL);
3632 tmp = xmlNodeGetLang(reader->node);
3633 if (tmp == NULL)
3634 return(NULL);
3635 ret = CONSTSTR(tmp);
3636 xmlFree(tmp);
3637 return(ret);
3638}
3639
3640/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003641 * xmlTextReaderConstString:
3642 * @reader: the xmlTextReaderPtr used
3643 * @str: the string to intern.
3644 *
3645 * Get an interned string from the reader, allows for example to
3646 * speedup string name comparisons
3647 *
3648 * Returns an interned copy of the string or NULL in case of error. The
3649 * string will be deallocated with the reader.
3650 */
3651const xmlChar *
3652xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3653 if (reader == NULL)
3654 return(NULL);
3655 return(CONSTSTR(str));
3656}
3657
3658/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003659 * xmlTextReaderNormalization:
3660 * @reader: the xmlTextReaderPtr used
3661 *
3662 * The value indicating whether to normalize white space and attribute values.
3663 * Since attribute value and end of line normalizations are a MUST in the XML
3664 * specification only the value true is accepted. The broken bahaviour of
3665 * accepting out of range character entities like &#0; is of course not
3666 * supported either.
3667 *
3668 * Returns 1 or -1 in case of error.
3669 */
3670int
3671xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3672 if (reader == NULL)
3673 return(-1);
3674 return(1);
3675}
3676
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003677/************************************************************************
3678 * *
3679 * Extensions to the base APIs *
3680 * *
3681 ************************************************************************/
3682
3683/**
3684 * xmlTextReaderSetParserProp:
3685 * @reader: the xmlTextReaderPtr used
3686 * @prop: the xmlParserProperties to set
3687 * @value: usually 0 or 1 to (de)activate it
3688 *
3689 * Change the parser processing behaviour by changing some of its internal
3690 * properties. Note that some properties can only be changed before any
3691 * read has been done.
3692 *
3693 * Returns 0 if the call was successful, or -1 in case of error
3694 */
3695int
3696xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3697 xmlParserProperties p = (xmlParserProperties) prop;
3698 xmlParserCtxtPtr ctxt;
3699
3700 if ((reader == NULL) || (reader->ctxt == NULL))
3701 return(-1);
3702 ctxt = reader->ctxt;
3703
3704 switch (p) {
3705 case XML_PARSER_LOADDTD:
3706 if (value != 0) {
3707 if (ctxt->loadsubset == 0) {
3708 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3709 return(-1);
3710 ctxt->loadsubset = XML_DETECT_IDS;
3711 }
3712 } else {
3713 ctxt->loadsubset = 0;
3714 }
3715 return(0);
3716 case XML_PARSER_DEFAULTATTRS:
3717 if (value != 0) {
3718 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3719 } else {
3720 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3721 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3722 }
3723 return(0);
3724 case XML_PARSER_VALIDATE:
3725 if (value != 0) {
3726 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003727 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003728 } else {
3729 ctxt->validate = 0;
3730 }
3731 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003732 case XML_PARSER_SUBST_ENTITIES:
3733 if (value != 0) {
3734 ctxt->replaceEntities = 1;
3735 } else {
3736 ctxt->replaceEntities = 0;
3737 }
3738 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003739 }
3740 return(-1);
3741}
3742
3743/**
3744 * xmlTextReaderGetParserProp:
3745 * @reader: the xmlTextReaderPtr used
3746 * @prop: the xmlParserProperties to get
3747 *
3748 * Read the parser internal property.
3749 *
3750 * Returns the value, usually 0 or 1, or -1 in case of error.
3751 */
3752int
3753xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3754 xmlParserProperties p = (xmlParserProperties) prop;
3755 xmlParserCtxtPtr ctxt;
3756
3757 if ((reader == NULL) || (reader->ctxt == NULL))
3758 return(-1);
3759 ctxt = reader->ctxt;
3760
3761 switch (p) {
3762 case XML_PARSER_LOADDTD:
3763 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3764 return(1);
3765 return(0);
3766 case XML_PARSER_DEFAULTATTRS:
3767 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3768 return(1);
3769 return(0);
3770 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003771 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003772 case XML_PARSER_SUBST_ENTITIES:
3773 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003774 }
3775 return(-1);
3776}
3777
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003778
Daniel Veillarde18fc182002-12-28 22:56:33 +00003779/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003780 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003781 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003782 *
3783 * Provide the line number of the current parsing point.
3784 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003785 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003786 */
3787int
3788xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3789{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003790 if ((reader == NULL) || (reader->ctxt == NULL) ||
3791 (reader->ctxt->input == NULL)) {
3792 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003793 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003794 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003795}
3796
3797/**
3798 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003799 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003800 *
3801 * Provide the column number of the current parsing point.
3802 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003803 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003804 */
3805int
3806xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3807{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003808 if ((reader == NULL) || (reader->ctxt == NULL) ||
3809 (reader->ctxt->input == NULL)) {
3810 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003811 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003812 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003813}
3814
3815/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003816 * xmlTextReaderCurrentNode:
3817 * @reader: the xmlTextReaderPtr used
3818 *
3819 * Hacking interface allowing to get the xmlNodePtr correponding to the
3820 * current node being accessed by the xmlTextReader. This is dangerous
3821 * because the underlying node may be destroyed on the next Reads.
3822 *
3823 * Returns the xmlNodePtr or NULL in case of error.
3824 */
3825xmlNodePtr
3826xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3827 if (reader == NULL)
3828 return(NULL);
3829
3830 if (reader->curnode != NULL)
3831 return(reader->curnode);
3832 return(reader->node);
3833}
3834
3835/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003836 * xmlTextReaderPreserve:
3837 * @reader: the xmlTextReaderPtr used
3838 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003839 * This tells the XML Reader to preserve the current node.
3840 * The caller must also use xmlTextReaderCurrentDoc() to
3841 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003842 *
3843 * Returns the xmlNodePtr or NULL in case of error.
3844 */
3845xmlNodePtr
3846xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3847 xmlNodePtr cur, parent;
3848
3849 if (reader == NULL)
3850 return(NULL);
3851
3852 if (reader->curnode != NULL)
3853 cur = reader->curnode;
3854 else
3855 cur = reader->node;
3856 if (cur == NULL)
3857 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003858
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003859 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003860 cur->extra |= NODE_IS_PRESERVED;
3861 cur->extra |= NODE_IS_SPRESERVED;
3862 }
3863 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003864
3865 parent = cur->parent;;
3866 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003867 if (parent->type == XML_ELEMENT_NODE)
3868 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003869 parent = parent->parent;
3870 }
3871 return(cur);
3872}
3873
Daniel Veillard1e906612003-12-05 14:57:46 +00003874#ifdef LIBXML_PATTERN_ENABLED
3875/**
3876 * xmlTextReaderPreservePattern:
3877 * @reader: the xmlTextReaderPtr used
3878 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003879 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003880 *
3881 * This tells the XML Reader to preserve all nodes matched by the
3882 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3883 * keep an handle on the resulting document once parsing has finished
3884 *
3885 * Returns a positive number in case of success and -1 in case of error
3886 */
3887int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003888xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3889 const xmlChar **namespaces)
3890{
Daniel Veillard1e906612003-12-05 14:57:46 +00003891 xmlPatternPtr comp;
3892
3893 if ((reader == NULL) || (pattern == NULL))
3894 return(-1);
3895
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003896 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003897 if (comp == NULL)
3898 return(-1);
3899
3900 if (reader->patternMax <= 0) {
3901 reader->patternMax = 4;
3902 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3903 sizeof(reader->patternTab[0]));
3904 if (reader->patternTab == NULL) {
3905 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3906 return (-1);
3907 }
3908 }
3909 if (reader->patternNr >= reader->patternMax) {
3910 xmlPatternPtr *tmp;
3911 reader->patternMax *= 2;
3912 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3913 reader->patternMax *
3914 sizeof(reader->patternTab[0]));
3915 if (tmp == NULL) {
3916 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3917 reader->patternMax /= 2;
3918 return (-1);
3919 }
3920 reader->patternTab = tmp;
3921 }
3922 reader->patternTab[reader->patternNr] = comp;
3923 return(reader->patternNr++);
3924}
3925#endif
3926
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003927/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003928 * xmlTextReaderCurrentDoc:
3929 * @reader: the xmlTextReaderPtr used
3930 *
3931 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003932 * current document being accessed by the xmlTextReader.
3933 * NOTE: as a result of this call, the reader will not destroy the
3934 * associated XML document and calling xmlFreeDoc() on the result
3935 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003936 *
3937 * Returns the xmlDocPtr or NULL in case of error.
3938 */
3939xmlDocPtr
3940xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003941 if (reader == NULL)
3942 return(NULL);
3943 if (reader->doc != NULL)
3944 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003945 if ((reader == NULL) || (reader->ctxt == NULL) ||
3946 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003947 return(NULL);
3948
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003949 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003950 return(reader->ctxt->myDoc);
3951}
3952
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003953#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003954
3955static char *
3956xmlTextReaderBuildMessage(const char *msg, va_list ap);
3957
Daniel Veillardffa3c742005-07-21 13:24:09 +00003958static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003959xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3960
Daniel Veillardffa3c742005-07-21 13:24:09 +00003961static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003962xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3963
Daniel Veillardffa3c742005-07-21 13:24:09 +00003964static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003965{
3966 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3967 char * str;
3968 va_list ap;
3969
3970 va_start(ap,msg);
3971 str = xmlTextReaderBuildMessage(msg,ap);
3972 if (!reader->errorFunc) {
3973 xmlTextReaderValidityError(ctx, "%s", str);
3974 } else {
3975 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3976 }
3977 if (str != NULL)
3978 xmlFree(str);
3979 va_end(ap);
3980}
3981
Daniel Veillardffa3c742005-07-21 13:24:09 +00003982static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003983{
3984 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3985 char * str;
3986 va_list ap;
3987
3988 va_start(ap,msg);
3989 str = xmlTextReaderBuildMessage(msg,ap);
3990 if (!reader->errorFunc) {
3991 xmlTextReaderValidityWarning(ctx, "%s", str);
3992 } else {
3993 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3994 }
3995 if (str != NULL)
3996 xmlFree(str);
3997 va_end(ap);
3998}
3999
4000static void
4001xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4002
4003static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
4004{
4005 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4006
4007 if (reader->sErrorFunc) {
4008 reader->sErrorFunc(reader->errorFuncArg, error);
4009 } else {
4010 xmlTextReaderStructuredError(reader, error);
4011 }
4012}
4013
Daniel Veillardf4e55762003-04-15 23:32:22 +00004014/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004015 * xmlTextReaderRelaxNGSetSchema:
4016 * @reader: the xmlTextReaderPtr used
4017 * @schema: a precompiled RelaxNG schema
4018 *
4019 * Use RelaxNG to validate the document as it is processed.
4020 * Activation is only possible before the first Read().
4021 * if @schema is NULL, then RelaxNG validation is desactivated.
4022 @ The @schema should not be freed until the reader is deallocated
4023 * or its use has been deactivated.
4024 *
4025 * Returns 0 in case the RelaxNG validation could be (des)activated and
4026 * -1 in case of error.
4027 */
4028int
4029xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004030 if (reader == NULL)
4031 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004032 if (schema == NULL) {
4033 if (reader->rngSchemas != NULL) {
4034 xmlRelaxNGFree(reader->rngSchemas);
4035 reader->rngSchemas = NULL;
4036 }
4037 if (reader->rngValidCtxt != NULL) {
4038 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4039 reader->rngValidCtxt = NULL;
4040 }
4041 return(0);
4042 }
4043 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4044 return(-1);
4045 if (reader->rngSchemas != NULL) {
4046 xmlRelaxNGFree(reader->rngSchemas);
4047 reader->rngSchemas = NULL;
4048 }
4049 if (reader->rngValidCtxt != NULL) {
4050 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4051 reader->rngValidCtxt = NULL;
4052 }
4053 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4054 if (reader->rngValidCtxt == NULL)
4055 return(-1);
4056 if (reader->errorFunc != NULL) {
4057 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004058 xmlTextReaderValidityErrorRelay,
4059 xmlTextReaderValidityWarningRelay,
4060 reader);
4061 }
4062 if (reader->sErrorFunc != NULL) {
4063 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4064 xmlTextReaderValidityStructuredRelay,
4065 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004066 }
4067 reader->rngValidErrors = 0;
4068 reader->rngFullNode = NULL;
4069 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4070 return(0);
4071}
4072
4073/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004074 * xmlTextReaderSetSchema:
4075 * @reader: the xmlTextReaderPtr used
4076 * @schema: a precompiled Schema schema
4077 *
4078 * Use XSD Schema to validate the document as it is processed.
4079 * Activation is only possible before the first Read().
4080 * if @schema is NULL, then Schema validation is desactivated.
4081 @ The @schema should not be freed until the reader is deallocated
4082 * or its use has been deactivated.
4083 *
4084 * Returns 0 in case the Schema validation could be (des)activated and
4085 * -1 in case of error.
4086 */
4087int
4088xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4089 if (reader == NULL)
4090 return(-1);
4091 if (schema == NULL) {
4092 if (reader->xsdPlug != NULL) {
4093 xmlSchemaSAXUnplug(reader->xsdPlug);
4094 reader->xsdPlug = NULL;
4095 }
4096 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004097 if (! reader->xsdPreserveCtxt)
4098 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4099 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004100 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004101 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004102 if (reader->xsdSchemas != NULL) {
4103 xmlSchemaFree(reader->xsdSchemas);
4104 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004105 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004106 return(0);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004107 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004108 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4109 return(-1);
4110 if (reader->xsdPlug != NULL) {
4111 xmlSchemaSAXUnplug(reader->xsdPlug);
4112 reader->xsdPlug = NULL;
4113 }
4114 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004115 if (! reader->xsdPreserveCtxt)
4116 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004117 reader->xsdValidCtxt = NULL;
4118 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004119 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004120 if (reader->xsdSchemas != NULL) {
4121 xmlSchemaFree(reader->xsdSchemas);
4122 reader->xsdSchemas = NULL;
4123 }
4124 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4125 if (reader->xsdValidCtxt == NULL) {
4126 xmlSchemaFree(reader->xsdSchemas);
4127 reader->xsdSchemas = NULL;
4128 return(-1);
4129 }
4130 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4131 &(reader->ctxt->sax),
4132 &(reader->ctxt->userData));
4133 if (reader->xsdPlug == NULL) {
4134 xmlSchemaFree(reader->xsdSchemas);
4135 reader->xsdSchemas = NULL;
4136 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4137 reader->xsdValidCtxt = NULL;
4138 return(-1);
4139 }
4140 if (reader->errorFunc != NULL) {
4141 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004142 xmlTextReaderValidityErrorRelay,
4143 xmlTextReaderValidityWarningRelay,
4144 reader);
4145 }
4146 if (reader->sErrorFunc != NULL) {
4147 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4148 xmlTextReaderValidityStructuredRelay,
4149 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004150 }
4151 reader->xsdValidErrors = 0;
4152 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4153 return(0);
4154}
4155
4156/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004157 * xmlTextReaderRelaxNGValidate:
4158 * @reader: the xmlTextReaderPtr used
4159 * @rng: the path to a RelaxNG schema or NULL
4160 *
4161 * Use RelaxNG to validate the document as it is processed.
4162 * Activation is only possible before the first Read().
4163 * if @rng is NULL, then RelaxNG validation is desactivated.
4164 *
4165 * Returns 0 in case the RelaxNG validation could be (des)activated and
4166 * -1 in case of error.
4167 */
4168int
4169xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4170 xmlRelaxNGParserCtxtPtr ctxt;
4171
4172 if (reader == NULL)
4173 return(-1);
4174
4175 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004176 if (reader->rngValidCtxt != NULL) {
4177 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4178 reader->rngValidCtxt = NULL;
4179 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004180 if (reader->rngSchemas != NULL) {
4181 xmlRelaxNGFree(reader->rngSchemas);
4182 reader->rngSchemas = NULL;
4183 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004184 return(0);
4185 }
4186 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4187 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004188 if (reader->rngSchemas != NULL) {
4189 xmlRelaxNGFree(reader->rngSchemas);
4190 reader->rngSchemas = NULL;
4191 }
4192 if (reader->rngValidCtxt != NULL) {
4193 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4194 reader->rngValidCtxt = NULL;
4195 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004196 ctxt = xmlRelaxNGNewParserCtxt(rng);
4197 if (reader->errorFunc != NULL) {
4198 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004199 xmlTextReaderValidityErrorRelay,
4200 xmlTextReaderValidityWarningRelay,
4201 reader);
4202 }
4203 if (reader->sErrorFunc != NULL) {
4204 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4205 xmlTextReaderValidityStructuredRelay,
4206 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004207 }
4208 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4209 xmlRelaxNGFreeParserCtxt(ctxt);
4210 if (reader->rngSchemas == NULL)
4211 return(-1);
4212 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004213 if (reader->rngValidCtxt == NULL) {
4214 xmlRelaxNGFree(reader->rngSchemas);
4215 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004216 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004217 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004218 if (reader->errorFunc != NULL) {
4219 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004220 xmlTextReaderValidityErrorRelay,
4221 xmlTextReaderValidityWarningRelay,
4222 reader);
4223 }
4224 if (reader->sErrorFunc != NULL) {
4225 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4226 xmlTextReaderValidityStructuredRelay,
4227 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004228 }
4229 reader->rngValidErrors = 0;
4230 reader->rngFullNode = NULL;
4231 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4232 return(0);
4233}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004234
4235/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004236 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004237 * @reader: the xmlTextReaderPtr used
4238 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004239 * @ctxt: the XML Schema validation context or NULL
4240 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004241 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004242 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004243 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004244 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004245 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004246 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004247 * -1 in case of error.
4248 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004249static int
4250xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4251 const char *xsd,
4252 xmlSchemaValidCtxtPtr ctxt,
4253 int options ATTRIBUTE_UNUSED)
4254{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004255 if (reader == NULL)
4256 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004257
4258 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004259 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004260
4261 if (((xsd != NULL) || (ctxt != NULL)) &&
4262 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4263 (reader->ctxt == NULL)))
4264 return(-1);
4265
4266 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004267 if (reader->xsdPlug != NULL) {
4268 xmlSchemaSAXUnplug(reader->xsdPlug);
4269 reader->xsdPlug = NULL;
4270 }
4271 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004272 if (! reader->xsdPreserveCtxt)
4273 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004274 reader->xsdValidCtxt = NULL;
4275 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004276 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004277 if (reader->xsdSchemas != NULL) {
4278 xmlSchemaFree(reader->xsdSchemas);
4279 reader->xsdSchemas = NULL;
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004280 }
4281
4282 if ((xsd == NULL) && (ctxt == NULL)) {
4283 /* We just want to deactivate the validation, so get out. */
4284 return(0);
4285 }
4286
4287 if (xsd != NULL) {
4288 xmlSchemaParserCtxtPtr pctxt;
4289 /* Parse the schema and create validation environment. */
4290 pctxt = xmlSchemaNewParserCtxt(xsd);
4291 if (reader->errorFunc != NULL) {
4292 xmlSchemaSetParserErrors(pctxt,
4293 xmlTextReaderValidityErrorRelay,
4294 xmlTextReaderValidityWarningRelay,
4295 reader);
4296 }
4297 reader->xsdSchemas = xmlSchemaParse(pctxt);
4298 xmlSchemaFreeParserCtxt(pctxt);
4299 if (reader->xsdSchemas == NULL)
4300 return(-1);
4301 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4302 if (reader->xsdValidCtxt == NULL) {
4303 xmlSchemaFree(reader->xsdSchemas);
4304 reader->xsdSchemas = NULL;
4305 return(-1);
4306 }
4307 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4308 &(reader->ctxt->sax),
4309 &(reader->ctxt->userData));
4310 if (reader->xsdPlug == NULL) {
4311 xmlSchemaFree(reader->xsdSchemas);
4312 reader->xsdSchemas = NULL;
4313 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4314 reader->xsdValidCtxt = NULL;
4315 return(-1);
4316 }
4317 } else {
4318 /* Use the given validation context. */
4319 reader->xsdValidCtxt = ctxt;
4320 reader->xsdPreserveCtxt = 1;
4321 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4322 &(reader->ctxt->sax),
4323 &(reader->ctxt->userData));
4324 if (reader->xsdPlug == NULL) {
4325 reader->xsdValidCtxt = NULL;
4326 reader->xsdPreserveCtxt = 0;
4327 return(-1);
4328 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004329 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004330 /*
4331 * Redirect the validation context's error channels to use
4332 * the reader channels.
4333 * TODO: In case the user provides the validation context we
4334 * could make this redirection optional.
4335 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004336 if (reader->errorFunc != NULL) {
4337 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004338 xmlTextReaderValidityErrorRelay,
4339 xmlTextReaderValidityWarningRelay,
4340 reader);
4341 }
4342 if (reader->sErrorFunc != NULL) {
4343 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4344 xmlTextReaderValidityStructuredRelay,
4345 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004346 }
4347 reader->xsdValidErrors = 0;
4348 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4349 return(0);
4350}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004351
4352/**
4353 * xmlTextReaderSchemaValidateCtxt:
4354 * @reader: the xmlTextReaderPtr used
4355 * @ctxt: the XML Schema validation context or NULL
4356 * @options: options (not used yet)
4357 *
4358 * Use W3C XSD schema context to validate the document as it is processed.
4359 * Activation is only possible before the first Read().
4360 * If @ctxt is NULL, then XML Schema validation is deactivated.
4361 *
4362 * Returns 0 in case the schemas validation could be (de)activated and
4363 * -1 in case of error.
4364 */
4365int
4366xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4367 xmlSchemaValidCtxtPtr ctxt,
4368 int options)
4369{
4370 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4371}
4372
4373/**
4374 * xmlTextReaderSchemaValidate:
4375 * @reader: the xmlTextReaderPtr used
4376 * @xsd: the path to a W3C XSD schema or NULL
4377 *
4378 * Use W3C XSD schema to validate the document as it is processed.
4379 * Activation is only possible before the first Read().
4380 * If @xsd is NULL, then XML Schema validation is deactivated.
4381 *
4382 * Returns 0 in case the schemas validation could be (de)activated and
4383 * -1 in case of error.
4384 */
4385int
4386xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4387{
4388 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4389}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004390#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004391
Daniel Veillarde2811272004-10-19 09:04:23 +00004392/**
4393 * xmlTextReaderIsNamespaceDecl:
4394 * @reader: the xmlTextReaderPtr used
4395 *
4396 * Determine whether the current node is a namespace declaration
4397 * rather than a regular attribute.
4398 *
4399 * Returns 1 if the current node is a namespace declaration, 0 if it
4400 * is a regular attribute or other type of node, or -1 in case of
4401 * error.
4402 */
4403int
4404xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4405 xmlNodePtr node;
4406 if (reader == NULL)
4407 return(-1);
4408 if (reader->node == NULL)
4409 return(-1);
4410 if (reader->curnode != NULL)
4411 node = reader->curnode;
4412 else
4413 node = reader->node;
4414
4415 if (XML_NAMESPACE_DECL == node->type)
4416 return(1);
4417 else
4418 return(0);
4419}
4420
4421/**
4422 * xmlTextReaderConstXmlVersion:
4423 * @reader: the xmlTextReaderPtr used
4424 *
4425 * Determine the XML version of the document being read.
4426 *
4427 * Returns a string containing the XML version of the document or NULL
4428 * in case of error. The string is deallocated with the reader.
4429 */
4430const xmlChar *
4431xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4432 xmlDocPtr doc = NULL;
4433 if (reader == NULL)
4434 return(NULL);
4435 if (reader->doc != NULL)
4436 doc = reader->doc;
4437 else if (reader->ctxt != NULL)
4438 doc = reader->ctxt->myDoc;
4439 if (doc == NULL)
4440 return(NULL);
4441
4442 if (doc->version == NULL)
4443 return(NULL);
4444 else
4445 return(CONSTSTR(doc->version));
4446}
4447
4448/**
4449 * xmlTextReaderStandalone:
4450 * @reader: the xmlTextReaderPtr used
4451 *
4452 * Determine the standalone status of the document being read.
4453 *
4454 * Returns 1 if the document was declared to be standalone, 0 if it
4455 * was declared to be not standalone, or -1 if the document did not
4456 * specify its standalone status or in case of error.
4457 */
4458int
4459xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4460 xmlDocPtr doc = NULL;
4461 if (reader == NULL)
4462 return(-1);
4463 if (reader->doc != NULL)
4464 doc = reader->doc;
4465 else if (reader->ctxt != NULL)
4466 doc = reader->ctxt->myDoc;
4467 if (doc == NULL)
4468 return(-1);
4469
4470 return(doc->standalone);
4471}
4472
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004473/************************************************************************
4474 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004475 * Error Handling Extensions *
4476 * *
4477 ************************************************************************/
4478
4479/* helper to build a xmlMalloc'ed string from a format and va_list */
4480static char *
4481xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4482 int size;
4483 int chars;
4484 char *larger;
4485 char *str;
4486
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004487 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004488 if (str == NULL) {
4489 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4490 return NULL;
4491 }
4492
4493 size = 150;
4494
4495 while (1) {
4496 chars = vsnprintf(str, size, msg, ap);
4497 if ((chars > -1) && (chars < size))
4498 break;
4499 if (chars > -1)
4500 size += chars + 1;
4501 else
4502 size += 100;
4503 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4504 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4505 xmlFree(str);
4506 return NULL;
4507 }
4508 str = larger;
4509 }
4510
4511 return str;
4512}
4513
Daniel Veillard417be3a2003-01-20 21:26:34 +00004514/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004515 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004516 * @locator: the xmlTextReaderLocatorPtr used
4517 *
4518 * Obtain the line number for the given locator.
4519 *
4520 * Returns the line number or -1 in case of error.
4521 */
4522int
4523xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4524 /* we know that locator is a xmlParserCtxtPtr */
4525 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4526 int ret = -1;
4527
Daniel Veillardce682bc2004-11-05 17:22:25 +00004528 if (locator == NULL)
4529 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004530 if (ctx->node != NULL) {
4531 ret = xmlGetLineNo(ctx->node);
4532 }
4533 else {
4534 /* inspired from error.c */
4535 xmlParserInputPtr input;
4536 input = ctx->input;
4537 if ((input->filename == NULL) && (ctx->inputNr > 1))
4538 input = ctx->inputTab[ctx->inputNr - 2];
4539 if (input != NULL) {
4540 ret = input->line;
4541 }
4542 else {
4543 ret = -1;
4544 }
4545 }
4546
4547 return ret;
4548}
4549
4550/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004551 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004552 * @locator: the xmlTextReaderLocatorPtr used
4553 *
4554 * Obtain the base URI for the given locator.
4555 *
4556 * Returns the base URI or NULL in case of error.
4557 */
4558xmlChar *
4559xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4560 /* we know that locator is a xmlParserCtxtPtr */
4561 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4562 xmlChar *ret = NULL;
4563
Daniel Veillardce682bc2004-11-05 17:22:25 +00004564 if (locator == NULL)
4565 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004566 if (ctx->node != NULL) {
4567 ret = xmlNodeGetBase(NULL,ctx->node);
4568 }
4569 else {
4570 /* inspired from error.c */
4571 xmlParserInputPtr input;
4572 input = ctx->input;
4573 if ((input->filename == NULL) && (ctx->inputNr > 1))
4574 input = ctx->inputTab[ctx->inputNr - 2];
4575 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004576 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004577 }
4578 else {
4579 ret = NULL;
4580 }
4581 }
4582
4583 return ret;
4584}
4585
Daniel Veillard26f70262003-01-16 22:45:08 +00004586static void
William M. Brack899e64a2003-09-26 18:03:42 +00004587xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004588 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4589 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4590
William M. Bracka3215c72004-07-31 16:24:01 +00004591 if (str != NULL) {
4592 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004593 reader->errorFunc(reader->errorFuncArg,
4594 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004595 severity,
4596 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004597 xmlFree(str);
4598 }
4599}
4600
4601static void
William M. Brack93d004f2004-02-03 00:14:10 +00004602xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4603 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4604 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4605
4606 if (error && reader->sErrorFunc) {
4607 reader->sErrorFunc(reader->errorFuncArg,
4608 (xmlErrorPtr) error);
4609 }
4610}
4611
Daniel Veillardffa3c742005-07-21 13:24:09 +00004612static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004613xmlTextReaderError(void *ctxt, const char *msg, ...) {
4614 va_list ap;
4615
4616 va_start(ap,msg);
4617 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004618 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004619 xmlTextReaderBuildMessage(msg,ap));
4620 va_end(ap);
4621
4622}
4623
Daniel Veillardffa3c742005-07-21 13:24:09 +00004624static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004625xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4626 va_list ap;
4627
4628 va_start(ap,msg);
4629 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004630 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004631 xmlTextReaderBuildMessage(msg,ap));
4632 va_end(ap);
4633}
4634
Daniel Veillardffa3c742005-07-21 13:24:09 +00004635static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004636xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4637 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004638 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004639
Daniel Veillard417be3a2003-01-20 21:26:34 +00004640 if ((len > 1) && (msg[len - 2] != ':')) {
4641 /*
4642 * some callbacks only report locator information:
4643 * skip them (mimicking behaviour in error.c)
4644 */
4645 va_start(ap,msg);
4646 xmlTextReaderGenericError(ctxt,
4647 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4648 xmlTextReaderBuildMessage(msg,ap));
4649 va_end(ap);
4650 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004651}
4652
Daniel Veillardffa3c742005-07-21 13:24:09 +00004653static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004654xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4655 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004656 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004657
Daniel Veillard417be3a2003-01-20 21:26:34 +00004658 if ((len != 0) && (msg[len - 1] != ':')) {
4659 /*
4660 * some callbacks only report locator information:
4661 * skip them (mimicking behaviour in error.c)
4662 */
4663 va_start(ap,msg);
4664 xmlTextReaderGenericError(ctxt,
4665 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4666 xmlTextReaderBuildMessage(msg,ap));
4667 va_end(ap);
4668 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004669}
4670
4671/**
4672 * xmlTextReaderSetErrorHandler:
4673 * @reader: the xmlTextReaderPtr used
4674 * @f: the callback function to call on error and warnings
4675 * @arg: a user argument to pass to the callback function
4676 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004677 * Register a callback function that will be called on error and warnings.
4678 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004679 * If @f is NULL, the default error and warning handlers are restored.
4680 */
4681void
4682xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4683 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004684 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004685 if (f != NULL) {
4686 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004687 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004688 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4689 reader->ctxt->sax->warning = xmlTextReaderWarning;
4690 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4691 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004692 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004693 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004694#ifdef LIBXML_SCHEMAS_ENABLED
4695 if (reader->rngValidCtxt) {
4696 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4697 xmlTextReaderValidityErrorRelay,
4698 xmlTextReaderValidityWarningRelay,
4699 reader);
4700 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4701 }
4702 if (reader->xsdValidCtxt) {
4703 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4704 xmlTextReaderValidityErrorRelay,
4705 xmlTextReaderValidityWarningRelay,
4706 reader);
4707 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4708 }
4709#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004710 }
4711 else {
4712 /* restore defaults */
4713 reader->ctxt->sax->error = xmlParserError;
4714 reader->ctxt->vctxt.error = xmlParserValidityError;
4715 reader->ctxt->sax->warning = xmlParserWarning;
4716 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4717 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004718 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004719 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004720#ifdef LIBXML_SCHEMAS_ENABLED
4721 if (reader->rngValidCtxt) {
4722 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4723 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4724 }
4725 if (reader->xsdValidCtxt) {
4726 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4727 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4728 }
4729#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004730 }
4731}
4732
Daniel Veillard417be3a2003-01-20 21:26:34 +00004733/**
William M. Brack93d004f2004-02-03 00:14:10 +00004734* xmlTextReaderSetStructuredErrorHandler:
4735 * @reader: the xmlTextReaderPtr used
4736 * @f: the callback function to call on error and warnings
4737 * @arg: a user argument to pass to the callback function
4738 *
4739 * Register a callback function that will be called on error and warnings.
4740 *
4741 * If @f is NULL, the default error and warning handlers are restored.
4742 */
4743void
4744xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4745 xmlStructuredErrorFunc f,
4746 void *arg) {
4747 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004748 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004749 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4750 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4751 reader->ctxt->sax->warning = xmlTextReaderWarning;
4752 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4753 reader->sErrorFunc = f;
4754 reader->errorFunc = NULL;
4755 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004756#ifdef LIBXML_SCHEMAS_ENABLED
4757 if (reader->rngValidCtxt) {
4758 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4759 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4760 xmlTextReaderValidityStructuredRelay,
4761 reader);
4762 }
4763 if (reader->xsdValidCtxt) {
4764 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4765 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4766 xmlTextReaderValidityStructuredRelay,
4767 reader);
4768 }
4769#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004770 }
4771 else {
4772 /* restore defaults */
4773 reader->ctxt->sax->error = xmlParserError;
4774 reader->ctxt->sax->serror = NULL;
4775 reader->ctxt->vctxt.error = xmlParserValidityError;
4776 reader->ctxt->sax->warning = xmlParserWarning;
4777 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4778 reader->errorFunc = NULL;
4779 reader->sErrorFunc = NULL;
4780 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004781#ifdef LIBXML_SCHEMAS_ENABLED
4782 if (reader->rngValidCtxt) {
4783 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4784 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4785 }
4786 if (reader->xsdValidCtxt) {
4787 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4788 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4789 }
4790#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004791 }
4792}
4793
4794/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004795 * xmlTextReaderIsValid:
4796 * @reader: the xmlTextReaderPtr used
4797 *
4798 * Retrieve the validity status from the parser context
4799 *
4800 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4801 */
4802int
4803xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004804 if (reader == NULL) return(-1);
4805#ifdef LIBXML_SCHEMAS_ENABLED
4806 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4807 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004808 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4809 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004810#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004811 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004812 return(reader->ctxt->valid);
4813 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004814}
4815
4816/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004817 * xmlTextReaderGetErrorHandler:
4818 * @reader: the xmlTextReaderPtr used
4819 * @f: the callback function or NULL is no callback has been registered
4820 * @arg: a user argument
4821 *
4822 * Retrieve the error callback function and user argument.
4823 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004824void
4825xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4826 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004827 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004828 if (f != NULL) *f = reader->errorFunc;
4829 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004830}
4831
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004832
4833/************************************************************************
4834 * *
4835 * New set (2.6.0) of simpler and more flexible APIs *
4836 * *
4837 ************************************************************************/
4838
4839/**
4840 * xmlTextReaderSetup:
4841 * @reader: an XML reader
4842 * @URL: the base URL to use for the document
4843 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004844 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004845 * @reuse: keep the context for reuse
4846 *
4847 * Setup an XML reader with new options
4848 *
4849 * Returns 0 in case of success and -1 in case of error.
4850 */
4851static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004852xmlTextReaderSetup(xmlTextReaderPtr reader,
4853 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004854 const char *encoding, int options)
4855{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004856 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004857 return (-1);
4858
Daniel Veillard8874b942005-08-25 13:19:21 +00004859 /*
4860 * we force the generation of compact text nodes on the reader
4861 * since usr applications should never modify the tree
4862 */
4863 options |= XML_PARSE_COMPACT;
4864
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004865 reader->doc = NULL;
4866 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004867 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004868 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004869 if ((input != NULL) && (reader->input != NULL) &&
4870 (reader->allocs & XML_TEXTREADER_INPUT)) {
4871 xmlFreeParserInputBuffer(reader->input);
4872 reader->input = NULL;
4873 reader->allocs -= XML_TEXTREADER_INPUT;
4874 }
4875 if (input != NULL) {
4876 reader->input = input;
4877 reader->allocs |= XML_TEXTREADER_INPUT;
4878 }
4879 if (reader->buffer == NULL)
4880 reader->buffer = xmlBufferCreateSize(100);
4881 if (reader->buffer == NULL) {
4882 xmlGenericError(xmlGenericErrorContext,
4883 "xmlTextReaderSetup : malloc failed\n");
4884 return (-1);
4885 }
4886 if (reader->sax == NULL)
4887 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4888 if (reader->sax == NULL) {
4889 xmlGenericError(xmlGenericErrorContext,
4890 "xmlTextReaderSetup : malloc failed\n");
4891 return (-1);
4892 }
4893 xmlSAXVersion(reader->sax, 2);
4894 reader->startElement = reader->sax->startElement;
4895 reader->sax->startElement = xmlTextReaderStartElement;
4896 reader->endElement = reader->sax->endElement;
4897 reader->sax->endElement = xmlTextReaderEndElement;
4898#ifdef LIBXML_SAX1_ENABLED
4899 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4900#endif /* LIBXML_SAX1_ENABLED */
4901 reader->startElementNs = reader->sax->startElementNs;
4902 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4903 reader->endElementNs = reader->sax->endElementNs;
4904 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4905#ifdef LIBXML_SAX1_ENABLED
4906 } else {
4907 reader->startElementNs = NULL;
4908 reader->endElementNs = NULL;
4909 }
4910#endif /* LIBXML_SAX1_ENABLED */
4911 reader->characters = reader->sax->characters;
4912 reader->sax->characters = xmlTextReaderCharacters;
4913 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4914 reader->cdataBlock = reader->sax->cdataBlock;
4915 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4916
4917 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4918 reader->node = NULL;
4919 reader->curnode = NULL;
4920 if (input != NULL) {
4921 if (reader->input->buffer->use < 4) {
4922 xmlParserInputBufferRead(input, 4);
4923 }
4924 if (reader->ctxt == NULL) {
4925 if (reader->input->buffer->use >= 4) {
4926 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4927 (const char *) reader->input->buffer->content, 4, URL);
4928 reader->base = 0;
4929 reader->cur = 4;
4930 } else {
4931 reader->ctxt =
4932 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4933 reader->base = 0;
4934 reader->cur = 0;
4935 }
4936 } else {
4937 xmlParserInputPtr inputStream;
4938 xmlParserInputBufferPtr buf;
4939 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4940
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004941 xmlCtxtReset(reader->ctxt);
4942 buf = xmlAllocParserInputBuffer(enc);
4943 if (buf == NULL) return(-1);
4944 inputStream = xmlNewInputStream(reader->ctxt);
4945 if (inputStream == NULL) {
4946 xmlFreeParserInputBuffer(buf);
4947 return(-1);
4948 }
4949
4950 if (URL == NULL)
4951 inputStream->filename = NULL;
4952 else
4953 inputStream->filename = (char *)
4954 xmlCanonicPath((const xmlChar *) URL);
4955 inputStream->buf = buf;
4956 inputStream->base = inputStream->buf->buffer->content;
4957 inputStream->cur = inputStream->buf->buffer->content;
4958 inputStream->end =
4959 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4960
4961 inputPush(reader->ctxt, inputStream);
4962 reader->cur = 0;
4963 }
4964 if (reader->ctxt == NULL) {
4965 xmlGenericError(xmlGenericErrorContext,
4966 "xmlTextReaderSetup : malloc failed\n");
4967 return (-1);
4968 }
4969 }
4970 if (reader->dict != NULL) {
4971 if (reader->ctxt->dict != NULL) {
4972 if (reader->dict != reader->ctxt->dict) {
4973 xmlDictFree(reader->dict);
4974 reader->dict = reader->ctxt->dict;
4975 }
4976 } else {
4977 reader->ctxt->dict = reader->dict;
4978 }
4979 } else {
4980 if (reader->ctxt->dict == NULL)
4981 reader->ctxt->dict = xmlDictCreate();
4982 reader->dict = reader->ctxt->dict;
4983 }
4984 reader->ctxt->_private = reader;
4985 reader->ctxt->linenumbers = 1;
4986 reader->ctxt->dictNames = 1;
4987 /*
4988 * use the parser dictionnary to allocate all elements and attributes names
4989 */
4990 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004991 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004992
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004993#ifdef LIBXML_XINCLUDE_ENABLED
4994 if (reader->xincctxt != NULL) {
4995 xmlXIncludeFreeContext(reader->xincctxt);
4996 reader->xincctxt = NULL;
4997 }
4998 if (options & XML_PARSE_XINCLUDE) {
4999 reader->xinclude = 1;
5000 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5001 options -= XML_PARSE_XINCLUDE;
5002 } else
5003 reader->xinclude = 0;
5004 reader->in_xinclude = 0;
5005#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005006#ifdef LIBXML_PATTERN_ENABLED
5007 if (reader->patternTab == NULL) {
5008 reader->patternNr = 0;
5009 reader->patternMax = 0;
5010 }
5011 while (reader->patternNr > 0) {
5012 reader->patternNr--;
5013 if (reader->patternTab[reader->patternNr] != NULL) {
5014 xmlFreePattern(reader->patternTab[reader->patternNr]);
5015 reader->patternTab[reader->patternNr] = NULL;
5016 }
5017 }
5018#endif
5019
Daniel Veillardc36965d2003-12-02 10:28:48 +00005020 if (options & XML_PARSE_DTDVALID)
5021 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5022
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005023 xmlCtxtUseOptions(reader->ctxt, options);
5024 if (encoding != NULL) {
5025 xmlCharEncodingHandlerPtr hdlr;
5026
5027 hdlr = xmlFindCharEncodingHandler(encoding);
5028 if (hdlr != NULL)
5029 xmlSwitchToEncoding(reader->ctxt, hdlr);
5030 }
5031 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5032 (reader->ctxt->input->filename == NULL))
5033 reader->ctxt->input->filename = (char *)
5034 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005035
5036 reader->doc = NULL;
5037
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005038 return (0);
5039}
5040
5041/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005042 * xmlTextReaderByteConsumed:
5043 * @reader: an XML reader
5044 *
5045 * This function provides the current index of the parser used
5046 * by the reader, relative to the start of the current entity.
5047 * This function actually just wraps a call to xmlBytesConsumed()
5048 * for the parser context associated with the reader.
5049 * See xmlBytesConsumed() for more information.
5050 *
5051 * Returns the index in bytes from the beginning of the entity or -1
5052 * in case the index could not be computed.
5053 */
5054long
5055xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5056 if ((reader == NULL) || (reader->ctxt == NULL))
5057 return(-1);
5058 return(xmlByteConsumed(reader->ctxt));
5059}
5060
5061
5062/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005063 * xmlReaderWalker:
5064 * @doc: a preparsed document
5065 *
5066 * Create an xmltextReader for a preparsed document.
5067 *
5068 * Returns the new reader or NULL in case of error.
5069 */
5070xmlTextReaderPtr
5071xmlReaderWalker(xmlDocPtr doc)
5072{
5073 xmlTextReaderPtr ret;
5074
5075 if (doc == NULL)
5076 return(NULL);
5077
5078 ret = xmlMalloc(sizeof(xmlTextReader));
5079 if (ret == NULL) {
5080 xmlGenericError(xmlGenericErrorContext,
5081 "xmlNewTextReader : malloc failed\n");
5082 return(NULL);
5083 }
5084 memset(ret, 0, sizeof(xmlTextReader));
5085 ret->entNr = 0;
5086 ret->input = NULL;
5087 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5088 ret->node = NULL;
5089 ret->curnode = NULL;
5090 ret->base = 0;
5091 ret->cur = 0;
5092 ret->allocs = XML_TEXTREADER_CTXT;
5093 ret->doc = doc;
5094 ret->state = XML_TEXTREADER_START;
5095 ret->dict = xmlDictCreate();
5096 return(ret);
5097}
5098
5099/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005100 * xmlReaderForDoc:
5101 * @cur: a pointer to a zero terminated string
5102 * @URL: the base URL to use for the document
5103 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005104 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005105 *
5106 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005107 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005108 *
5109 * Returns the new reader or NULL in case of error.
5110 */
5111xmlTextReaderPtr
5112xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5113 int options)
5114{
5115 int len;
5116
5117 if (cur == NULL)
5118 return (NULL);
5119 len = xmlStrlen(cur);
5120
5121 return (xmlReaderForMemory
5122 ((const char *) cur, len, URL, encoding, options));
5123}
5124
5125/**
5126 * xmlReaderForFile:
5127 * @filename: a file or URL
5128 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005129 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005130 *
5131 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005132 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005133 *
5134 * Returns the new reader or NULL in case of error.
5135 */
5136xmlTextReaderPtr
5137xmlReaderForFile(const char *filename, const char *encoding, int options)
5138{
5139 xmlTextReaderPtr reader;
5140
5141 reader = xmlNewTextReaderFilename(filename);
5142 if (reader == NULL)
5143 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005144 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005145 return (reader);
5146}
5147
5148/**
5149 * xmlReaderForMemory:
5150 * @buffer: a pointer to a char array
5151 * @size: the size of the array
5152 * @URL: the base URL to use for the document
5153 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005154 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005155 *
5156 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005157 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005158 *
5159 * Returns the new reader or NULL in case of error.
5160 */
5161xmlTextReaderPtr
5162xmlReaderForMemory(const char *buffer, int size, const char *URL,
5163 const char *encoding, int options)
5164{
5165 xmlTextReaderPtr reader;
5166 xmlParserInputBufferPtr buf;
5167
Daniel Veillard21924522004-02-19 16:37:07 +00005168 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005169 XML_CHAR_ENCODING_NONE);
5170 if (buf == NULL) {
5171 return (NULL);
5172 }
5173 reader = xmlNewTextReader(buf, URL);
5174 if (reader == NULL) {
5175 xmlFreeParserInputBuffer(buf);
5176 return (NULL);
5177 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005178 reader->allocs |= XML_TEXTREADER_INPUT;
5179 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005180 return (reader);
5181}
5182
5183/**
5184 * xmlReaderForFd:
5185 * @fd: an open file descriptor
5186 * @URL: the base URL to use for the document
5187 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005188 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005189 *
5190 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005191 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005192 * NOTE that the file descriptor will not be closed when the
5193 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005194 *
5195 * Returns the new reader or NULL in case of error.
5196 */
5197xmlTextReaderPtr
5198xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5199{
5200 xmlTextReaderPtr reader;
5201 xmlParserInputBufferPtr input;
5202
5203 if (fd < 0)
5204 return (NULL);
5205
5206 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5207 if (input == NULL)
5208 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005209 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005210 reader = xmlNewTextReader(input, URL);
5211 if (reader == NULL) {
5212 xmlFreeParserInputBuffer(input);
5213 return (NULL);
5214 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005215 reader->allocs |= XML_TEXTREADER_INPUT;
5216 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005217 return (reader);
5218}
5219
5220/**
5221 * xmlReaderForIO:
5222 * @ioread: an I/O read function
5223 * @ioclose: an I/O close function
5224 * @ioctx: an I/O handler
5225 * @URL: the base URL to use for the document
5226 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005227 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005228 *
5229 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005230 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005231 *
5232 * Returns the new reader or NULL in case of error.
5233 */
5234xmlTextReaderPtr
5235xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5236 void *ioctx, const char *URL, const char *encoding,
5237 int options)
5238{
5239 xmlTextReaderPtr reader;
5240 xmlParserInputBufferPtr input;
5241
5242 if (ioread == NULL)
5243 return (NULL);
5244
5245 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5246 XML_CHAR_ENCODING_NONE);
5247 if (input == NULL)
5248 return (NULL);
5249 reader = xmlNewTextReader(input, URL);
5250 if (reader == NULL) {
5251 xmlFreeParserInputBuffer(input);
5252 return (NULL);
5253 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005254 reader->allocs |= XML_TEXTREADER_INPUT;
5255 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005256 return (reader);
5257}
5258
5259/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005260 * xmlReaderNewWalker:
5261 * @reader: an XML reader
5262 * @doc: a preparsed document
5263 *
5264 * Setup an xmltextReader to parse a preparsed XML document.
5265 * This reuses the existing @reader xmlTextReader.
5266 *
5267 * Returns 0 in case of success and -1 in case of error
5268 */
5269int
5270xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5271{
5272 if (doc == NULL)
5273 return (-1);
5274 if (reader == NULL)
5275 return (-1);
5276
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005277 if (reader->input != NULL) {
5278 xmlFreeParserInputBuffer(reader->input);
5279 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005280 if (reader->ctxt != NULL) {
5281 xmlCtxtReset(reader->ctxt);
5282 }
5283
5284 reader->entNr = 0;
5285 reader->input = NULL;
5286 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5287 reader->node = NULL;
5288 reader->curnode = NULL;
5289 reader->base = 0;
5290 reader->cur = 0;
5291 reader->allocs = XML_TEXTREADER_CTXT;
5292 reader->doc = doc;
5293 reader->state = XML_TEXTREADER_START;
5294 if (reader->dict == NULL) {
5295 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5296 reader->dict = reader->ctxt->dict;
5297 else
5298 reader->dict = xmlDictCreate();
5299 }
5300 return(0);
5301}
5302
5303/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005304 * xmlReaderNewDoc:
5305 * @reader: an XML reader
5306 * @cur: a pointer to a zero terminated string
5307 * @URL: the base URL to use for the document
5308 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005309 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005310 *
5311 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005312 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005313 * This reuses the existing @reader xmlTextReader.
5314 *
5315 * Returns 0 in case of success and -1 in case of error
5316 */
5317int
5318xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5319 const char *URL, const char *encoding, int options)
5320{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005321
5322 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005323
5324 if (cur == NULL)
5325 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005326 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005327 return (-1);
5328
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005329 len = xmlStrlen(cur);
5330 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5331 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005332}
5333
5334/**
5335 * xmlReaderNewFile:
5336 * @reader: an XML reader
5337 * @filename: a file or URL
5338 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005339 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005340 *
5341 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005342 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005343 * This reuses the existing @reader xmlTextReader.
5344 *
5345 * Returns 0 in case of success and -1 in case of error
5346 */
5347int
5348xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5349 const char *encoding, int options)
5350{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005351 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005352
5353 if (filename == NULL)
5354 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005355 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005356 return (-1);
5357
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005358 input =
5359 xmlParserInputBufferCreateFilename(filename,
5360 XML_CHAR_ENCODING_NONE);
5361 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005362 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005363 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005364}
5365
5366/**
5367 * xmlReaderNewMemory:
5368 * @reader: an XML reader
5369 * @buffer: a pointer to a char array
5370 * @size: the size of the array
5371 * @URL: the base URL to use for the document
5372 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005373 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005374 *
5375 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005376 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005377 * This reuses the existing @reader xmlTextReader.
5378 *
5379 * Returns 0 in case of success and -1 in case of error
5380 */
5381int
5382xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5383 const char *URL, const char *encoding, int options)
5384{
5385 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005386
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005387 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005388 return (-1);
5389 if (buffer == NULL)
5390 return (-1);
5391
Daniel Veillard21924522004-02-19 16:37:07 +00005392 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005393 XML_CHAR_ENCODING_NONE);
5394 if (input == NULL) {
5395 return (-1);
5396 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005397 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005398}
5399
5400/**
5401 * xmlReaderNewFd:
5402 * @reader: an XML reader
5403 * @fd: an open file descriptor
5404 * @URL: the base URL to use for the document
5405 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005406 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005407 *
5408 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005409 * NOTE that the file descriptor will not be closed when the
5410 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005411 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005412 * This reuses the existing @reader xmlTextReader.
5413 *
5414 * Returns 0 in case of success and -1 in case of error
5415 */
5416int
5417xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5418 const char *URL, const char *encoding, int options)
5419{
5420 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005421
5422 if (fd < 0)
5423 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005424 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005425 return (-1);
5426
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005427 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5428 if (input == NULL)
5429 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005430 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005431 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005432}
5433
5434/**
5435 * xmlReaderNewIO:
5436 * @reader: an XML reader
5437 * @ioread: an I/O read function
5438 * @ioclose: an I/O close function
5439 * @ioctx: an I/O handler
5440 * @URL: the base URL to use for the document
5441 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005442 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005443 *
5444 * Setup an xmltextReader to parse an XML document from I/O functions
5445 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005446 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005447 * This reuses the existing @reader xmlTextReader.
5448 *
5449 * Returns 0 in case of success and -1 in case of error
5450 */
5451int
5452xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5453 xmlInputCloseCallback ioclose, void *ioctx,
5454 const char *URL, const char *encoding, int options)
5455{
5456 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005457
5458 if (ioread == NULL)
5459 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005460 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005461 return (-1);
5462
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005463 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5464 XML_CHAR_ENCODING_NONE);
5465 if (input == NULL)
5466 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005467 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005468}
Daniel Veillard26f70262003-01-16 22:45:08 +00005469/************************************************************************
5470 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005471 * Utilities *
5472 * *
5473 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005474#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005475/**
5476 * xmlBase64Decode:
5477 * @in: the input buffer
5478 * @inlen: the size of the input (in), the size read from it (out)
5479 * @to: the output buffer
5480 * @tolen: the size of the output (in), the size written to (out)
5481 *
5482 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005483 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005484 *
5485 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5486 * 2 if there wasn't enough space on the output or -1 in case of error.
5487 */
5488static int
5489xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5490 unsigned char *to, unsigned long *tolen) {
5491 unsigned long incur; /* current index in in[] */
5492 unsigned long inblk; /* last block index in in[] */
5493 unsigned long outcur; /* current index in out[] */
5494 unsigned long inmax; /* size of in[] */
5495 unsigned long outmax; /* size of out[] */
5496 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005497 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005498 int nbintmp; /* number of byte in intmp[] */
5499 int is_ignore; /* cur should be ignored */
5500 int is_end = 0; /* the end of the base64 was found */
5501 int retval = 1;
5502 int i;
5503
5504 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5505 return(-1);
5506
5507 incur = 0;
5508 inblk = 0;
5509 outcur = 0;
5510 inmax = *inlen;
5511 outmax = *tolen;
5512 nbintmp = 0;
5513
5514 while (1) {
5515 if (incur >= inmax)
5516 break;
5517 cur = in[incur++];
5518 is_ignore = 0;
5519 if ((cur >= 'A') && (cur <= 'Z'))
5520 cur = cur - 'A';
5521 else if ((cur >= 'a') && (cur <= 'z'))
5522 cur = cur - 'a' + 26;
5523 else if ((cur >= '0') && (cur <= '9'))
5524 cur = cur - '0' + 52;
5525 else if (cur == '+')
5526 cur = 62;
5527 else if (cur == '/')
5528 cur = 63;
5529 else if (cur == '.')
5530 cur = 0;
5531 else if (cur == '=') /*no op , end of the base64 stream */
5532 is_end = 1;
5533 else {
5534 is_ignore = 1;
5535 if (nbintmp == 0)
5536 inblk = incur;
5537 }
5538
5539 if (!is_ignore) {
5540 int nbouttmp = 3;
5541 int is_break = 0;
5542
5543 if (is_end) {
5544 if (nbintmp == 0)
5545 break;
5546 if ((nbintmp == 1) || (nbintmp == 2))
5547 nbouttmp = 1;
5548 else
5549 nbouttmp = 2;
5550 nbintmp = 3;
5551 is_break = 1;
5552 }
5553 intmp[nbintmp++] = cur;
5554 /*
5555 * if intmp is full, push the 4byte sequence as a 3 byte
5556 * sequence out
5557 */
5558 if (nbintmp == 4) {
5559 nbintmp = 0;
5560 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5561 outtmp[1] =
5562 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5563 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5564 if (outcur + 3 >= outmax) {
5565 retval = 2;
5566 break;
5567 }
5568
5569 for (i = 0; i < nbouttmp; i++)
5570 to[outcur++] = outtmp[i];
5571 inblk = incur;
5572 }
5573
5574 if (is_break) {
5575 retval = 0;
5576 break;
5577 }
5578 }
5579 }
5580
5581 *tolen = outcur;
5582 *inlen = inblk;
5583 return (retval);
5584}
5585
5586/*
5587 * Test routine for the xmlBase64Decode function
5588 */
5589#if 0
5590int main(int argc, char **argv) {
5591 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5592 char output[100];
5593 char output2[100];
5594 char output3[100];
5595 unsigned long inlen = strlen(input);
5596 unsigned long outlen = 100;
5597 int ret;
5598 unsigned long cons, tmp, tmp2, prod;
5599
5600 /*
5601 * Direct
5602 */
5603 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5604
5605 output[outlen] = 0;
5606 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5607
5608 /*
5609 * output chunking
5610 */
5611 cons = 0;
5612 prod = 0;
5613 while (cons < inlen) {
5614 tmp = 5;
5615 tmp2 = inlen - cons;
5616
5617 printf("%ld %ld\n", cons, prod);
5618 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5619 cons += tmp2;
5620 prod += tmp;
5621 printf("%ld %ld\n", cons, prod);
5622 }
5623 output2[outlen] = 0;
5624 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5625
5626 /*
5627 * input chunking
5628 */
5629 cons = 0;
5630 prod = 0;
5631 while (cons < inlen) {
5632 tmp = 100 - prod;
5633 tmp2 = inlen - cons;
5634 if (tmp2 > 5)
5635 tmp2 = 5;
5636
5637 printf("%ld %ld\n", cons, prod);
5638 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5639 cons += tmp2;
5640 prod += tmp;
5641 printf("%ld %ld\n", cons, prod);
5642 }
5643 output3[outlen] = 0;
5644 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5645 return(0);
5646
5647}
5648#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005649#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005650#define bottom_xmlreader
5651#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005652#endif /* LIBXML_READER_ENABLED */