blob: 14843eb8abd0cc8a701092312719aaecb7e66d5d [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 */
134 int rngValidErrors;/* The number of errors detected */
135 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 */
139 int xsdValidErrors;/* The number of errors detected */
140 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000141#endif
142#ifdef LIBXML_XINCLUDE_ENABLED
143 /* Handling of XInclude processing */
144 int xinclude; /* is xinclude asked for */
145 const xmlChar * xinclude_name; /* the xinclude name from dict */
146 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
147 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000148#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000149#ifdef LIBXML_PATTERN_ENABLED
150 int patternNr; /* number of preserve patterns */
151 int patternMax; /* max preserve patterns */
152 xmlPatternPtr *patternTab; /* array of preserve patterns */
153#endif
154 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000155 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000156 /* Structured error handling */
157 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000158};
159
Daniel Veillarde8039df2003-10-27 11:25:13 +0000160#define NODE_IS_EMPTY 0x1
161#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000162#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000163
Daniel Veillarde72c5082003-09-19 12:44:05 +0000164/**
165 * CONSTSTR:
166 *
167 * Macro used to return an interned string
168 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000169#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
170#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
171
172static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
173static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000174
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000175/************************************************************************
176 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000177 * Our own version of the freeing routines as we recycle nodes *
178 * *
179 ************************************************************************/
180/**
181 * DICT_FREE:
182 * @str: a string
183 *
184 * Free a string if it is not owned by the "dict" dictionnary in the
185 * current scope
186 */
187#define DICT_FREE(str) \
188 if ((str) && ((!dict) || \
189 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
190 xmlFree((char *)(str));
191
192static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
193static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
194
195/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000196 * xmlFreeID:
197 * @not: A id
198 *
199 * Deallocate the memory used by an id definition
200 */
201static void
202xmlFreeID(xmlIDPtr id) {
203 xmlDictPtr dict = NULL;
204
205 if (id == NULL) return;
206
207 if (id->doc != NULL)
208 dict = id->doc->dict;
209
210 if (id->value != NULL)
211 DICT_FREE(id->value)
212 xmlFree(id);
213}
214
215/**
216 * xmlTextReaderRemoveID:
217 * @doc: the document
218 * @attr: the attribute
219 *
220 * Remove the given attribute from the ID table maintained internally.
221 *
222 * Returns -1 if the lookup failed and 0 otherwise
223 */
224static int
225xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
226 xmlIDTablePtr table;
227 xmlIDPtr id;
228 xmlChar *ID;
229
230 if (doc == NULL) return(-1);
231 if (attr == NULL) return(-1);
232 table = (xmlIDTablePtr) doc->ids;
233 if (table == NULL)
234 return(-1);
235
236 if (attr == NULL)
237 return(-1);
238 ID = xmlNodeListGetString(doc, attr->children, 1);
239 if (ID == NULL)
240 return(-1);
241 id = xmlHashLookup(table, ID);
242 xmlFree(ID);
243 if (id == NULL || id->attr != attr) {
244 return(-1);
245 }
246 id->name = attr->name;
247 id->attr = NULL;
248 return(0);
249}
250
251/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000252 * xmlTextReaderFreeProp:
253 * @reader: the xmlTextReaderPtr used
254 * @cur: the node
255 *
256 * Free a node.
257 */
258static void
259xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
260 xmlDictPtr dict;
261
262 dict = reader->ctxt->dict;
263 if (cur == NULL) return;
264
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000265 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
266 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
267
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000268 /* Check for ID removal -> leading to invalid references ! */
269 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
270 ((cur->parent->doc->intSubset != NULL) ||
271 (cur->parent->doc->extSubset != NULL))) {
272 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000273 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000274 }
275 if (cur->children != NULL)
276 xmlTextReaderFreeNodeList(reader, cur->children);
277
278 DICT_FREE(cur->name);
279 if ((reader != NULL) && (reader->ctxt != NULL) &&
280 (reader->ctxt->freeAttrsNr < 100)) {
281 cur->next = reader->ctxt->freeAttrs;
282 reader->ctxt->freeAttrs = cur;
283 reader->ctxt->freeAttrsNr++;
284 } else {
285 xmlFree(cur);
286 }
287}
288
289/**
290 * xmlTextReaderFreePropList:
291 * @reader: the xmlTextReaderPtr used
292 * @cur: the first property in the list
293 *
294 * Free a property and all its siblings, all the children are freed too.
295 */
296static void
297xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
298 xmlAttrPtr next;
299 if (cur == NULL) return;
300 while (cur != NULL) {
301 next = cur->next;
302 xmlTextReaderFreeProp(reader, cur);
303 cur = next;
304 }
305}
306
307/**
308 * xmlTextReaderFreeNodeList:
309 * @reader: the xmlTextReaderPtr used
310 * @cur: the first node in the list
311 *
312 * Free a node and all its siblings, this is a recursive behaviour, all
313 * the children are freed too.
314 */
315static void
316xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
317 xmlNodePtr next;
318 xmlDictPtr dict;
319
320 dict = reader->ctxt->dict;
321 if (cur == NULL) return;
322 if (cur->type == XML_NAMESPACE_DECL) {
323 xmlFreeNsList((xmlNsPtr) cur);
324 return;
325 }
326 if ((cur->type == XML_DOCUMENT_NODE) ||
327 (cur->type == XML_HTML_DOCUMENT_NODE)) {
328 xmlFreeDoc((xmlDocPtr) cur);
329 return;
330 }
331 while (cur != NULL) {
332 next = cur->next;
333 /* unroll to speed up freeing the document */
334 if (cur->type != XML_DTD_NODE) {
335
336 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000337 (cur->type != XML_ENTITY_REF_NODE)) {
338 if (cur->children->parent == cur)
339 xmlTextReaderFreeNodeList(reader, cur->children);
340 cur->children = NULL;
341 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000342
343 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
344 xmlDeregisterNodeDefaultValue(cur);
345
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000346 if (((cur->type == XML_ELEMENT_NODE) ||
347 (cur->type == XML_XINCLUDE_START) ||
348 (cur->type == XML_XINCLUDE_END)) &&
349 (cur->properties != NULL))
350 xmlTextReaderFreePropList(reader, cur->properties);
351 if ((cur->type != XML_ELEMENT_NODE) &&
352 (cur->type != XML_XINCLUDE_START) &&
353 (cur->type != XML_XINCLUDE_END) &&
354 (cur->type != XML_ENTITY_REF_NODE)) {
355 DICT_FREE(cur->content);
356 }
357 if (((cur->type == XML_ELEMENT_NODE) ||
358 (cur->type == XML_XINCLUDE_START) ||
359 (cur->type == XML_XINCLUDE_END)) &&
360 (cur->nsDef != NULL))
361 xmlFreeNsList(cur->nsDef);
362
363 /*
364 * we don't free element names here they are interned now
365 */
366 if ((cur->type != XML_TEXT_NODE) &&
367 (cur->type != XML_COMMENT_NODE))
368 DICT_FREE(cur->name);
369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_TEXT_NODE)) &&
371 (reader != NULL) && (reader->ctxt != NULL) &&
372 (reader->ctxt->freeElemsNr < 100)) {
373 cur->next = reader->ctxt->freeElems;
374 reader->ctxt->freeElems = cur;
375 reader->ctxt->freeElemsNr++;
376 } else {
377 xmlFree(cur);
378 }
379 }
380 cur = next;
381 }
382}
383
384/**
385 * xmlTextReaderFreeNode:
386 * @reader: the xmlTextReaderPtr used
387 * @cur: the node
388 *
389 * Free a node, this is a recursive behaviour, all the children are freed too.
390 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
391 */
392static void
393xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
394 xmlDictPtr dict;
395
396 dict = reader->ctxt->dict;
397 if (cur->type == XML_DTD_NODE) {
398 xmlFreeDtd((xmlDtdPtr) cur);
399 return;
400 }
401 if (cur->type == XML_NAMESPACE_DECL) {
402 xmlFreeNs((xmlNsPtr) cur);
403 return;
404 }
405 if (cur->type == XML_ATTRIBUTE_NODE) {
406 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
407 return;
408 }
409
410 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000411 (cur->type != XML_ENTITY_REF_NODE)) {
412 if (cur->children->parent == cur)
413 xmlTextReaderFreeNodeList(reader, cur->children);
414 cur->children = NULL;
415 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000416
417 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
418 xmlDeregisterNodeDefaultValue(cur);
419
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000420 if (((cur->type == XML_ELEMENT_NODE) ||
421 (cur->type == XML_XINCLUDE_START) ||
422 (cur->type == XML_XINCLUDE_END)) &&
423 (cur->properties != NULL))
424 xmlTextReaderFreePropList(reader, cur->properties);
425 if ((cur->type != XML_ELEMENT_NODE) &&
426 (cur->type != XML_XINCLUDE_START) &&
427 (cur->type != XML_XINCLUDE_END) &&
428 (cur->type != XML_ENTITY_REF_NODE)) {
429 DICT_FREE(cur->content);
430 }
431 if (((cur->type == XML_ELEMENT_NODE) ||
432 (cur->type == XML_XINCLUDE_START) ||
433 (cur->type == XML_XINCLUDE_END)) &&
434 (cur->nsDef != NULL))
435 xmlFreeNsList(cur->nsDef);
436
437 /*
438 * we don't free names here they are interned now
439 */
440 if ((cur->type != XML_TEXT_NODE) &&
441 (cur->type != XML_COMMENT_NODE))
442 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000443
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000444 if (((cur->type == XML_ELEMENT_NODE) ||
445 (cur->type == XML_TEXT_NODE)) &&
446 (reader != NULL) && (reader->ctxt != NULL) &&
447 (reader->ctxt->freeElemsNr < 100)) {
448 cur->next = reader->ctxt->freeElems;
449 reader->ctxt->freeElems = cur;
450 reader->ctxt->freeElemsNr++;
451 } else {
452 xmlFree(cur);
453 }
454}
455
456/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000457 * xmlTextReaderFreeIDTable:
458 * @table: An id table
459 *
460 * Deallocate the memory used by an ID hash table.
461 */
William M. Brack60f394e2003-11-16 06:25:42 +0000462static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000463xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
464 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
465}
466
467/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000468 * xmlTextReaderFreeDoc:
469 * @reader: the xmlTextReaderPtr used
470 * @cur: pointer to the document
471 *
472 * Free up all the structures used by a document, tree included.
473 */
474static void
475xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
476 xmlDtdPtr extSubset, intSubset;
477
478 if (cur == NULL) return;
479
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000480 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
481 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
482
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000483 /*
484 * Do this before freeing the children list to avoid ID lookups
485 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000486 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000487 cur->ids = NULL;
488 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
489 cur->refs = NULL;
490 extSubset = cur->extSubset;
491 intSubset = cur->intSubset;
492 if (intSubset == extSubset)
493 extSubset = NULL;
494 if (extSubset != NULL) {
495 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
496 cur->extSubset = NULL;
497 xmlFreeDtd(extSubset);
498 }
499 if (intSubset != NULL) {
500 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
501 cur->intSubset = NULL;
502 xmlFreeDtd(intSubset);
503 }
504
505 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
506
507 if (cur->version != NULL) xmlFree((char *) cur->version);
508 if (cur->name != NULL) xmlFree((char *) cur->name);
509 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
510 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
511 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000512 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000513
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000514 xmlFree(cur);
515}
516
517/************************************************************************
518 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000519 * The reader core parser *
520 * *
521 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000522#ifdef DEBUG_READER
523static void
524xmlTextReaderDebug(xmlTextReaderPtr reader) {
525 if ((reader == NULL) || (reader->ctxt == NULL)) {
526 fprintf(stderr, "xmlTextReader NULL\n");
527 return;
528 }
529 fprintf(stderr, "xmlTextReader: state %d depth %d ",
530 reader->state, reader->depth);
531 if (reader->node == NULL) {
532 fprintf(stderr, "node = NULL\n");
533 } else {
534 fprintf(stderr, "node %s\n", reader->node->name);
535 }
536 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
537 reader->base, reader->cur, reader->ctxt->nodeNr);
538 if (reader->input->buffer == NULL) {
539 fprintf(stderr, "buffer is NULL\n");
540 } else {
541#ifdef LIBXML_DEBUG_ENABLED
542 xmlDebugDumpString(stderr,
543 &reader->input->buffer->content[reader->cur]);
544#endif
545 fprintf(stderr, "\n");
546 }
547}
548#endif
549
550/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000551 * xmlTextReaderEntPush:
552 * @reader: the xmlTextReaderPtr used
553 * @value: the entity reference node
554 *
555 * Pushes a new entity reference node on top of the entities stack
556 *
557 * Returns 0 in case of error, the index in the stack otherwise
558 */
559static int
560xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
561{
562 if (reader->entMax <= 0) {
563 reader->entMax = 10;
564 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
565 sizeof(reader->entTab[0]));
566 if (reader->entTab == NULL) {
567 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
568 return (0);
569 }
570 }
571 if (reader->entNr >= reader->entMax) {
572 reader->entMax *= 2;
573 reader->entTab =
574 (xmlNodePtr *) xmlRealloc(reader->entTab,
575 reader->entMax *
576 sizeof(reader->entTab[0]));
577 if (reader->entTab == NULL) {
578 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
579 return (0);
580 }
581 }
582 reader->entTab[reader->entNr] = value;
583 reader->ent = value;
584 return (reader->entNr++);
585}
586
587/**
588 * xmlTextReaderEntPop:
589 * @reader: the xmlTextReaderPtr used
590 *
591 * Pops the top element entity from the entities stack
592 *
593 * Returns the entity just removed
594 */
595static xmlNodePtr
596xmlTextReaderEntPop(xmlTextReaderPtr reader)
597{
598 xmlNodePtr ret;
599
600 if (reader->entNr <= 0)
601 return (0);
602 reader->entNr--;
603 if (reader->entNr > 0)
604 reader->ent = reader->entTab[reader->entNr - 1];
605 else
606 reader->ent = NULL;
607 ret = reader->entTab[reader->entNr];
608 reader->entTab[reader->entNr] = 0;
609 return (ret);
610}
611
612/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000613 * xmlTextReaderStartElement:
614 * @ctx: the user data (XML parser context)
615 * @fullname: The element name, including namespace prefix
616 * @atts: An array of name/value attributes pairs, NULL terminated
617 *
618 * called when an opening tag has been processed.
619 */
620static void
621xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
622 const xmlChar **atts) {
623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
624 xmlTextReaderPtr reader = ctxt->_private;
625
626#ifdef DEBUG_CALLBACKS
627 printf("xmlTextReaderStartElement(%s)\n", fullname);
628#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000629 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000630 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000631 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
632 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
633 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000634 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000635 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000636 if (reader != NULL)
637 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000638}
639
640/**
641 * xmlTextReaderEndElement:
642 * @ctx: the user data (XML parser context)
643 * @fullname: The element name, including namespace prefix
644 *
645 * called when an ending tag has been processed.
646 */
647static void
648xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
649 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
650 xmlTextReaderPtr reader = ctxt->_private;
651
652#ifdef DEBUG_CALLBACKS
653 printf("xmlTextReaderEndElement(%s)\n", fullname);
654#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000655 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000656 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000657 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000658}
659
660/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000661 * xmlTextReaderStartElementNs:
662 * @ctx: the user data (XML parser context)
663 * @localname: the local name of the element
664 * @prefix: the element namespace prefix if available
665 * @URI: the element namespace name if available
666 * @nb_namespaces: number of namespace definitions on that node
667 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
668 * @nb_attributes: the number of attributes on that node
669 * nb_defaulted: the number of defaulted attributes.
670 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
671 * attribute values.
672 *
673 * called when an opening tag has been processed.
674 */
675static void
676xmlTextReaderStartElementNs(void *ctx,
677 const xmlChar *localname,
678 const xmlChar *prefix,
679 const xmlChar *URI,
680 int nb_namespaces,
681 const xmlChar **namespaces,
682 int nb_attributes,
683 int nb_defaulted,
684 const xmlChar **attributes)
685{
686 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
687 xmlTextReaderPtr reader = ctxt->_private;
688
689#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000690 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000691#endif
692 if ((reader != NULL) && (reader->startElementNs != NULL)) {
693 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
694 namespaces, nb_attributes, nb_defaulted,
695 attributes);
696 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
697 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
698 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000699 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000700 }
701 if (reader != NULL)
702 reader->state = XML_TEXTREADER_ELEMENT;
703}
704
705/**
706 * xmlTextReaderEndElementNs:
707 * @ctx: the user data (XML parser context)
708 * @localname: the local name of the element
709 * @prefix: the element namespace prefix if available
710 * @URI: the element namespace name if available
711 *
712 * called when an ending tag has been processed.
713 */
714static void
715xmlTextReaderEndElementNs(void *ctx,
716 const xmlChar * localname,
717 const xmlChar * prefix,
718 const xmlChar * URI)
719{
720 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
721 xmlTextReaderPtr reader = ctxt->_private;
722
723#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000724 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000725#endif
726 if ((reader != NULL) && (reader->endElementNs != NULL)) {
727 reader->endElementNs(ctx, localname, prefix, URI);
728 }
729}
730
731
732/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000733 * xmlTextReaderCharacters:
734 * @ctx: the user data (XML parser context)
735 * @ch: a xmlChar string
736 * @len: the number of xmlChar
737 *
738 * receiving some chars from the parser.
739 */
740static void
741xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
742{
743 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
744 xmlTextReaderPtr reader = ctxt->_private;
745
746#ifdef DEBUG_CALLBACKS
747 printf("xmlTextReaderCharacters()\n");
748#endif
749 if ((reader != NULL) && (reader->characters != NULL)) {
750 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000751 }
752}
753
754/**
755 * xmlTextReaderCDataBlock:
756 * @ctx: the user data (XML parser context)
757 * @value: The pcdata content
758 * @len: the block length
759 *
760 * called when a pcdata block has been parsed
761 */
762static void
763xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
764{
765 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
766 xmlTextReaderPtr reader = ctxt->_private;
767
768#ifdef DEBUG_CALLBACKS
769 printf("xmlTextReaderCDataBlock()\n");
770#endif
771 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
772 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000773 }
774}
775
776/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000777 * xmlTextReaderPushData:
778 * @reader: the xmlTextReaderPtr used
779 *
780 * Push data down the progressive parser until a significant callback
781 * got raised.
782 *
783 * Returns -1 in case of failure, 0 otherwise
784 */
785static int
786xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000787 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000788 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000789 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000790
791 if ((reader->input == NULL) || (reader->input->buffer == NULL))
792 return(-1);
793
Daniel Veillardea7751d2002-12-20 00:16:24 +0000794 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000795 reader->state = XML_TEXTREADER_NONE;
796 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000797
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000799 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000800 /*
801 * Refill the buffer unless we are at the end of the stream
802 */
803 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
804 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000805 if ((val == 0) &&
806 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
807 if (inbuf->use == reader->cur) {
808 reader->mode = XML_TEXTREADER_MODE_EOF;
809 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000810 }
811 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000812 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000813 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000814 if ((oldstate != XML_TEXTREADER_START) ||
815 (reader->ctxt->myDoc != NULL))
816 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000817 } else if (val == 0) {
818 /* mark the end of the stream and process the remains */
819 reader->mode = XML_TEXTREADER_MODE_EOF;
820 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000822
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000823 } else
824 break;
825 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000826 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000827 * parse by block of CHUNK_SIZE bytes, various tests show that
828 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000829 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000831 val = xmlParseChunk(reader->ctxt,
832 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000833 CHUNK_SIZE, 0);
834 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000835 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000836 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000837 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000838 s = inbuf->use - reader->cur;
839 val = xmlParseChunk(reader->ctxt,
840 (const char *) &inbuf->content[reader->cur],
841 s, 0);
842 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000843 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000844 return(-1);
845 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000846 }
847 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000848
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000849 /*
850 * Discard the consumed input when needed and possible
851 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000852 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000853 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
854 if ((reader->cur >= 4096) &&
855 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
856 val = xmlBufferShrink(inbuf, reader->cur);
857 if (val >= 0) {
858 reader->cur -= val;
859 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000860 }
861 }
862 }
863
864 /*
865 * At the end of the stream signal that the work is done to the Push
866 * parser.
867 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000868 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000869 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000870 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000871 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000872 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000873 s, 1);
874 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000875 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000876 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000877 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000878 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000879 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000880 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000881 return(0);
882}
883
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000884#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000885/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000886 * xmlTextReaderValidatePush:
887 * @reader: the xmlTextReaderPtr used
888 *
889 * Push the current node for validation
890 */
891static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000892xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000893 xmlNodePtr node = reader->node;
894
Daniel Veillardf54cd532004-02-25 11:52:31 +0000895#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000896 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
897 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
898 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
899 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
900 reader->ctxt->myDoc, node, node->name);
901 } else {
902 /* TODO use the BuildQName interface */
903 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000904
Daniel Veillardf4e55762003-04-15 23:32:22 +0000905 qname = xmlStrdup(node->ns->prefix);
906 qname = xmlStrcat(qname, BAD_CAST ":");
907 qname = xmlStrcat(qname, node->name);
908 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
909 reader->ctxt->myDoc, node, qname);
910 if (qname != NULL)
911 xmlFree(qname);
912 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000913 }
914#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000915#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000916 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000917 (reader->rngValidCtxt != NULL)) {
918 int ret;
919
920 if (reader->rngFullNode != NULL) return;
921 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
922 reader->ctxt->myDoc,
923 node);
924 if (ret == 0) {
925 /*
926 * this element requires a full tree
927 */
928 node = xmlTextReaderExpand(reader);
929 if (node == NULL) {
930printf("Expand failed !\n");
931 ret = -1;
932 } else {
933 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
934 reader->ctxt->myDoc,
935 node);
936 reader->rngFullNode = node;
937 }
938 }
939 if (ret != 1)
940 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000941 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000942#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000943}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000944
945/**
946 * xmlTextReaderValidateCData:
947 * @reader: the xmlTextReaderPtr used
948 * @data: pointer to the CData
949 * @len: lenght of the CData block in bytes.
950 *
951 * Push some CData for validation
952 */
953static void
954xmlTextReaderValidateCData(xmlTextReaderPtr reader,
955 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000956#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000957 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
958 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
959 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
960 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000961 }
962#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000963#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000964 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965 (reader->rngValidCtxt != NULL)) {
966 int ret;
967
968 if (reader->rngFullNode != NULL) return;
969 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
970 if (ret != 1)
971 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000972 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000973#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000974}
975
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000976/**
977 * xmlTextReaderValidatePop:
978 * @reader: the xmlTextReaderPtr used
979 *
980 * Pop the current node from validation
981 */
982static void
983xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
984 xmlNodePtr node = reader->node;
985
Daniel Veillardf54cd532004-02-25 11:52:31 +0000986#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000987 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
988 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
989 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
990 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
991 reader->ctxt->myDoc, node, node->name);
992 } else {
993 /* TODO use the BuildQName interface */
994 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000995
Daniel Veillardf4e55762003-04-15 23:32:22 +0000996 qname = xmlStrdup(node->ns->prefix);
997 qname = xmlStrcat(qname, BAD_CAST ":");
998 qname = xmlStrcat(qname, node->name);
999 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1000 reader->ctxt->myDoc, node, qname);
1001 if (qname != NULL)
1002 xmlFree(qname);
1003 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001004 }
1005#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001006#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001008 (reader->rngValidCtxt != NULL)) {
1009 int ret;
1010
1011 if (reader->rngFullNode != NULL) {
1012 if (node == reader->rngFullNode)
1013 reader->rngFullNode = NULL;
1014 return;
1015 }
1016 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1017 reader->ctxt->myDoc,
1018 node);
1019 if (ret != 1)
1020 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001021 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001022#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001023}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001024
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001025/**
1026 * xmlTextReaderValidateEntity:
1027 * @reader: the xmlTextReaderPtr used
1028 *
1029 * Handle the validation when an entity reference is encountered and
1030 * entity substitution is not activated. As a result the parser interface
1031 * must walk through the entity and do the validation calls
1032 */
1033static void
1034xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1035 xmlNodePtr oldnode = reader->node;
1036 xmlNodePtr node = reader->node;
1037 xmlParserCtxtPtr ctxt = reader->ctxt;
1038
1039 do {
1040 if (node->type == XML_ENTITY_REF_NODE) {
1041 /*
1042 * Case where the underlying tree is not availble, lookup the entity
1043 * and walk it.
1044 */
1045 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1046 (ctxt->sax->getEntity != NULL)) {
1047 node->children = (xmlNodePtr)
1048 ctxt->sax->getEntity(ctxt, node->name);
1049 }
1050
1051 if ((node->children != NULL) &&
1052 (node->children->type == XML_ENTITY_DECL) &&
1053 (node->children->children != NULL)) {
1054 xmlTextReaderEntPush(reader, node);
1055 node = node->children->children;
1056 continue;
1057 } else {
1058 /*
1059 * The error has probably be raised already.
1060 */
1061 if (node == oldnode)
1062 break;
1063 node = node->next;
1064 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001065#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001066 } else if (node->type == XML_ELEMENT_NODE) {
1067 reader->node = node;
1068 xmlTextReaderValidatePush(reader);
1069 } else if ((node->type == XML_TEXT_NODE) ||
1070 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001071 xmlTextReaderValidateCData(reader, node->content,
1072 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001073#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001074 }
1075
1076 /*
1077 * go to next node
1078 */
1079 if (node->children != NULL) {
1080 node = node->children;
1081 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001082 } else if (node->type == XML_ELEMENT_NODE) {
1083 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001084 }
1085 if (node->next != NULL) {
1086 node = node->next;
1087 continue;
1088 }
1089 do {
1090 node = node->parent;
1091 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001092 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001093 if (reader->entNr == 0) {
1094 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001095 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 xmlUnlinkNode(tmp);
1097 xmlTextReaderFreeNode(reader, tmp);
1098 } else
1099 break;
1100 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001101 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001102 reader->node = node;
1103 xmlTextReaderValidatePop(reader);
1104 }
1105 if ((node->type == XML_ENTITY_DECL) &&
1106 (reader->ent != NULL) && (reader->ent->children == node)) {
1107 node = xmlTextReaderEntPop(reader);
1108 }
1109 if (node == oldnode)
1110 break;
1111 if (node->next != NULL) {
1112 node = node->next;
1113 break;
1114 }
1115 } while ((node != NULL) && (node != oldnode));
1116 } while ((node != NULL) && (node != oldnode));
1117 reader->node = oldnode;
1118}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001119#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001120
1121
1122/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001123 * xmlTextReaderGetSuccessor:
1124 * @cur: the current node
1125 *
1126 * Get the successor of a node if available.
1127 *
1128 * Returns the successor node or NULL
1129 */
1130static xmlNodePtr
1131xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1132 if (cur == NULL) return(NULL) ; /* ERROR */
1133 if (cur->next != NULL) return(cur->next) ;
1134 do {
1135 cur = cur->parent;
1136 if (cur == NULL) return(NULL);
1137 if (cur->next != NULL) return(cur->next);
1138 } while (cur != NULL);
1139 return(cur);
1140}
1141
1142/**
1143 * xmlTextReaderDoExpand:
1144 * @reader: the xmlTextReaderPtr used
1145 *
1146 * Makes sure that the current node is fully read as well as all its
1147 * descendant. It means the full DOM subtree must be available at the
1148 * end of the call.
1149 *
1150 * Returns 1 if the node was expanded successfully, 0 if there is no more
1151 * nodes to read, or -1 in case of error
1152 */
1153static int
1154xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1155 int val;
1156
1157 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1158 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001159 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001160 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1161
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001162 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1163 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001164 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001165 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001166 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1167 return(1);
1168 val = xmlTextReaderPushData(reader);
1169 if (val < 0)
1170 return(-1);
1171 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1172 return(1);
1173}
1174
1175/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001176 * xmlTextReaderCollectSiblings:
1177 * @node: the first child
1178 *
1179 * Traverse depth-first through all sibling nodes and their children
1180 * nodes and concatenate their content. This is an auxiliary function
1181 * to xmlTextReaderReadString.
1182 *
1183 * Returns a string containing the content, or NULL in case of error.
1184 */
1185static xmlChar *
1186xmlTextReaderCollectSiblings(xmlNodePtr node)
1187{
1188 xmlBufferPtr buffer;
1189 xmlChar *ret;
1190
1191 buffer = xmlBufferCreate();
1192 if (buffer == NULL)
1193 return NULL;
1194
1195 for ( ; node != NULL; node = node->next) {
1196 switch (node->type) {
1197 case XML_TEXT_NODE:
1198 case XML_CDATA_SECTION_NODE:
1199 xmlBufferCat(buffer, node->content);
1200 break;
1201 case XML_ELEMENT_NODE:
1202 xmlBufferCat(buffer, xmlTextReaderCollectSiblings(node->children));
1203 default:
1204 break;
1205 }
1206 }
1207 ret = buffer->content;
1208 buffer->content = NULL;
1209 xmlBufferFree(buffer);
1210 return(ret);
1211}
1212
1213/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001214 * xmlTextReaderRead:
1215 * @reader: the xmlTextReaderPtr used
1216 *
1217 * Moves the position of the current instance to the next node in
1218 * the stream, exposing its properties.
1219 *
1220 * Returns 1 if the node was read successfully, 0 if there is no more
1221 * nodes to read, or -1 in case of error
1222 */
1223int
1224xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001225 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001226 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001227 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001228
William M. Brack1af55582004-07-22 17:18:00 +00001229
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001230 if (reader == NULL)
1231 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001232 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001233 if (reader->doc != NULL)
1234 return(xmlTextReaderReadTree(reader));
1235 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001236 return(-1);
1237 if (reader->ctxt->wellFormed != 1)
1238 return(-1);
1239
1240#ifdef DEBUG_READER
1241 fprintf(stderr, "\nREAD ");
1242 DUMP_READER
1243#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001244 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1245 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001246 /*
1247 * Initial state
1248 */
1249 do {
1250 val = xmlTextReaderPushData(reader);
1251 if (val < 0)
1252 return(-1);
1253 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001254 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1255 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001256 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001257 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001258 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001259 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001260 if (reader->node == NULL)
1261 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001262 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001264 if (reader->ctxt->myDoc != NULL) {
1265 reader->node = reader->ctxt->myDoc->children;
1266 }
1267 if (reader->node == NULL)
1268 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001269 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001270 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001271 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001272 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001273 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001274 }
1275 oldstate = reader->state;
1276 olddepth = reader->ctxt->nodeNr;
1277 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001278
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001279get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001280 if (reader->node == NULL) {
1281 if (reader->mode == XML_TEXTREADER_DONE)
1282 return(0);
1283 else
1284 return(-1);
1285 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001286
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287 /*
1288 * If we are not backtracking on ancestors or examined nodes,
1289 * that the parser didn't finished or that we arent at the end
1290 * of stream, continue processing.
1291 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001292 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001293 (reader->ctxt->nodeNr == olddepth) &&
1294 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001295 (reader->node->children == NULL) ||
1296 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001297 ((reader->node->children != NULL) &&
1298 (reader->node->children->type == XML_TEXT_NODE) &&
1299 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001300 (reader->node->type == XML_DTD_NODE) ||
1301 (reader->node->type == XML_DOCUMENT_NODE) ||
1302 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001303 ((reader->ctxt->node == NULL) ||
1304 (reader->ctxt->node == reader->node) ||
1305 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001306 (reader->ctxt->instate != XML_PARSER_EOF)) {
1307 val = xmlTextReaderPushData(reader);
1308 if (val < 0)
1309 return(-1);
1310 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001311 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001312 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001313 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001314 if ((reader->node->children != NULL) &&
1315 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001316 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001317 (reader->node->type != XML_DTD_NODE)) {
1318 reader->node = reader->node->children;
1319 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001320 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001321 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 }
1323 }
1324 if (reader->node->next != NULL) {
1325 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001326 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001327 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001328 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1329#ifdef LIBXML_XINCLUDE_ENABLED
1330 && (reader->in_xinclude <= 0)
1331#endif
1332 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001333 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001334 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001336#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001337 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001338 (reader->node->type == XML_ELEMENT_NODE))
1339 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001340#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001341 if ((reader->preserves > 0) &&
1342 (reader->node->extra & NODE_IS_SPRESERVED))
1343 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 reader->node = reader->node->next;
1345 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001346
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001347 /*
1348 * Cleanup of the old node
1349 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001350 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001351#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001352 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001353#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001354 (reader->entNr == 0) &&
1355 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001356 (reader->node->prev->type != XML_DTD_NODE) &&
1357 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001358 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001359 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001360 xmlUnlinkNode(tmp);
1361 xmlTextReaderFreeNode(reader, tmp);
1362 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 }
1364
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001365 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001366 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001367 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001368 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001369 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001370 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001371 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001372 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001373 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001374#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001375 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001376 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001377#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001378 if ((reader->preserves > 0) &&
1379 (reader->node->extra & NODE_IS_SPRESERVED))
1380 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001381 reader->node = reader->node->parent;
1382 if ((reader->node == NULL) ||
1383 (reader->node->type == XML_DOCUMENT_NODE) ||
1384#ifdef LIBXML_DOCB_ENABLED
1385 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1386#endif
1387 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001388 if (reader->mode != XML_TEXTREADER_DONE) {
1389 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1390 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001391 if (val != 0)
1392 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001393 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001394 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001395 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001396
1397 /*
1398 * Cleanup of the old node
1399 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001400 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001401#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001402 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001403#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001404 (reader->entNr == 0) &&
1405 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001406 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001407 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001408 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001409 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001410 }
1411
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001412 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001413 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001414 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001415#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001416 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001417#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001418 (reader->entNr == 0) &&
1419 (reader->node->last != NULL) &&
1420 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1421 xmlNodePtr tmp = reader->node->last;
1422 xmlUnlinkNode(tmp);
1423 xmlTextReaderFreeNode(reader, tmp);
1424 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001425 reader->depth--;
1426 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001427
1428node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001429 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001430
1431 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001432 * If we are in the middle of a piece of CDATA make sure it's finished
1433 */
1434 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001435 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001436 ((reader->node->type == XML_TEXT_NODE) ||
1437 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001438 if (xmlTextReaderExpand(reader) == NULL)
1439 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001440 }
1441
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001442#ifdef LIBXML_XINCLUDE_ENABLED
1443 /*
1444 * Handle XInclude if asked for
1445 */
1446 if ((reader->xinclude) && (reader->node != NULL) &&
1447 (reader->node->type == XML_ELEMENT_NODE) &&
1448 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001449 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1450 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001451 if (reader->xincctxt == NULL) {
1452 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001453 xmlXIncludeSetFlags(reader->xincctxt,
1454 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001455 }
1456 /*
1457 * expand that node and process it
1458 */
William M. Brack42331a92004-07-29 07:07:16 +00001459 if (xmlTextReaderExpand(reader) == NULL)
1460 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001461 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1462 }
1463 if (reader->node->type == XML_XINCLUDE_START) {
1464 reader->in_xinclude++;
1465 goto get_next_node;
1466 }
1467 if (reader->node->type == XML_XINCLUDE_END) {
1468 reader->in_xinclude--;
1469 goto get_next_node;
1470 }
1471#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001472 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001473 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001474 */
1475 if ((reader->node != NULL) &&
1476 (reader->node->type == XML_ENTITY_REF_NODE) &&
1477 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1478 /*
1479 * Case where the underlying tree is not availble, lookup the entity
1480 * and walk it.
1481 */
1482 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1483 (reader->ctxt->sax->getEntity != NULL)) {
1484 reader->node->children = (xmlNodePtr)
1485 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1486 }
1487
1488 if ((reader->node->children != NULL) &&
1489 (reader->node->children->type == XML_ENTITY_DECL) &&
1490 (reader->node->children->children != NULL)) {
1491 xmlTextReaderEntPush(reader, reader->node);
1492 reader->node = reader->node->children->children;
1493 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001494#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001495 } else if ((reader->node != NULL) &&
1496 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001497 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001498 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001499#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001500 }
1501 if ((reader->node != NULL) &&
1502 (reader->node->type == XML_ENTITY_DECL) &&
1503 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1504 reader->node = xmlTextReaderEntPop(reader);
1505 reader->depth++;
1506 goto get_next_node;
1507 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001508#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001509 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001510 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001511
1512 if ((node->type == XML_ELEMENT_NODE) &&
1513 ((reader->state != XML_TEXTREADER_END) &&
1514 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1515 xmlTextReaderValidatePush(reader);
1516 } else if ((node->type == XML_TEXT_NODE) ||
1517 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001518 xmlTextReaderValidateCData(reader, node->content,
1519 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001520 }
1521 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001522#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001523#ifdef LIBXML_PATTERN_ENABLED
1524 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1525 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1526 int i;
1527 for (i = 0;i < reader->patternNr;i++) {
1528 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1529 xmlTextReaderPreserve(reader);
1530 break;
1531 }
1532 }
1533 }
1534#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001535#ifdef LIBXML_SCHEMAS_ENABLED
1536 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1537 (reader->xsdValidErrors == 0) &&
1538 (reader->xsdValidCtxt != NULL)) {
1539 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1540 }
1541#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001542 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001543node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001544 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001545 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001546}
1547
Daniel Veillard67df8092002-12-16 22:04:11 +00001548/**
1549 * xmlTextReaderReadState:
1550 * @reader: the xmlTextReaderPtr used
1551 *
1552 * Gets the read state of the reader.
1553 *
1554 * Returns the state value, or -1 in case of error
1555 */
1556int
1557xmlTextReaderReadState(xmlTextReaderPtr reader) {
1558 if (reader == NULL)
1559 return(-1);
1560 return(reader->mode);
1561}
1562
1563/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001564 * xmlTextReaderExpand:
1565 * @reader: the xmlTextReaderPtr used
1566 *
1567 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001568 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001569 *
1570 * Returns a node pointer valid until the next xmlTextReaderRead() call
1571 * or NULL in case of error.
1572 */
1573xmlNodePtr
1574xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001575 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001576 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001577 if (reader->doc != NULL)
1578 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001579 if (reader->ctxt == NULL)
1580 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001581 if (xmlTextReaderDoExpand(reader) < 0)
1582 return(NULL);
1583 return(reader->node);
1584}
1585
1586/**
1587 * xmlTextReaderNext:
1588 * @reader: the xmlTextReaderPtr used
1589 *
1590 * Skip to the node following the current one in document order while
1591 * avoiding the subtree if any.
1592 *
1593 * Returns 1 if the node was read successfully, 0 if there is no more
1594 * nodes to read, or -1 in case of error
1595 */
1596int
1597xmlTextReaderNext(xmlTextReaderPtr reader) {
1598 int ret;
1599 xmlNodePtr cur;
1600
1601 if (reader == NULL)
1602 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001603 if (reader->doc != NULL)
1604 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001605 cur = reader->node;
1606 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1607 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001608 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001609 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001610 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001611 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001612 do {
1613 ret = xmlTextReaderRead(reader);
1614 if (ret != 1)
1615 return(ret);
1616 } while (reader->node != cur);
1617 return(xmlTextReaderRead(reader));
1618}
1619
1620/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001621 * xmlTextReaderReadInnerXml:
1622 * @reader: the xmlTextReaderPtr used
1623 *
1624 * Reads the contents of the current node, including child nodes and markup.
1625 *
1626 * Returns a string containing the XML content, or NULL if the current node
1627 * is neither an element nor attribute, or has no child nodes. The
1628 * string must be deallocated by the caller.
1629 */
1630xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001631xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1632{
1633 xmlChar *resbuf;
1634 xmlNodePtr node, cur_node;
1635 xmlBufferPtr buff, buff2;
1636 xmlDocPtr doc;
1637
1638 if (xmlTextReaderExpand(reader) == NULL) {
1639 return NULL;
1640 }
1641 doc = reader->doc;
1642 buff = xmlBufferCreate();
1643 for (cur_node = reader->node->children; cur_node != NULL;
1644 cur_node = cur_node->next) {
1645 node = xmlDocCopyNode(cur_node, doc, 1);
1646 buff2 = xmlBufferCreate();
1647 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1648 xmlFreeNode(node);
1649 xmlBufferFree(buff2);
1650 xmlBufferFree(buff);
1651 return NULL;
1652 }
1653 xmlBufferCat(buff, buff2->content);
1654 xmlFreeNode(node);
1655 xmlBufferFree(buff2);
1656 }
1657 resbuf = buff->content;
1658 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001659}
1660
1661/**
1662 * xmlTextReaderReadOuterXml:
1663 * @reader: the xmlTextReaderPtr used
1664 *
1665 * Reads the contents of the current node, including child nodes and markup.
1666 *
1667 * Returns a string containing the XML content, or NULL if the current node
1668 * is neither an element nor attribute, or has no child nodes. The
1669 * string must be deallocated by the caller.
1670 */
1671xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001672xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1673{
1674 xmlChar *resbuf;
1675 xmlNodePtr node;
1676 xmlBufferPtr buff;
1677 xmlDocPtr doc;
1678
1679 node = reader->node;
1680 doc = reader->doc;
1681 if (xmlTextReaderExpand(reader) == NULL) {
1682 return NULL;
1683 }
1684 node = xmlDocCopyNode(node, doc, 1);
1685 buff = xmlBufferCreate();
1686 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1687 xmlFreeNode(node);
1688 xmlBufferFree(buff);
1689 return NULL;
1690 }
1691
1692 resbuf = buff->content;
1693 buff->content = NULL;
1694
1695 xmlFreeNode(node);
1696 xmlBufferFree(buff);
1697 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001698}
1699
1700/**
1701 * xmlTextReaderReadString:
1702 * @reader: the xmlTextReaderPtr used
1703 *
1704 * Reads the contents of an element or a text node as a string.
1705 *
1706 * Returns a string containing the contents of the Element or Text node,
1707 * or NULL if the reader is positioned on any other type of node.
1708 * The string must be deallocated by the caller.
1709 */
1710xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001711xmlTextReaderReadString(xmlTextReaderPtr reader)
1712{
1713 xmlNodePtr node;
1714
1715 if ((reader == NULL) || (reader->node == NULL))
1716 return(NULL);
1717
1718 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1719 switch (node->type) {
1720 case XML_TEXT_NODE:
1721 if (node->content != NULL)
1722 return(xmlStrdup(node->content));
1723 break;
1724 case XML_ELEMENT_NODE:
1725 if (xmlTextReaderDoExpand(reader) != -1) {
1726 return xmlTextReaderCollectSiblings(node->children);
1727 }
1728 case XML_ATTRIBUTE_NODE:
1729 TODO
1730 break;
1731 default:
1732 break;
1733 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001734 return(NULL);
1735}
1736
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001737#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001738/**
1739 * xmlTextReaderReadBase64:
1740 * @reader: the xmlTextReaderPtr used
1741 * @array: a byte array to store the content.
1742 * @offset: the zero-based index into array where the method should
1743 * begin to write.
1744 * @len: the number of bytes to write.
1745 *
1746 * Reads and decodes the Base64 encoded contents of an element and
1747 * stores the result in a byte buffer.
1748 *
1749 * Returns the number of bytes written to array, or zero if the current
1750 * instance is not positioned on an element or -1 in case of error.
1751 */
1752int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001753xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1754 unsigned char *array ATTRIBUTE_UNUSED,
1755 int offset ATTRIBUTE_UNUSED,
1756 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001757 if ((reader == NULL) || (reader->ctxt == NULL))
1758 return(-1);
1759 if (reader->ctxt->wellFormed != 1)
1760 return(-1);
1761
1762 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1763 return(0);
1764 TODO
1765 return(0);
1766}
1767
1768/**
1769 * xmlTextReaderReadBinHex:
1770 * @reader: the xmlTextReaderPtr used
1771 * @array: a byte array to store the content.
1772 * @offset: the zero-based index into array where the method should
1773 * begin to write.
1774 * @len: the number of bytes to write.
1775 *
1776 * Reads and decodes the BinHex encoded contents of an element and
1777 * stores the result in a byte buffer.
1778 *
1779 * Returns the number of bytes written to array, or zero if the current
1780 * instance is not positioned on an element or -1 in case of error.
1781 */
1782int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001783xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1784 unsigned char *array ATTRIBUTE_UNUSED,
1785 int offset ATTRIBUTE_UNUSED,
1786 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001787 if ((reader == NULL) || (reader->ctxt == NULL))
1788 return(-1);
1789 if (reader->ctxt->wellFormed != 1)
1790 return(-1);
1791
1792 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1793 return(0);
1794 TODO
1795 return(0);
1796}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001797#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001798
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001799/************************************************************************
1800 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 * Operating on a preparsed tree *
1802 * *
1803 ************************************************************************/
1804static int
1805xmlTextReaderNextTree(xmlTextReaderPtr reader)
1806{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001807 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001808 return(-1);
1809
1810 if (reader->state == XML_TEXTREADER_END)
1811 return(0);
1812
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001813 if (reader->node == NULL) {
1814 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001815 reader->state = XML_TEXTREADER_END;
1816 return(0);
1817 }
1818
1819 reader->node = reader->doc->children;
1820 reader->state = XML_TEXTREADER_START;
1821 return(1);
1822 }
1823
1824 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1825 if (reader->node->children != 0) {
1826 reader->node = reader->node->children;
1827 reader->depth++;
1828 reader->state = XML_TEXTREADER_START;
1829 return(1);
1830 }
1831
1832 if ((reader->node->type == XML_ELEMENT_NODE) ||
1833 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1834 reader->state = XML_TEXTREADER_BACKTRACK;
1835 return(1);
1836 }
1837 }
1838
1839 if (reader->node->next != 0) {
1840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1843 }
1844
1845 if (reader->node->parent != 0) {
1846 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1847 reader->state = XML_TEXTREADER_END;
1848 return(0);
1849 }
1850
1851 reader->node = reader->node->parent;
1852 reader->depth--;
1853 reader->state = XML_TEXTREADER_BACKTRACK;
1854 return(1);
1855 }
1856
1857 reader->state = XML_TEXTREADER_END;
1858
1859 return(1);
1860}
1861
1862/**
1863 * xmlTextReaderReadTree:
1864 * @reader: the xmlTextReaderPtr used
1865 *
1866 * Moves the position of the current instance to the next node in
1867 * the stream, exposing its properties.
1868 *
1869 * Returns 1 if the node was read successfully, 0 if there is no more
1870 * nodes to read, or -1 in case of error
1871 */
1872static int
1873xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1874 if (reader->state == XML_TEXTREADER_END)
1875 return(0);
1876
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001877next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001878 if (reader->node == NULL) {
1879 if (reader->doc->children == NULL) {
1880 reader->state = XML_TEXTREADER_END;
1881 return(0);
1882 }
1883
1884 reader->node = reader->doc->children;
1885 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001886 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001887 }
1888
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001889 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1890 (reader->node->type != XML_DTD_NODE) &&
1891 (reader->node->type != XML_XINCLUDE_START) &&
1892 (reader->node->type != XML_ENTITY_REF_NODE)) {
1893 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001894 reader->node = reader->node->children;
1895 reader->depth++;
1896 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001897 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001898 }
1899
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001900 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001901 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001902 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 }
1904 }
1905
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001906 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001907 reader->node = reader->node->next;
1908 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001909 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 }
1911
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001912 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001913 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1914 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1915 reader->state = XML_TEXTREADER_END;
1916 return(0);
1917 }
1918
1919 reader->node = reader->node->parent;
1920 reader->depth--;
1921 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001922 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 }
1924
1925 reader->state = XML_TEXTREADER_END;
1926
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001927found_node:
1928 if ((reader->node->type == XML_XINCLUDE_START) ||
1929 (reader->node->type == XML_XINCLUDE_END))
1930 goto next_node;
1931
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 return(1);
1933}
1934
1935/**
William M. Brackb1d53162003-11-18 06:54:40 +00001936 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001937 * @reader: the xmlTextReaderPtr used
1938 *
1939 * Skip to the node following the current one in document order while
1940 * avoiding the subtree if any.
1941 * Currently implemented only for Readers built on a document
1942 *
1943 * Returns 1 if the node was read successfully, 0 if there is no more
1944 * nodes to read, or -1 in case of error
1945 */
1946int
1947xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1948 if (reader == NULL)
1949 return(-1);
1950 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001951 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001952 return(-1);
1953 }
1954
1955 if (reader->state == XML_TEXTREADER_END)
1956 return(0);
1957
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001958 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001959 return(xmlTextReaderNextTree(reader));
1960
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001961 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001962 reader->node = reader->node->next;
1963 reader->state = XML_TEXTREADER_START;
1964 return(1);
1965 }
1966
1967 return(0);
1968}
1969
1970/************************************************************************
1971 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001972 * Constructor and destructors *
1973 * *
1974 ************************************************************************/
1975/**
1976 * xmlNewTextReader:
1977 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001978 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001979 *
1980 * Create an xmlTextReader structure fed with @input
1981 *
1982 * Returns the new xmlTextReaderPtr or NULL in case of error
1983 */
1984xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001985xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001986 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001987
1988 if (input == NULL)
1989 return(NULL);
1990 ret = xmlMalloc(sizeof(xmlTextReader));
1991 if (ret == NULL) {
1992 xmlGenericError(xmlGenericErrorContext,
1993 "xmlNewTextReader : malloc failed\n");
1994 return(NULL);
1995 }
1996 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001997 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001998 ret->entTab = NULL;
1999 ret->entMax = 0;
2000 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002001 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002002 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002003 if (ret->buffer == NULL) {
2004 xmlFree(ret);
2005 xmlGenericError(xmlGenericErrorContext,
2006 "xmlNewTextReader : malloc failed\n");
2007 return(NULL);
2008 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002009 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2010 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002011 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002012 xmlFree(ret);
2013 xmlGenericError(xmlGenericErrorContext,
2014 "xmlNewTextReader : malloc failed\n");
2015 return(NULL);
2016 }
Daniel Veillard81273902003-09-30 00:43:48 +00002017 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018 ret->startElement = ret->sax->startElement;
2019 ret->sax->startElement = xmlTextReaderStartElement;
2020 ret->endElement = ret->sax->endElement;
2021 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002022#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002023 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002024#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002025 ret->startElementNs = ret->sax->startElementNs;
2026 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2027 ret->endElementNs = ret->sax->endElementNs;
2028 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002029#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002030 } else {
2031 ret->startElementNs = NULL;
2032 ret->endElementNs = NULL;
2033 }
Daniel Veillard81273902003-09-30 00:43:48 +00002034#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002035 ret->characters = ret->sax->characters;
2036 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002037 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002038 ret->cdataBlock = ret->sax->cdataBlock;
2039 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002040
Daniel Veillard67df8092002-12-16 22:04:11 +00002041 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002042 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002043 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002044 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002045 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002046 }
2047 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002049 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002050 ret->base = 0;
2051 ret->cur = 4;
2052 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002053 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002054 ret->base = 0;
2055 ret->cur = 0;
2056 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002057
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002058 if (ret->ctxt == NULL) {
2059 xmlGenericError(xmlGenericErrorContext,
2060 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002061 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002062 xmlFree(ret->sax);
2063 xmlFree(ret);
2064 return(NULL);
2065 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002066 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002067 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002068 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002069 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002070 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002071 /*
2072 * use the parser dictionnary to allocate all elements and attributes names
2073 */
2074 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002075 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002076#ifdef LIBXML_XINCLUDE_ENABLED
2077 ret->xinclude = 0;
2078#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002079#ifdef LIBXML_PATTERN_ENABLED
2080 ret->patternMax = 0;
2081 ret->patternTab = NULL;
2082#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002083 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002084}
2085
2086/**
2087 * xmlNewTextReaderFilename:
2088 * @URI: the URI of the resource to process
2089 *
2090 * Create an xmlTextReader structure fed with the resource at @URI
2091 *
2092 * Returns the new xmlTextReaderPtr or NULL in case of error
2093 */
2094xmlTextReaderPtr
2095xmlNewTextReaderFilename(const char *URI) {
2096 xmlParserInputBufferPtr input;
2097 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002098 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002099
2100 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2101 if (input == NULL)
2102 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002103 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002104 if (ret == NULL) {
2105 xmlFreeParserInputBuffer(input);
2106 return(NULL);
2107 }
2108 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002109 if (ret->ctxt->directory == NULL)
2110 directory = xmlParserGetDirectory(URI);
2111 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2112 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2113 if (directory != NULL)
2114 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115 return(ret);
2116}
2117
2118/**
2119 * xmlFreeTextReader:
2120 * @reader: the xmlTextReaderPtr
2121 *
2122 * Deallocate all the resources associated to the reader
2123 */
2124void
2125xmlFreeTextReader(xmlTextReaderPtr reader) {
2126 if (reader == NULL)
2127 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002128#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002129 if (reader->rngSchemas != NULL) {
2130 xmlRelaxNGFree(reader->rngSchemas);
2131 reader->rngSchemas = NULL;
2132 }
2133 if (reader->rngValidCtxt != NULL) {
2134 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2135 reader->rngValidCtxt = NULL;
2136 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002137 if (reader->xsdPlug != NULL) {
2138 xmlSchemaSAXUnplug(reader->xsdPlug);
2139 reader->xsdPlug = NULL;
2140 }
2141 if (reader->xsdValidCtxt != NULL) {
2142 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2143 reader->xsdValidCtxt = NULL;
2144 }
2145 if (reader->xsdSchemas != NULL) {
2146 xmlSchemaFree(reader->xsdSchemas);
2147 reader->xsdSchemas = NULL;
2148 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002149#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002150#ifdef LIBXML_XINCLUDE_ENABLED
2151 if (reader->xincctxt != NULL)
2152 xmlXIncludeFreeContext(reader->xincctxt);
2153#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002154#ifdef LIBXML_PATTERN_ENABLED
2155 if (reader->patternTab != NULL) {
2156 int i;
2157 for (i = 0;i < reader->patternNr;i++) {
2158 if (reader->patternTab[i] != NULL)
2159 xmlFreePattern(reader->patternTab[i]);
2160 }
2161 xmlFree(reader->patternTab);
2162 }
2163#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002164 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002165 if (reader->dict == reader->ctxt->dict)
2166 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002167 if (reader->ctxt->myDoc != NULL) {
2168 if (reader->preserve == 0)
2169 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2170 reader->ctxt->myDoc = NULL;
2171 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002172 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2173 (reader->ctxt->vctxt.vstateMax > 0)){
2174 xmlFree(reader->ctxt->vctxt.vstateTab);
2175 reader->ctxt->vctxt.vstateTab = 0;
2176 reader->ctxt->vctxt.vstateMax = 0;
2177 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002178 if (reader->allocs & XML_TEXTREADER_CTXT)
2179 xmlFreeParserCtxt(reader->ctxt);
2180 }
2181 if (reader->sax != NULL)
2182 xmlFree(reader->sax);
2183 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2184 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002185 if (reader->faketext != NULL) {
2186 xmlFreeNode(reader->faketext);
2187 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002188 if (reader->buffer != NULL)
2189 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002190 if (reader->entTab != NULL)
2191 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002192 if (reader->dict != NULL)
2193 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002194 xmlFree(reader);
2195}
2196
2197/************************************************************************
2198 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002199 * Methods for XmlTextReader *
2200 * *
2201 ************************************************************************/
2202/**
2203 * xmlTextReaderClose:
2204 * @reader: the xmlTextReaderPtr used
2205 *
2206 * This method releases any resources allocated by the current instance
2207 * changes the state to Closed and close any underlying input.
2208 *
2209 * Returns 0 or -1 in case of error
2210 */
2211int
2212xmlTextReaderClose(xmlTextReaderPtr reader) {
2213 if (reader == NULL)
2214 return(-1);
2215 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002216 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002217 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2218 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002219 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002220 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002221 if (reader->preserve == 0)
2222 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002223 reader->ctxt->myDoc = NULL;
2224 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002225 }
2226 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2227 xmlFreeParserInputBuffer(reader->input);
2228 reader->allocs -= XML_TEXTREADER_INPUT;
2229 }
2230 return(0);
2231}
2232
2233/**
2234 * xmlTextReaderGetAttributeNo:
2235 * @reader: the xmlTextReaderPtr used
2236 * @no: the zero-based index of the attribute relative to the containing element
2237 *
2238 * Provides the value of the attribute with the specified index relative
2239 * to the containing element.
2240 *
2241 * Returns a string containing the value of the specified attribute, or NULL
2242 * in case of error. The string must be deallocated by the caller.
2243 */
2244xmlChar *
2245xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2246 xmlChar *ret;
2247 int i;
2248 xmlAttrPtr cur;
2249 xmlNsPtr ns;
2250
2251 if (reader == NULL)
2252 return(NULL);
2253 if (reader->node == NULL)
2254 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002255 if (reader->curnode != NULL)
2256 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002257 /* TODO: handle the xmlDecl */
2258 if (reader->node->type != XML_ELEMENT_NODE)
2259 return(NULL);
2260
2261 ns = reader->node->nsDef;
2262 for (i = 0;(i < no) && (ns != NULL);i++) {
2263 ns = ns->next;
2264 }
2265 if (ns != NULL)
2266 return(xmlStrdup(ns->href));
2267
2268 cur = reader->node->properties;
2269 if (cur == NULL)
2270 return(NULL);
2271 for (;i < no;i++) {
2272 cur = cur->next;
2273 if (cur == NULL)
2274 return(NULL);
2275 }
2276 /* TODO walk the DTD if present */
2277
2278 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2279 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2280 return(ret);
2281}
2282
2283/**
2284 * xmlTextReaderGetAttribute:
2285 * @reader: the xmlTextReaderPtr used
2286 * @name: the qualified name of the attribute.
2287 *
2288 * Provides the value of the attribute with the specified qualified name.
2289 *
2290 * Returns a string containing the value of the specified attribute, or NULL
2291 * in case of error. The string must be deallocated by the caller.
2292 */
2293xmlChar *
2294xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2295 xmlChar *prefix = NULL;
2296 xmlChar *localname;
2297 xmlNsPtr ns;
2298 xmlChar *ret = NULL;
2299
2300 if ((reader == NULL) || (name == NULL))
2301 return(NULL);
2302 if (reader->node == NULL)
2303 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002304 if (reader->curnode != NULL)
2305 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002306
2307 /* TODO: handle the xmlDecl */
2308 if (reader->node->type != XML_ELEMENT_NODE)
2309 return(NULL);
2310
2311 localname = xmlSplitQName2(name, &prefix);
2312 if (localname == NULL)
2313 return(xmlGetProp(reader->node, name));
2314
2315 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2316 if (ns != NULL)
2317 ret = xmlGetNsProp(reader->node, localname, ns->href);
2318
2319 if (localname != NULL)
2320 xmlFree(localname);
2321 if (prefix != NULL)
2322 xmlFree(prefix);
2323 return(ret);
2324}
2325
2326
2327/**
2328 * xmlTextReaderGetAttributeNs:
2329 * @reader: the xmlTextReaderPtr used
2330 * @localName: the local name of the attribute.
2331 * @namespaceURI: the namespace URI of the attribute.
2332 *
2333 * Provides the value of the specified attribute
2334 *
2335 * Returns a string containing the value of the specified attribute, or NULL
2336 * in case of error. The string must be deallocated by the caller.
2337 */
2338xmlChar *
2339xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2340 const xmlChar *namespaceURI) {
2341 if ((reader == NULL) || (localName == NULL))
2342 return(NULL);
2343 if (reader->node == NULL)
2344 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002345 if (reader->curnode != NULL)
2346 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002347
2348 /* TODO: handle the xmlDecl */
2349 if (reader->node->type != XML_ELEMENT_NODE)
2350 return(NULL);
2351
2352 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2353}
2354
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002355/**
2356 * xmlTextReaderGetRemainder:
2357 * @reader: the xmlTextReaderPtr used
2358 *
2359 * Method to get the remainder of the buffered XML. this method stops the
2360 * parser, set its state to End Of File and return the input stream with
2361 * what is left that the parser did not use.
2362 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002363 * The implementation is not good, the parser certainly procgressed past
2364 * what's left in reader->input, and there is an allocation problem. Best
2365 * would be to rewrite it differently.
2366 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002367 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2368 * in case of error.
2369 */
2370xmlParserInputBufferPtr
2371xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2372 xmlParserInputBufferPtr ret = NULL;
2373
2374 if (reader == NULL)
2375 return(NULL);
2376 if (reader->node == NULL)
2377 return(NULL);
2378
2379 reader->node = NULL;
2380 reader->curnode = NULL;
2381 reader->mode = XML_TEXTREADER_MODE_EOF;
2382 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002383 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002384 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002385 if (reader->preserve == 0)
2386 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002387 reader->ctxt->myDoc = NULL;
2388 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002389 }
2390 if (reader->allocs & XML_TEXTREADER_INPUT) {
2391 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002392 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002393 reader->allocs -= XML_TEXTREADER_INPUT;
2394 } else {
2395 /*
2396 * Hum, one may need to duplicate the data structure because
2397 * without reference counting the input may be freed twice:
2398 * - by the layer which allocated it.
2399 * - by the layer to which would have been returned to.
2400 */
2401 TODO
2402 return(NULL);
2403 }
2404 return(ret);
2405}
2406
2407/**
2408 * xmlTextReaderLookupNamespace:
2409 * @reader: the xmlTextReaderPtr used
2410 * @prefix: the prefix whose namespace URI is to be resolved. To return
2411 * the default namespace, specify NULL
2412 *
2413 * Resolves a namespace prefix in the scope of the current element.
2414 *
2415 * Returns a string containing the namespace URI to which the prefix maps
2416 * or NULL in case of error. The string must be deallocated by the caller.
2417 */
2418xmlChar *
2419xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2420 xmlNsPtr ns;
2421
2422 if (reader == NULL)
2423 return(NULL);
2424 if (reader->node == NULL)
2425 return(NULL);
2426
2427 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2428 if (ns == NULL)
2429 return(NULL);
2430 return(xmlStrdup(ns->href));
2431}
2432
2433/**
2434 * xmlTextReaderMoveToAttributeNo:
2435 * @reader: the xmlTextReaderPtr used
2436 * @no: the zero-based index of the attribute relative to the containing
2437 * element.
2438 *
2439 * Moves the position of the current instance to the attribute with
2440 * the specified index relative to the containing element.
2441 *
2442 * Returns 1 in case of success, -1 in case of error, 0 if not found
2443 */
2444int
2445xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2446 int i;
2447 xmlAttrPtr cur;
2448 xmlNsPtr ns;
2449
2450 if (reader == NULL)
2451 return(-1);
2452 if (reader->node == NULL)
2453 return(-1);
2454 /* TODO: handle the xmlDecl */
2455 if (reader->node->type != XML_ELEMENT_NODE)
2456 return(-1);
2457
2458 reader->curnode = NULL;
2459
2460 ns = reader->node->nsDef;
2461 for (i = 0;(i < no) && (ns != NULL);i++) {
2462 ns = ns->next;
2463 }
2464 if (ns != NULL) {
2465 reader->curnode = (xmlNodePtr) ns;
2466 return(1);
2467 }
2468
2469 cur = reader->node->properties;
2470 if (cur == NULL)
2471 return(0);
2472 for (;i < no;i++) {
2473 cur = cur->next;
2474 if (cur == NULL)
2475 return(0);
2476 }
2477 /* TODO walk the DTD if present */
2478
2479 reader->curnode = (xmlNodePtr) cur;
2480 return(1);
2481}
2482
2483/**
2484 * xmlTextReaderMoveToAttribute:
2485 * @reader: the xmlTextReaderPtr used
2486 * @name: the qualified name of the attribute.
2487 *
2488 * Moves the position of the current instance to the attribute with
2489 * the specified qualified name.
2490 *
2491 * Returns 1 in case of success, -1 in case of error, 0 if not found
2492 */
2493int
2494xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2495 xmlChar *prefix = NULL;
2496 xmlChar *localname;
2497 xmlNsPtr ns;
2498 xmlAttrPtr prop;
2499
2500 if ((reader == NULL) || (name == NULL))
2501 return(-1);
2502 if (reader->node == NULL)
2503 return(-1);
2504
2505 /* TODO: handle the xmlDecl */
2506 if (reader->node->type != XML_ELEMENT_NODE)
2507 return(0);
2508
2509 localname = xmlSplitQName2(name, &prefix);
2510 if (localname == NULL) {
2511 /*
2512 * Namespace default decl
2513 */
2514 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2515 ns = reader->node->nsDef;
2516 while (ns != NULL) {
2517 if (ns->prefix == NULL) {
2518 reader->curnode = (xmlNodePtr) ns;
2519 return(1);
2520 }
2521 ns = ns->next;
2522 }
2523 return(0);
2524 }
2525
2526 prop = reader->node->properties;
2527 while (prop != NULL) {
2528 /*
2529 * One need to have
2530 * - same attribute names
2531 * - and the attribute carrying that namespace
2532 */
2533 if ((xmlStrEqual(prop->name, name)) &&
2534 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2535 reader->curnode = (xmlNodePtr) prop;
2536 return(1);
2537 }
2538 prop = prop->next;
2539 }
2540 return(0);
2541 }
2542
2543 /*
2544 * Namespace default decl
2545 */
2546 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2547 ns = reader->node->nsDef;
2548 while (ns != NULL) {
2549 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2550 reader->curnode = (xmlNodePtr) ns;
2551 goto found;
2552 }
2553 ns = ns->next;
2554 }
2555 goto not_found;
2556 }
2557 prop = reader->node->properties;
2558 while (prop != NULL) {
2559 /*
2560 * One need to have
2561 * - same attribute names
2562 * - and the attribute carrying that namespace
2563 */
2564 if ((xmlStrEqual(prop->name, localname)) &&
2565 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2566 reader->curnode = (xmlNodePtr) prop;
2567 goto found;
2568 }
2569 prop = prop->next;
2570 }
2571not_found:
2572 if (localname != NULL)
2573 xmlFree(localname);
2574 if (prefix != NULL)
2575 xmlFree(prefix);
2576 return(0);
2577
2578found:
2579 if (localname != NULL)
2580 xmlFree(localname);
2581 if (prefix != NULL)
2582 xmlFree(prefix);
2583 return(1);
2584}
2585
2586/**
2587 * xmlTextReaderMoveToAttributeNs:
2588 * @reader: the xmlTextReaderPtr used
2589 * @localName: the local name of the attribute.
2590 * @namespaceURI: the namespace URI of the attribute.
2591 *
2592 * Moves the position of the current instance to the attribute with the
2593 * specified local name and namespace URI.
2594 *
2595 * Returns 1 in case of success, -1 in case of error, 0 if not found
2596 */
2597int
2598xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2599 const xmlChar *localName, const xmlChar *namespaceURI) {
2600 xmlAttrPtr prop;
2601 xmlNodePtr node;
2602
2603 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2604 return(-1);
2605 if (reader->node == NULL)
2606 return(-1);
2607 if (reader->node->type != XML_ELEMENT_NODE)
2608 return(0);
2609 node = reader->node;
2610
2611 /*
2612 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2613 * namespace name associated to "xmlns"
2614 */
2615 prop = node->properties;
2616 while (prop != NULL) {
2617 /*
2618 * One need to have
2619 * - same attribute names
2620 * - and the attribute carrying that namespace
2621 */
2622 if (xmlStrEqual(prop->name, localName) &&
2623 ((prop->ns != NULL) &&
2624 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2625 reader->curnode = (xmlNodePtr) prop;
2626 return(1);
2627 }
2628 prop = prop->next;
2629 }
2630 return(0);
2631}
2632
2633/**
2634 * xmlTextReaderMoveToFirstAttribute:
2635 * @reader: the xmlTextReaderPtr used
2636 *
2637 * Moves the position of the current instance to the first attribute
2638 * associated with the current node.
2639 *
2640 * Returns 1 in case of success, -1 in case of error, 0 if not found
2641 */
2642int
2643xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2644 if (reader == NULL)
2645 return(-1);
2646 if (reader->node == NULL)
2647 return(-1);
2648 if (reader->node->type != XML_ELEMENT_NODE)
2649 return(0);
2650
2651 if (reader->node->nsDef != NULL) {
2652 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2653 return(1);
2654 }
2655 if (reader->node->properties != NULL) {
2656 reader->curnode = (xmlNodePtr) reader->node->properties;
2657 return(1);
2658 }
2659 return(0);
2660}
2661
2662/**
2663 * xmlTextReaderMoveToNextAttribute:
2664 * @reader: the xmlTextReaderPtr used
2665 *
2666 * Moves the position of the current instance to the next attribute
2667 * associated with the current node.
2668 *
2669 * Returns 1 in case of success, -1 in case of error, 0 if not found
2670 */
2671int
2672xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2673 if (reader == NULL)
2674 return(-1);
2675 if (reader->node == NULL)
2676 return(-1);
2677 if (reader->node->type != XML_ELEMENT_NODE)
2678 return(0);
2679 if (reader->curnode == NULL)
2680 return(xmlTextReaderMoveToFirstAttribute(reader));
2681
2682 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2683 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2684 if (ns->next != NULL) {
2685 reader->curnode = (xmlNodePtr) ns->next;
2686 return(1);
2687 }
2688 if (reader->node->properties != NULL) {
2689 reader->curnode = (xmlNodePtr) reader->node->properties;
2690 return(1);
2691 }
2692 return(0);
2693 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2694 (reader->curnode->next != NULL)) {
2695 reader->curnode = reader->curnode->next;
2696 return(1);
2697 }
2698 return(0);
2699}
2700
2701/**
2702 * xmlTextReaderMoveToElement:
2703 * @reader: the xmlTextReaderPtr used
2704 *
2705 * Moves the position of the current instance to the node that
2706 * contains the current Attribute node.
2707 *
2708 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2709 */
2710int
2711xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2712 if (reader == NULL)
2713 return(-1);
2714 if (reader->node == NULL)
2715 return(-1);
2716 if (reader->node->type != XML_ELEMENT_NODE)
2717 return(0);
2718 if (reader->curnode != NULL) {
2719 reader->curnode = NULL;
2720 return(1);
2721 }
2722 return(0);
2723}
2724
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002725/**
2726 * xmlTextReaderReadAttributeValue:
2727 * @reader: the xmlTextReaderPtr used
2728 *
2729 * Parses an attribute value into one or more Text and EntityReference nodes.
2730 *
2731 * Returns 1 in case of success, 0 if the reader was not positionned on an
2732 * ttribute node or all the attribute values have been read, or -1
2733 * in case of error.
2734 */
2735int
2736xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2737 if (reader == NULL)
2738 return(-1);
2739 if (reader->node == NULL)
2740 return(-1);
2741 if (reader->curnode == NULL)
2742 return(0);
2743 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2744 if (reader->curnode->children == NULL)
2745 return(0);
2746 reader->curnode = reader->curnode->children;
2747 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2748 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2749
2750 if (reader->faketext == NULL) {
2751 reader->faketext = xmlNewDocText(reader->node->doc,
2752 ns->href);
2753 } else {
2754 if (reader->faketext->content != NULL)
2755 xmlFree(reader->faketext->content);
2756 reader->faketext->content = xmlStrdup(ns->href);
2757 }
2758 reader->curnode = reader->faketext;
2759 } else {
2760 if (reader->curnode->next == NULL)
2761 return(0);
2762 reader->curnode = reader->curnode->next;
2763 }
2764 return(1);
2765}
2766
Daniel Veillarde2811272004-10-19 09:04:23 +00002767/**
2768 * xmlTextReaderConstEncoding:
2769 * @reader: the xmlTextReaderPtr used
2770 *
2771 * Determine the encoding of the document being read.
2772 *
2773 * Returns a string containing the encoding of the document or NULL in
2774 * case of error. The string is deallocated with the reader.
2775 */
2776const xmlChar *
2777xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2778 xmlDocPtr doc = NULL;
2779 if (reader == NULL)
2780 return(NULL);
2781 if (reader->doc != NULL)
2782 doc = reader->doc;
2783 else if (reader->ctxt != NULL)
2784 doc = reader->ctxt->myDoc;
2785 if (doc == NULL)
2786 return(NULL);
2787
2788 if (doc->encoding == NULL)
2789 return(NULL);
2790 else
2791 return(CONSTSTR(doc->encoding));
2792}
2793
2794
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002795/************************************************************************
2796 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002797 * Acces API to the current node *
2798 * *
2799 ************************************************************************/
2800/**
2801 * xmlTextReaderAttributeCount:
2802 * @reader: the xmlTextReaderPtr used
2803 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002804 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002805 *
2806 * Returns 0 i no attributes, -1 in case of error or the attribute count
2807 */
2808int
2809xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2810 int ret;
2811 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002812 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002813 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002814
2815 if (reader == NULL)
2816 return(-1);
2817 if (reader->node == NULL)
2818 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002819
2820 if (reader->curnode != NULL)
2821 node = reader->curnode;
2822 else
2823 node = reader->node;
2824
2825 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002826 return(0);
2827 if ((reader->state == XML_TEXTREADER_END) ||
2828 (reader->state == XML_TEXTREADER_BACKTRACK))
2829 return(0);
2830 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002831 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002832 while (attr != NULL) {
2833 ret++;
2834 attr = attr->next;
2835 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002836 ns = node->nsDef;
2837 while (ns != NULL) {
2838 ret++;
2839 ns = ns->next;
2840 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002841 return(ret);
2842}
2843
2844/**
2845 * xmlTextReaderNodeType:
2846 * @reader: the xmlTextReaderPtr used
2847 *
2848 * Get the node type of the current node
2849 * Reference:
2850 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2851 *
2852 * Returns the xmlNodeType of the current node or -1 in case of error
2853 */
2854int
2855xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002856 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002857
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002858 if (reader == NULL)
2859 return(-1);
2860 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002861 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002862 if (reader->curnode != NULL)
2863 node = reader->curnode;
2864 else
2865 node = reader->node;
2866 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002867 case XML_ELEMENT_NODE:
2868 if ((reader->state == XML_TEXTREADER_END) ||
2869 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002870 return(XML_READER_TYPE_END_ELEMENT);
2871 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002872 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002873 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002874 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002875 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002876 if (xmlIsBlankNode(reader->node)) {
2877 if (xmlNodeGetSpacePreserve(reader->node))
2878 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2879 else
2880 return(XML_READER_TYPE_WHITESPACE);
2881 } else {
2882 return(XML_READER_TYPE_TEXT);
2883 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002884 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002885 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002886 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002887 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002888 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002889 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002890 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002891 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002892 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002893 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002894 case XML_DOCUMENT_NODE:
2895 case XML_HTML_DOCUMENT_NODE:
2896#ifdef LIBXML_DOCB_ENABLED
2897 case XML_DOCB_DOCUMENT_NODE:
2898#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002899 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002900 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002901 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002902 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002903 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002904 case XML_DOCUMENT_TYPE_NODE:
2905 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002906 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002907
2908 case XML_ELEMENT_DECL:
2909 case XML_ATTRIBUTE_DECL:
2910 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002911 case XML_XINCLUDE_START:
2912 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002913 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002914 }
2915 return(-1);
2916}
2917
2918/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002919 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002920 * @reader: the xmlTextReaderPtr used
2921 *
2922 * Check if the current node is empty
2923 *
2924 * Returns 1 if empty, 0 if not and -1 in case of error
2925 */
2926int
2927xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2928 if ((reader == NULL) || (reader->node == NULL))
2929 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002930 if (reader->node->type != XML_ELEMENT_NODE)
2931 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002932 if (reader->curnode != NULL)
2933 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002934 if (reader->node->children != NULL)
2935 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002936 if (reader->state == XML_TEXTREADER_END)
2937 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002938 if (reader->doc != NULL)
2939 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002940#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002941 if (reader->in_xinclude > 0)
2942 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002943#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002944 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002945}
2946
2947/**
2948 * xmlTextReaderLocalName:
2949 * @reader: the xmlTextReaderPtr used
2950 *
2951 * The local name of the node.
2952 *
2953 * Returns the local name or NULL if not available
2954 */
2955xmlChar *
2956xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002957 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002958 if ((reader == NULL) || (reader->node == NULL))
2959 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002960 if (reader->curnode != NULL)
2961 node = reader->curnode;
2962 else
2963 node = reader->node;
2964 if (node->type == XML_NAMESPACE_DECL) {
2965 xmlNsPtr ns = (xmlNsPtr) node;
2966 if (ns->prefix == NULL)
2967 return(xmlStrdup(BAD_CAST "xmlns"));
2968 else
2969 return(xmlStrdup(ns->prefix));
2970 }
2971 if ((node->type != XML_ELEMENT_NODE) &&
2972 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002973 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002974 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002975}
2976
2977/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002978 * xmlTextReaderConstLocalName:
2979 * @reader: the xmlTextReaderPtr used
2980 *
2981 * The local name of the node.
2982 *
2983 * Returns the local name or NULL if not available, the
2984 * string will be deallocated with the reader.
2985 */
2986const xmlChar *
2987xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2988 xmlNodePtr node;
2989 if ((reader == NULL) || (reader->node == NULL))
2990 return(NULL);
2991 if (reader->curnode != NULL)
2992 node = reader->curnode;
2993 else
2994 node = reader->node;
2995 if (node->type == XML_NAMESPACE_DECL) {
2996 xmlNsPtr ns = (xmlNsPtr) node;
2997 if (ns->prefix == NULL)
2998 return(CONSTSTR(BAD_CAST "xmlns"));
2999 else
3000 return(ns->prefix);
3001 }
3002 if ((node->type != XML_ELEMENT_NODE) &&
3003 (node->type != XML_ATTRIBUTE_NODE))
3004 return(xmlTextReaderConstName(reader));
3005 return(node->name);
3006}
3007
3008/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003009 * xmlTextReaderName:
3010 * @reader: the xmlTextReaderPtr used
3011 *
3012 * The qualified name of the node, equal to Prefix :LocalName.
3013 *
3014 * Returns the local name or NULL if not available
3015 */
3016xmlChar *
3017xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003018 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003019 xmlChar *ret;
3020
3021 if ((reader == NULL) || (reader->node == NULL))
3022 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003023 if (reader->curnode != NULL)
3024 node = reader->curnode;
3025 else
3026 node = reader->node;
3027 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003028 case XML_ELEMENT_NODE:
3029 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003030 if ((node->ns == NULL) ||
3031 (node->ns->prefix == NULL))
3032 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003033
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003034 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003035 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003036 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003037 return(ret);
3038 case XML_TEXT_NODE:
3039 return(xmlStrdup(BAD_CAST "#text"));
3040 case XML_CDATA_SECTION_NODE:
3041 return(xmlStrdup(BAD_CAST "#cdata-section"));
3042 case XML_ENTITY_NODE:
3043 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003044 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003045 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003046 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003047 case XML_COMMENT_NODE:
3048 return(xmlStrdup(BAD_CAST "#comment"));
3049 case XML_DOCUMENT_NODE:
3050 case XML_HTML_DOCUMENT_NODE:
3051#ifdef LIBXML_DOCB_ENABLED
3052 case XML_DOCB_DOCUMENT_NODE:
3053#endif
3054 return(xmlStrdup(BAD_CAST "#document"));
3055 case XML_DOCUMENT_FRAG_NODE:
3056 return(xmlStrdup(BAD_CAST "#document-fragment"));
3057 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003058 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003059 case XML_DOCUMENT_TYPE_NODE:
3060 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003061 return(xmlStrdup(node->name));
3062 case XML_NAMESPACE_DECL: {
3063 xmlNsPtr ns = (xmlNsPtr) node;
3064
3065 ret = xmlStrdup(BAD_CAST "xmlns");
3066 if (ns->prefix == NULL)
3067 return(ret);
3068 ret = xmlStrcat(ret, BAD_CAST ":");
3069 ret = xmlStrcat(ret, ns->prefix);
3070 return(ret);
3071 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003072
3073 case XML_ELEMENT_DECL:
3074 case XML_ATTRIBUTE_DECL:
3075 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003076 case XML_XINCLUDE_START:
3077 case XML_XINCLUDE_END:
3078 return(NULL);
3079 }
3080 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003081}
3082
3083/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003084 * xmlTextReaderConstName:
3085 * @reader: the xmlTextReaderPtr used
3086 *
3087 * The qualified name of the node, equal to Prefix :LocalName.
3088 *
3089 * Returns the local name or NULL if not available, the string is
3090 * deallocated with the reader.
3091 */
3092const xmlChar *
3093xmlTextReaderConstName(xmlTextReaderPtr reader) {
3094 xmlNodePtr node;
3095
3096 if ((reader == NULL) || (reader->node == NULL))
3097 return(NULL);
3098 if (reader->curnode != NULL)
3099 node = reader->curnode;
3100 else
3101 node = reader->node;
3102 switch (node->type) {
3103 case XML_ELEMENT_NODE:
3104 case XML_ATTRIBUTE_NODE:
3105 if ((node->ns == NULL) ||
3106 (node->ns->prefix == NULL))
3107 return(node->name);
3108 return(CONSTQSTR(node->ns->prefix, node->name));
3109 case XML_TEXT_NODE:
3110 return(CONSTSTR(BAD_CAST "#text"));
3111 case XML_CDATA_SECTION_NODE:
3112 return(CONSTSTR(BAD_CAST "#cdata-section"));
3113 case XML_ENTITY_NODE:
3114 case XML_ENTITY_REF_NODE:
3115 return(CONSTSTR(node->name));
3116 case XML_PI_NODE:
3117 return(CONSTSTR(node->name));
3118 case XML_COMMENT_NODE:
3119 return(CONSTSTR(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(CONSTSTR(BAD_CAST "#document"));
3126 case XML_DOCUMENT_FRAG_NODE:
3127 return(CONSTSTR(BAD_CAST "#document-fragment"));
3128 case XML_NOTATION_NODE:
3129 return(CONSTSTR(node->name));
3130 case XML_DOCUMENT_TYPE_NODE:
3131 case XML_DTD_NODE:
3132 return(CONSTSTR(node->name));
3133 case XML_NAMESPACE_DECL: {
3134 xmlNsPtr ns = (xmlNsPtr) node;
3135
3136 if (ns->prefix == NULL)
3137 return(CONSTSTR(BAD_CAST "xmlns"));
3138 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3139 }
3140
3141 case XML_ELEMENT_DECL:
3142 case XML_ATTRIBUTE_DECL:
3143 case XML_ENTITY_DECL:
3144 case XML_XINCLUDE_START:
3145 case XML_XINCLUDE_END:
3146 return(NULL);
3147 }
3148 return(NULL);
3149}
3150
3151/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003152 * xmlTextReaderPrefix:
3153 * @reader: the xmlTextReaderPtr used
3154 *
3155 * A shorthand reference to the namespace associated with the node.
3156 *
3157 * Returns the prefix or NULL if not available
3158 */
3159xmlChar *
3160xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003161 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003162 if ((reader == NULL) || (reader->node == NULL))
3163 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003164 if (reader->curnode != NULL)
3165 node = reader->curnode;
3166 else
3167 node = reader->node;
3168 if (node->type == XML_NAMESPACE_DECL) {
3169 xmlNsPtr ns = (xmlNsPtr) node;
3170 if (ns->prefix == NULL)
3171 return(NULL);
3172 return(xmlStrdup(BAD_CAST "xmlns"));
3173 }
3174 if ((node->type != XML_ELEMENT_NODE) &&
3175 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003176 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003177 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003178 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003179 return(NULL);
3180}
3181
3182/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003183 * xmlTextReaderConstPrefix:
3184 * @reader: the xmlTextReaderPtr used
3185 *
3186 * A shorthand reference to the namespace associated with the node.
3187 *
3188 * Returns the prefix or NULL if not available, the string is deallocated
3189 * with the reader.
3190 */
3191const xmlChar *
3192xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3193 xmlNodePtr node;
3194 if ((reader == NULL) || (reader->node == NULL))
3195 return(NULL);
3196 if (reader->curnode != NULL)
3197 node = reader->curnode;
3198 else
3199 node = reader->node;
3200 if (node->type == XML_NAMESPACE_DECL) {
3201 xmlNsPtr ns = (xmlNsPtr) node;
3202 if (ns->prefix == NULL)
3203 return(NULL);
3204 return(CONSTSTR(BAD_CAST "xmlns"));
3205 }
3206 if ((node->type != XML_ELEMENT_NODE) &&
3207 (node->type != XML_ATTRIBUTE_NODE))
3208 return(NULL);
3209 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3210 return(CONSTSTR(node->ns->prefix));
3211 return(NULL);
3212}
3213
3214/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003215 * xmlTextReaderNamespaceUri:
3216 * @reader: the xmlTextReaderPtr used
3217 *
3218 * The URI defining the namespace associated with the node.
3219 *
3220 * Returns the namespace URI or NULL if not available
3221 */
3222xmlChar *
3223xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003224 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003225 if ((reader == NULL) || (reader->node == NULL))
3226 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003227 if (reader->curnode != NULL)
3228 node = reader->curnode;
3229 else
3230 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003231 if (node->type == XML_NAMESPACE_DECL)
3232 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003233 if ((node->type != XML_ELEMENT_NODE) &&
3234 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003235 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003236 if (node->ns != NULL)
3237 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003238 return(NULL);
3239}
3240
3241/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003242 * xmlTextReaderConstNamespaceUri:
3243 * @reader: the xmlTextReaderPtr used
3244 *
3245 * The URI defining the namespace associated with the node.
3246 *
3247 * Returns the namespace URI or NULL if not available, the string
3248 * will be deallocated with the reader
3249 */
3250const xmlChar *
3251xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3252 xmlNodePtr node;
3253 if ((reader == NULL) || (reader->node == NULL))
3254 return(NULL);
3255 if (reader->curnode != NULL)
3256 node = reader->curnode;
3257 else
3258 node = reader->node;
3259 if (node->type == XML_NAMESPACE_DECL)
3260 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3261 if ((node->type != XML_ELEMENT_NODE) &&
3262 (node->type != XML_ATTRIBUTE_NODE))
3263 return(NULL);
3264 if (node->ns != NULL)
3265 return(CONSTSTR(node->ns->href));
3266 return(NULL);
3267}
3268
3269/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003270 * xmlTextReaderBaseUri:
3271 * @reader: the xmlTextReaderPtr used
3272 *
3273 * The base URI of the node.
3274 *
3275 * Returns the base URI or NULL if not available
3276 */
3277xmlChar *
3278xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3279 if ((reader == NULL) || (reader->node == NULL))
3280 return(NULL);
3281 return(xmlNodeGetBase(NULL, reader->node));
3282}
3283
3284/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003285 * xmlTextReaderConstBaseUri:
3286 * @reader: the xmlTextReaderPtr used
3287 *
3288 * The base URI of the node.
3289 *
3290 * Returns the base URI or NULL if not available, the string
3291 * will be deallocated with the reader
3292 */
3293const xmlChar *
3294xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3295 xmlChar *tmp;
3296 const xmlChar *ret;
3297
3298 if ((reader == NULL) || (reader->node == NULL))
3299 return(NULL);
3300 tmp = xmlNodeGetBase(NULL, reader->node);
3301 if (tmp == NULL)
3302 return(NULL);
3303 ret = CONSTSTR(tmp);
3304 xmlFree(tmp);
3305 return(ret);
3306}
3307
3308/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003309 * xmlTextReaderDepth:
3310 * @reader: the xmlTextReaderPtr used
3311 *
3312 * The depth of the node in the tree.
3313 *
3314 * Returns the depth or -1 in case of error
3315 */
3316int
3317xmlTextReaderDepth(xmlTextReaderPtr reader) {
3318 if (reader == NULL)
3319 return(-1);
3320 if (reader->node == NULL)
3321 return(0);
3322
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003323 if (reader->curnode != NULL) {
3324 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3325 (reader->curnode->type == XML_NAMESPACE_DECL))
3326 return(reader->depth + 1);
3327 return(reader->depth + 2);
3328 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003329 return(reader->depth);
3330}
3331
3332/**
3333 * xmlTextReaderHasAttributes:
3334 * @reader: the xmlTextReaderPtr used
3335 *
3336 * Whether the node has attributes.
3337 *
3338 * Returns 1 if true, 0 if false, and -1 in case or error
3339 */
3340int
3341xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003342 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003343 if (reader == NULL)
3344 return(-1);
3345 if (reader->node == NULL)
3346 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003347 if (reader->curnode != NULL)
3348 node = reader->curnode;
3349 else
3350 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003351
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003352 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003353 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003354 return(1);
3355 /* TODO: handle the xmlDecl */
3356 return(0);
3357}
3358
3359/**
3360 * xmlTextReaderHasValue:
3361 * @reader: the xmlTextReaderPtr used
3362 *
3363 * Whether the node can have a text value.
3364 *
3365 * Returns 1 if true, 0 if false, and -1 in case or error
3366 */
3367int
3368xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003369 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003370 if (reader == NULL)
3371 return(-1);
3372 if (reader->node == NULL)
3373 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003374 if (reader->curnode != NULL)
3375 node = reader->curnode;
3376 else
3377 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003378
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003379 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003380 case XML_ATTRIBUTE_NODE:
3381 case XML_TEXT_NODE:
3382 case XML_CDATA_SECTION_NODE:
3383 case XML_PI_NODE:
3384 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003385 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003386 return(1);
3387 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003388 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003389 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003390 return(0);
3391}
3392
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003393/**
3394 * xmlTextReaderValue:
3395 * @reader: the xmlTextReaderPtr used
3396 *
3397 * Provides the text value of the node if present
3398 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003399 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003400 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003401 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003402xmlChar *
3403xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003404 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003405 if (reader == NULL)
3406 return(NULL);
3407 if (reader->node == NULL)
3408 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003409 if (reader->curnode != NULL)
3410 node = reader->curnode;
3411 else
3412 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003413
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003414 switch (node->type) {
3415 case XML_NAMESPACE_DECL:
3416 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003417 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003418 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003419
3420 if (attr->parent != NULL)
3421 return (xmlNodeListGetString
3422 (attr->parent->doc, attr->children, 1));
3423 else
3424 return (xmlNodeListGetString(NULL, attr->children, 1));
3425 break;
3426 }
3427 case XML_TEXT_NODE:
3428 case XML_CDATA_SECTION_NODE:
3429 case XML_PI_NODE:
3430 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003431 if (node->content != NULL)
3432 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003433 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003434 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003435 }
3436 return(NULL);
3437}
3438
3439/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003440 * xmlTextReaderConstValue:
3441 * @reader: the xmlTextReaderPtr used
3442 *
3443 * Provides the text value of the node if present
3444 *
3445 * Returns the string or NULL if not available. The result will be
3446 * deallocated on the next Read() operation.
3447 */
3448const xmlChar *
3449xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3450 xmlNodePtr node;
3451 if (reader == NULL)
3452 return(NULL);
3453 if (reader->node == NULL)
3454 return(NULL);
3455 if (reader->curnode != NULL)
3456 node = reader->curnode;
3457 else
3458 node = reader->node;
3459
3460 switch (node->type) {
3461 case XML_NAMESPACE_DECL:
3462 return(((xmlNsPtr) node)->href);
3463 case XML_ATTRIBUTE_NODE:{
3464 xmlAttrPtr attr = (xmlAttrPtr) node;
3465
3466 if ((attr->children != NULL) &&
3467 (attr->children->type == XML_TEXT_NODE) &&
3468 (attr->children->next == NULL))
3469 return(attr->children->content);
3470 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003471 if (reader->buffer == NULL)
3472 reader->buffer = xmlBufferCreateSize(100);
3473 if (reader->buffer == NULL) {
3474 xmlGenericError(xmlGenericErrorContext,
3475 "xmlTextReaderSetup : malloc failed\n");
3476 return (NULL);
3477 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003478 reader->buffer->use = 0;
3479 xmlNodeBufGetContent(reader->buffer, node);
3480 return(reader->buffer->content);
3481 }
3482 break;
3483 }
3484 case XML_TEXT_NODE:
3485 case XML_CDATA_SECTION_NODE:
3486 case XML_PI_NODE:
3487 case XML_COMMENT_NODE:
3488 return(node->content);
3489 default:
3490 break;
3491 }
3492 return(NULL);
3493}
3494
3495/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003496 * xmlTextReaderIsDefault:
3497 * @reader: the xmlTextReaderPtr used
3498 *
3499 * Whether an Attribute node was generated from the default value
3500 * defined in the DTD or schema.
3501 *
3502 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3503 */
3504int
3505xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3506 if (reader == NULL)
3507 return(-1);
3508 return(0);
3509}
3510
3511/**
3512 * xmlTextReaderQuoteChar:
3513 * @reader: the xmlTextReaderPtr used
3514 *
3515 * The quotation mark character used to enclose the value of an attribute.
3516 *
3517 * Returns " or ' and -1 in case of error
3518 */
3519int
3520xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3521 if (reader == NULL)
3522 return(-1);
3523 /* TODO maybe lookup the attribute value for " first */
3524 return((int) '"');
3525}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003526
3527/**
3528 * xmlTextReaderXmlLang:
3529 * @reader: the xmlTextReaderPtr used
3530 *
3531 * The xml:lang scope within which the node resides.
3532 *
3533 * Returns the xml:lang value or NULL if none exists.
3534 */
3535xmlChar *
3536xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3537 if (reader == NULL)
3538 return(NULL);
3539 if (reader->node == NULL)
3540 return(NULL);
3541 return(xmlNodeGetLang(reader->node));
3542}
3543
Daniel Veillard67df8092002-12-16 22:04:11 +00003544/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003545 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003546 * @reader: the xmlTextReaderPtr used
3547 *
3548 * The xml:lang scope within which the node resides.
3549 *
3550 * Returns the xml:lang value or NULL if none exists.
3551 */
3552const xmlChar *
3553xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3554 xmlChar *tmp;
3555 const xmlChar *ret;
3556
3557 if (reader == NULL)
3558 return(NULL);
3559 if (reader->node == NULL)
3560 return(NULL);
3561 tmp = xmlNodeGetLang(reader->node);
3562 if (tmp == NULL)
3563 return(NULL);
3564 ret = CONSTSTR(tmp);
3565 xmlFree(tmp);
3566 return(ret);
3567}
3568
3569/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003570 * xmlTextReaderConstString:
3571 * @reader: the xmlTextReaderPtr used
3572 * @str: the string to intern.
3573 *
3574 * Get an interned string from the reader, allows for example to
3575 * speedup string name comparisons
3576 *
3577 * Returns an interned copy of the string or NULL in case of error. The
3578 * string will be deallocated with the reader.
3579 */
3580const xmlChar *
3581xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3582 if (reader == NULL)
3583 return(NULL);
3584 return(CONSTSTR(str));
3585}
3586
3587/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003588 * xmlTextReaderNormalization:
3589 * @reader: the xmlTextReaderPtr used
3590 *
3591 * The value indicating whether to normalize white space and attribute values.
3592 * Since attribute value and end of line normalizations are a MUST in the XML
3593 * specification only the value true is accepted. The broken bahaviour of
3594 * accepting out of range character entities like &#0; is of course not
3595 * supported either.
3596 *
3597 * Returns 1 or -1 in case of error.
3598 */
3599int
3600xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3601 if (reader == NULL)
3602 return(-1);
3603 return(1);
3604}
3605
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003606/************************************************************************
3607 * *
3608 * Extensions to the base APIs *
3609 * *
3610 ************************************************************************/
3611
3612/**
3613 * xmlTextReaderSetParserProp:
3614 * @reader: the xmlTextReaderPtr used
3615 * @prop: the xmlParserProperties to set
3616 * @value: usually 0 or 1 to (de)activate it
3617 *
3618 * Change the parser processing behaviour by changing some of its internal
3619 * properties. Note that some properties can only be changed before any
3620 * read has been done.
3621 *
3622 * Returns 0 if the call was successful, or -1 in case of error
3623 */
3624int
3625xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3626 xmlParserProperties p = (xmlParserProperties) prop;
3627 xmlParserCtxtPtr ctxt;
3628
3629 if ((reader == NULL) || (reader->ctxt == NULL))
3630 return(-1);
3631 ctxt = reader->ctxt;
3632
3633 switch (p) {
3634 case XML_PARSER_LOADDTD:
3635 if (value != 0) {
3636 if (ctxt->loadsubset == 0) {
3637 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3638 return(-1);
3639 ctxt->loadsubset = XML_DETECT_IDS;
3640 }
3641 } else {
3642 ctxt->loadsubset = 0;
3643 }
3644 return(0);
3645 case XML_PARSER_DEFAULTATTRS:
3646 if (value != 0) {
3647 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3648 } else {
3649 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3650 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3651 }
3652 return(0);
3653 case XML_PARSER_VALIDATE:
3654 if (value != 0) {
3655 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003656 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003657 } else {
3658 ctxt->validate = 0;
3659 }
3660 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003661 case XML_PARSER_SUBST_ENTITIES:
3662 if (value != 0) {
3663 ctxt->replaceEntities = 1;
3664 } else {
3665 ctxt->replaceEntities = 0;
3666 }
3667 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003668 }
3669 return(-1);
3670}
3671
3672/**
3673 * xmlTextReaderGetParserProp:
3674 * @reader: the xmlTextReaderPtr used
3675 * @prop: the xmlParserProperties to get
3676 *
3677 * Read the parser internal property.
3678 *
3679 * Returns the value, usually 0 or 1, or -1 in case of error.
3680 */
3681int
3682xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3683 xmlParserProperties p = (xmlParserProperties) prop;
3684 xmlParserCtxtPtr ctxt;
3685
3686 if ((reader == NULL) || (reader->ctxt == NULL))
3687 return(-1);
3688 ctxt = reader->ctxt;
3689
3690 switch (p) {
3691 case XML_PARSER_LOADDTD:
3692 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3693 return(1);
3694 return(0);
3695 case XML_PARSER_DEFAULTATTRS:
3696 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3697 return(1);
3698 return(0);
3699 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003700 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003701 case XML_PARSER_SUBST_ENTITIES:
3702 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003703 }
3704 return(-1);
3705}
3706
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003707
Daniel Veillarde18fc182002-12-28 22:56:33 +00003708/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003709 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003710 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003711 *
3712 * Provide the line number of the current parsing point.
3713 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003714 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003715 */
3716int
3717xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3718{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003719 if ((reader == NULL) || (reader->ctxt == NULL) ||
3720 (reader->ctxt->input == NULL)) {
3721 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003722 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003723 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003724}
3725
3726/**
3727 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003728 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003729 *
3730 * Provide the column number of the current parsing point.
3731 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003732 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003733 */
3734int
3735xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3736{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003737 if ((reader == NULL) || (reader->ctxt == NULL) ||
3738 (reader->ctxt->input == NULL)) {
3739 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003740 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003741 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003742}
3743
3744/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003745 * xmlTextReaderCurrentNode:
3746 * @reader: the xmlTextReaderPtr used
3747 *
3748 * Hacking interface allowing to get the xmlNodePtr correponding to the
3749 * current node being accessed by the xmlTextReader. This is dangerous
3750 * because the underlying node may be destroyed on the next Reads.
3751 *
3752 * Returns the xmlNodePtr or NULL in case of error.
3753 */
3754xmlNodePtr
3755xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3756 if (reader == NULL)
3757 return(NULL);
3758
3759 if (reader->curnode != NULL)
3760 return(reader->curnode);
3761 return(reader->node);
3762}
3763
3764/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003765 * xmlTextReaderPreserve:
3766 * @reader: the xmlTextReaderPtr used
3767 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003768 * This tells the XML Reader to preserve the current node.
3769 * The caller must also use xmlTextReaderCurrentDoc() to
3770 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003771 *
3772 * Returns the xmlNodePtr or NULL in case of error.
3773 */
3774xmlNodePtr
3775xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3776 xmlNodePtr cur, parent;
3777
3778 if (reader == NULL)
3779 return(NULL);
3780
3781 if (reader->curnode != NULL)
3782 cur = reader->curnode;
3783 else
3784 cur = reader->node;
3785 if (cur == NULL)
3786 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003787
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003788 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003789 cur->extra |= NODE_IS_PRESERVED;
3790 cur->extra |= NODE_IS_SPRESERVED;
3791 }
3792 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003793
3794 parent = cur->parent;;
3795 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003796 if (parent->type == XML_ELEMENT_NODE)
3797 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003798 parent = parent->parent;
3799 }
3800 return(cur);
3801}
3802
Daniel Veillard1e906612003-12-05 14:57:46 +00003803#ifdef LIBXML_PATTERN_ENABLED
3804/**
3805 * xmlTextReaderPreservePattern:
3806 * @reader: the xmlTextReaderPtr used
3807 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003808 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003809 *
3810 * This tells the XML Reader to preserve all nodes matched by the
3811 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3812 * keep an handle on the resulting document once parsing has finished
3813 *
3814 * Returns a positive number in case of success and -1 in case of error
3815 */
3816int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003817xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3818 const xmlChar **namespaces)
3819{
Daniel Veillard1e906612003-12-05 14:57:46 +00003820 xmlPatternPtr comp;
3821
3822 if ((reader == NULL) || (pattern == NULL))
3823 return(-1);
3824
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003825 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003826 if (comp == NULL)
3827 return(-1);
3828
3829 if (reader->patternMax <= 0) {
3830 reader->patternMax = 4;
3831 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3832 sizeof(reader->patternTab[0]));
3833 if (reader->patternTab == NULL) {
3834 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3835 return (-1);
3836 }
3837 }
3838 if (reader->patternNr >= reader->patternMax) {
3839 xmlPatternPtr *tmp;
3840 reader->patternMax *= 2;
3841 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3842 reader->patternMax *
3843 sizeof(reader->patternTab[0]));
3844 if (tmp == NULL) {
3845 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3846 reader->patternMax /= 2;
3847 return (-1);
3848 }
3849 reader->patternTab = tmp;
3850 }
3851 reader->patternTab[reader->patternNr] = comp;
3852 return(reader->patternNr++);
3853}
3854#endif
3855
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003856/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003857 * xmlTextReaderCurrentDoc:
3858 * @reader: the xmlTextReaderPtr used
3859 *
3860 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003861 * current document being accessed by the xmlTextReader.
3862 * NOTE: as a result of this call, the reader will not destroy the
3863 * associated XML document and calling xmlFreeDoc() on the result
3864 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003865 *
3866 * Returns the xmlDocPtr or NULL in case of error.
3867 */
3868xmlDocPtr
3869xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003870 if (reader == NULL)
3871 return(NULL);
3872 if (reader->doc != NULL)
3873 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003874 if ((reader == NULL) || (reader->ctxt == NULL) ||
3875 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003876 return(NULL);
3877
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003878 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003879 return(reader->ctxt->myDoc);
3880}
3881
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003882#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003883/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003884 * xmlTextReaderRelaxNGSetSchema:
3885 * @reader: the xmlTextReaderPtr used
3886 * @schema: a precompiled RelaxNG schema
3887 *
3888 * Use RelaxNG to validate the document as it is processed.
3889 * Activation is only possible before the first Read().
3890 * if @schema is NULL, then RelaxNG validation is desactivated.
3891 @ The @schema should not be freed until the reader is deallocated
3892 * or its use has been deactivated.
3893 *
3894 * Returns 0 in case the RelaxNG validation could be (des)activated and
3895 * -1 in case of error.
3896 */
3897int
3898xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00003899 if (reader == NULL)
3900 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003901 if (schema == NULL) {
3902 if (reader->rngSchemas != NULL) {
3903 xmlRelaxNGFree(reader->rngSchemas);
3904 reader->rngSchemas = NULL;
3905 }
3906 if (reader->rngValidCtxt != NULL) {
3907 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3908 reader->rngValidCtxt = NULL;
3909 }
3910 return(0);
3911 }
3912 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3913 return(-1);
3914 if (reader->rngSchemas != NULL) {
3915 xmlRelaxNGFree(reader->rngSchemas);
3916 reader->rngSchemas = NULL;
3917 }
3918 if (reader->rngValidCtxt != NULL) {
3919 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3920 reader->rngValidCtxt = NULL;
3921 }
3922 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3923 if (reader->rngValidCtxt == NULL)
3924 return(-1);
3925 if (reader->errorFunc != NULL) {
3926 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3927 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3928 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3929 reader->errorFuncArg);
3930 }
3931 reader->rngValidErrors = 0;
3932 reader->rngFullNode = NULL;
3933 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3934 return(0);
3935}
3936
3937/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00003938 * xmlTextReaderSetSchema:
3939 * @reader: the xmlTextReaderPtr used
3940 * @schema: a precompiled Schema schema
3941 *
3942 * Use XSD Schema to validate the document as it is processed.
3943 * Activation is only possible before the first Read().
3944 * if @schema is NULL, then Schema validation is desactivated.
3945 @ The @schema should not be freed until the reader is deallocated
3946 * or its use has been deactivated.
3947 *
3948 * Returns 0 in case the Schema validation could be (des)activated and
3949 * -1 in case of error.
3950 */
3951int
3952xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
3953 if (reader == NULL)
3954 return(-1);
3955 if (schema == NULL) {
3956 if (reader->xsdPlug != NULL) {
3957 xmlSchemaSAXUnplug(reader->xsdPlug);
3958 reader->xsdPlug = NULL;
3959 }
3960 if (reader->xsdValidCtxt != NULL) {
3961 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
3962 reader->xsdValidCtxt = NULL;
3963 }
3964 if (reader->xsdSchemas != NULL) {
3965 xmlSchemaFree(reader->xsdSchemas);
3966 reader->xsdSchemas = NULL;
3967 }
3968 return(0);
3969 }
3970 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3971 return(-1);
3972 if (reader->xsdPlug != NULL) {
3973 xmlSchemaSAXUnplug(reader->xsdPlug);
3974 reader->xsdPlug = NULL;
3975 }
3976 if (reader->xsdValidCtxt != NULL) {
3977 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
3978 reader->xsdValidCtxt = NULL;
3979 }
3980 if (reader->xsdSchemas != NULL) {
3981 xmlSchemaFree(reader->xsdSchemas);
3982 reader->xsdSchemas = NULL;
3983 }
3984 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
3985 if (reader->xsdValidCtxt == NULL) {
3986 xmlSchemaFree(reader->xsdSchemas);
3987 reader->xsdSchemas = NULL;
3988 return(-1);
3989 }
3990 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
3991 &(reader->ctxt->sax),
3992 &(reader->ctxt->userData));
3993 if (reader->xsdPlug == NULL) {
3994 xmlSchemaFree(reader->xsdSchemas);
3995 reader->xsdSchemas = NULL;
3996 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
3997 reader->xsdValidCtxt = NULL;
3998 return(-1);
3999 }
4000 if (reader->errorFunc != NULL) {
4001 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4002 (xmlSchemaValidityErrorFunc)reader->errorFunc,
4003 (xmlSchemaValidityWarningFunc) reader->errorFunc,
4004 reader->errorFuncArg);
4005 }
4006 reader->xsdValidErrors = 0;
4007 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4008 return(0);
4009}
4010
4011/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004012 * xmlTextReaderRelaxNGValidate:
4013 * @reader: the xmlTextReaderPtr used
4014 * @rng: the path to a RelaxNG schema or NULL
4015 *
4016 * Use RelaxNG to validate the document as it is processed.
4017 * Activation is only possible before the first Read().
4018 * if @rng is NULL, then RelaxNG validation is desactivated.
4019 *
4020 * Returns 0 in case the RelaxNG validation could be (des)activated and
4021 * -1 in case of error.
4022 */
4023int
4024xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4025 xmlRelaxNGParserCtxtPtr ctxt;
4026
4027 if (reader == NULL)
4028 return(-1);
4029
4030 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004031 if (reader->rngValidCtxt != NULL) {
4032 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4033 reader->rngValidCtxt = NULL;
4034 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004035 if (reader->rngSchemas != NULL) {
4036 xmlRelaxNGFree(reader->rngSchemas);
4037 reader->rngSchemas = NULL;
4038 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004039 return(0);
4040 }
4041 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4042 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004043 if (reader->rngSchemas != NULL) {
4044 xmlRelaxNGFree(reader->rngSchemas);
4045 reader->rngSchemas = NULL;
4046 }
4047 if (reader->rngValidCtxt != NULL) {
4048 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4049 reader->rngValidCtxt = NULL;
4050 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004051 ctxt = xmlRelaxNGNewParserCtxt(rng);
4052 if (reader->errorFunc != NULL) {
4053 xmlRelaxNGSetParserErrors(ctxt,
4054 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
4055 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
4056 reader->errorFuncArg);
4057 }
4058 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4059 xmlRelaxNGFreeParserCtxt(ctxt);
4060 if (reader->rngSchemas == NULL)
4061 return(-1);
4062 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004063 if (reader->rngValidCtxt == NULL) {
4064 xmlRelaxNGFree(reader->rngSchemas);
4065 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004066 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004067 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004068 if (reader->errorFunc != NULL) {
4069 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4070 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
4071 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
4072 reader->errorFuncArg);
4073 }
4074 reader->rngValidErrors = 0;
4075 reader->rngFullNode = NULL;
4076 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4077 return(0);
4078}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004079
4080/**
4081 * xmlTextReaderSchemaValidate:
4082 * @reader: the xmlTextReaderPtr used
4083 * @xsd: the path to a W3C XSD schema or NULL
4084 *
4085 * Use W3C XSD schema to validate the document as it is processed.
4086 * Activation is only possible before the first Read().
4087 * if @xsd is NULL, then RelaxNG validation is desactivated.
4088 *
4089 * Returns 0 in case the schemas validation could be (des)activated and
4090 * -1 in case of error.
4091 */
4092int
4093xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4094 xmlSchemaParserCtxtPtr ctxt;
4095
4096 if (reader == NULL)
4097 return(-1);
4098
4099 if (xsd == NULL) {
4100 if (reader->xsdPlug != NULL) {
4101 xmlSchemaSAXUnplug(reader->xsdPlug);
4102 reader->xsdPlug = NULL;
4103 }
4104 if (reader->xsdSchemas != NULL) {
4105 xmlSchemaFree(reader->xsdSchemas);
4106 reader->xsdSchemas = NULL;
4107 }
4108 if (reader->xsdValidCtxt != NULL) {
4109 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4110 reader->xsdValidCtxt = NULL;
4111 }
4112 return(0);
4113 }
4114 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4115 (reader->ctxt == NULL))
4116 return(-1);
4117 if (reader->xsdPlug != NULL) {
4118 xmlSchemaSAXUnplug(reader->xsdPlug);
4119 reader->xsdPlug = NULL;
4120 }
4121 if (reader->xsdValidCtxt != NULL) {
4122 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4123 reader->xsdValidCtxt = NULL;
4124 }
4125 if (reader->xsdSchemas != NULL) {
4126 xmlSchemaFree(reader->xsdSchemas);
4127 reader->xsdSchemas = NULL;
4128 }
4129 ctxt = xmlSchemaNewParserCtxt(xsd);
4130 if (reader->errorFunc != NULL) {
4131 xmlSchemaSetParserErrors(ctxt,
4132 (xmlSchemaValidityErrorFunc) reader->errorFunc,
4133 (xmlSchemaValidityWarningFunc) reader->errorFunc,
4134 reader->errorFuncArg);
4135 }
4136 reader->xsdSchemas = xmlSchemaParse(ctxt);
4137 xmlSchemaFreeParserCtxt(ctxt);
4138 if (reader->xsdSchemas == NULL)
4139 return(-1);
4140 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4141 if (reader->xsdValidCtxt == NULL) {
4142 xmlSchemaFree(reader->xsdSchemas);
4143 reader->xsdSchemas = NULL;
4144 return(-1);
4145 }
4146 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4147 &(reader->ctxt->sax),
4148 &(reader->ctxt->userData));
4149 if (reader->xsdPlug == NULL) {
4150 xmlSchemaFree(reader->xsdSchemas);
4151 reader->xsdSchemas = NULL;
4152 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4153 reader->xsdValidCtxt = NULL;
4154 return(-1);
4155 }
4156 if (reader->errorFunc != NULL) {
4157 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4158 (xmlSchemaValidityErrorFunc)reader->errorFunc,
4159 (xmlSchemaValidityWarningFunc) reader->errorFunc,
4160 reader->errorFuncArg);
4161 }
4162 reader->xsdValidErrors = 0;
4163 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4164 return(0);
4165}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004166#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004167
Daniel Veillarde2811272004-10-19 09:04:23 +00004168/**
4169 * xmlTextReaderIsNamespaceDecl:
4170 * @reader: the xmlTextReaderPtr used
4171 *
4172 * Determine whether the current node is a namespace declaration
4173 * rather than a regular attribute.
4174 *
4175 * Returns 1 if the current node is a namespace declaration, 0 if it
4176 * is a regular attribute or other type of node, or -1 in case of
4177 * error.
4178 */
4179int
4180xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4181 xmlNodePtr node;
4182 if (reader == NULL)
4183 return(-1);
4184 if (reader->node == NULL)
4185 return(-1);
4186 if (reader->curnode != NULL)
4187 node = reader->curnode;
4188 else
4189 node = reader->node;
4190
4191 if (XML_NAMESPACE_DECL == node->type)
4192 return(1);
4193 else
4194 return(0);
4195}
4196
4197/**
4198 * xmlTextReaderConstXmlVersion:
4199 * @reader: the xmlTextReaderPtr used
4200 *
4201 * Determine the XML version of the document being read.
4202 *
4203 * Returns a string containing the XML version of the document or NULL
4204 * in case of error. The string is deallocated with the reader.
4205 */
4206const xmlChar *
4207xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4208 xmlDocPtr doc = NULL;
4209 if (reader == NULL)
4210 return(NULL);
4211 if (reader->doc != NULL)
4212 doc = reader->doc;
4213 else if (reader->ctxt != NULL)
4214 doc = reader->ctxt->myDoc;
4215 if (doc == NULL)
4216 return(NULL);
4217
4218 if (doc->version == NULL)
4219 return(NULL);
4220 else
4221 return(CONSTSTR(doc->version));
4222}
4223
4224/**
4225 * xmlTextReaderStandalone:
4226 * @reader: the xmlTextReaderPtr used
4227 *
4228 * Determine the standalone status of the document being read.
4229 *
4230 * Returns 1 if the document was declared to be standalone, 0 if it
4231 * was declared to be not standalone, or -1 if the document did not
4232 * specify its standalone status or in case of error.
4233 */
4234int
4235xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4236 xmlDocPtr doc = NULL;
4237 if (reader == NULL)
4238 return(-1);
4239 if (reader->doc != NULL)
4240 doc = reader->doc;
4241 else if (reader->ctxt != NULL)
4242 doc = reader->ctxt->myDoc;
4243 if (doc == NULL)
4244 return(-1);
4245
4246 return(doc->standalone);
4247}
4248
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004249/************************************************************************
4250 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004251 * Error Handling Extensions *
4252 * *
4253 ************************************************************************/
4254
4255/* helper to build a xmlMalloc'ed string from a format and va_list */
4256static char *
4257xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4258 int size;
4259 int chars;
4260 char *larger;
4261 char *str;
4262
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004263 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004264 if (str == NULL) {
4265 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4266 return NULL;
4267 }
4268
4269 size = 150;
4270
4271 while (1) {
4272 chars = vsnprintf(str, size, msg, ap);
4273 if ((chars > -1) && (chars < size))
4274 break;
4275 if (chars > -1)
4276 size += chars + 1;
4277 else
4278 size += 100;
4279 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4280 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4281 xmlFree(str);
4282 return NULL;
4283 }
4284 str = larger;
4285 }
4286
4287 return str;
4288}
4289
Daniel Veillard417be3a2003-01-20 21:26:34 +00004290/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004291 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004292 * @locator: the xmlTextReaderLocatorPtr used
4293 *
4294 * Obtain the line number for the given locator.
4295 *
4296 * Returns the line number or -1 in case of error.
4297 */
4298int
4299xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4300 /* we know that locator is a xmlParserCtxtPtr */
4301 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4302 int ret = -1;
4303
Daniel Veillardce682bc2004-11-05 17:22:25 +00004304 if (locator == NULL)
4305 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004306 if (ctx->node != NULL) {
4307 ret = xmlGetLineNo(ctx->node);
4308 }
4309 else {
4310 /* inspired from error.c */
4311 xmlParserInputPtr input;
4312 input = ctx->input;
4313 if ((input->filename == NULL) && (ctx->inputNr > 1))
4314 input = ctx->inputTab[ctx->inputNr - 2];
4315 if (input != NULL) {
4316 ret = input->line;
4317 }
4318 else {
4319 ret = -1;
4320 }
4321 }
4322
4323 return ret;
4324}
4325
4326/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004327 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004328 * @locator: the xmlTextReaderLocatorPtr used
4329 *
4330 * Obtain the base URI for the given locator.
4331 *
4332 * Returns the base URI or NULL in case of error.
4333 */
4334xmlChar *
4335xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4336 /* we know that locator is a xmlParserCtxtPtr */
4337 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4338 xmlChar *ret = NULL;
4339
Daniel Veillardce682bc2004-11-05 17:22:25 +00004340 if (locator == NULL)
4341 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004342 if (ctx->node != NULL) {
4343 ret = xmlNodeGetBase(NULL,ctx->node);
4344 }
4345 else {
4346 /* inspired from error.c */
4347 xmlParserInputPtr input;
4348 input = ctx->input;
4349 if ((input->filename == NULL) && (ctx->inputNr > 1))
4350 input = ctx->inputTab[ctx->inputNr - 2];
4351 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004352 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004353 }
4354 else {
4355 ret = NULL;
4356 }
4357 }
4358
4359 return ret;
4360}
4361
Daniel Veillard26f70262003-01-16 22:45:08 +00004362static void
William M. Brack899e64a2003-09-26 18:03:42 +00004363xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004364 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4365 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4366
William M. Bracka3215c72004-07-31 16:24:01 +00004367 if (str != NULL) {
4368 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004369 reader->errorFunc(reader->errorFuncArg,
4370 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004371 severity,
4372 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004373 xmlFree(str);
4374 }
4375}
4376
4377static void
William M. Brack93d004f2004-02-03 00:14:10 +00004378xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4379 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4380 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4381
4382 if (error && reader->sErrorFunc) {
4383 reader->sErrorFunc(reader->errorFuncArg,
4384 (xmlErrorPtr) error);
4385 }
4386}
4387
4388static void
Daniel Veillard26f70262003-01-16 22:45:08 +00004389xmlTextReaderError(void *ctxt, const char *msg, ...) {
4390 va_list ap;
4391
4392 va_start(ap,msg);
4393 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004394 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004395 xmlTextReaderBuildMessage(msg,ap));
4396 va_end(ap);
4397
4398}
4399
4400static void
4401xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4402 va_list ap;
4403
4404 va_start(ap,msg);
4405 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004406 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004407 xmlTextReaderBuildMessage(msg,ap));
4408 va_end(ap);
4409}
4410
4411static void
4412xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4413 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004414 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004415
Daniel Veillard417be3a2003-01-20 21:26:34 +00004416 if ((len > 1) && (msg[len - 2] != ':')) {
4417 /*
4418 * some callbacks only report locator information:
4419 * skip them (mimicking behaviour in error.c)
4420 */
4421 va_start(ap,msg);
4422 xmlTextReaderGenericError(ctxt,
4423 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4424 xmlTextReaderBuildMessage(msg,ap));
4425 va_end(ap);
4426 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004427}
4428
4429static void
4430xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4431 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004432 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004433
Daniel Veillard417be3a2003-01-20 21:26:34 +00004434 if ((len != 0) && (msg[len - 1] != ':')) {
4435 /*
4436 * some callbacks only report locator information:
4437 * skip them (mimicking behaviour in error.c)
4438 */
4439 va_start(ap,msg);
4440 xmlTextReaderGenericError(ctxt,
4441 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4442 xmlTextReaderBuildMessage(msg,ap));
4443 va_end(ap);
4444 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004445}
4446
4447/**
4448 * xmlTextReaderSetErrorHandler:
4449 * @reader: the xmlTextReaderPtr used
4450 * @f: the callback function to call on error and warnings
4451 * @arg: a user argument to pass to the callback function
4452 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004453 * Register a callback function that will be called on error and warnings.
4454 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004455 * If @f is NULL, the default error and warning handlers are restored.
4456 */
4457void
4458xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4459 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004460 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004461 if (f != NULL) {
4462 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004463 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004464 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4465 reader->ctxt->sax->warning = xmlTextReaderWarning;
4466 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4467 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004468 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004469 reader->errorFuncArg = arg;
4470 }
4471 else {
4472 /* restore defaults */
4473 reader->ctxt->sax->error = xmlParserError;
4474 reader->ctxt->vctxt.error = xmlParserValidityError;
4475 reader->ctxt->sax->warning = xmlParserWarning;
4476 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4477 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004478 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004479 reader->errorFuncArg = NULL;
4480 }
4481}
4482
Daniel Veillard417be3a2003-01-20 21:26:34 +00004483/**
William M. Brack93d004f2004-02-03 00:14:10 +00004484* xmlTextReaderSetStructuredErrorHandler:
4485 * @reader: the xmlTextReaderPtr used
4486 * @f: the callback function to call on error and warnings
4487 * @arg: a user argument to pass to the callback function
4488 *
4489 * Register a callback function that will be called on error and warnings.
4490 *
4491 * If @f is NULL, the default error and warning handlers are restored.
4492 */
4493void
4494xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4495 xmlStructuredErrorFunc f,
4496 void *arg) {
4497 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004498 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004499 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4500 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4501 reader->ctxt->sax->warning = xmlTextReaderWarning;
4502 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4503 reader->sErrorFunc = f;
4504 reader->errorFunc = NULL;
4505 reader->errorFuncArg = arg;
4506 }
4507 else {
4508 /* restore defaults */
4509 reader->ctxt->sax->error = xmlParserError;
4510 reader->ctxt->sax->serror = NULL;
4511 reader->ctxt->vctxt.error = xmlParserValidityError;
4512 reader->ctxt->sax->warning = xmlParserWarning;
4513 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4514 reader->errorFunc = NULL;
4515 reader->sErrorFunc = NULL;
4516 reader->errorFuncArg = NULL;
4517 }
4518}
4519
4520/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004521 * xmlTextReaderIsValid:
4522 * @reader: the xmlTextReaderPtr used
4523 *
4524 * Retrieve the validity status from the parser context
4525 *
4526 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4527 */
4528int
4529xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004530 if (reader == NULL) return(-1);
4531#ifdef LIBXML_SCHEMAS_ENABLED
4532 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4533 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004534 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4535 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004536#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004537 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004538 return(reader->ctxt->valid);
4539 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004540}
4541
4542/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004543 * xmlTextReaderGetErrorHandler:
4544 * @reader: the xmlTextReaderPtr used
4545 * @f: the callback function or NULL is no callback has been registered
4546 * @arg: a user argument
4547 *
4548 * Retrieve the error callback function and user argument.
4549 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004550void
4551xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4552 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004553 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004554 if (f != NULL) *f = reader->errorFunc;
4555 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004556}
4557
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004558
4559/************************************************************************
4560 * *
4561 * New set (2.6.0) of simpler and more flexible APIs *
4562 * *
4563 ************************************************************************/
4564
4565/**
4566 * xmlTextReaderSetup:
4567 * @reader: an XML reader
4568 * @URL: the base URL to use for the document
4569 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004570 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004571 * @reuse: keep the context for reuse
4572 *
4573 * Setup an XML reader with new options
4574 *
4575 * Returns 0 in case of success and -1 in case of error.
4576 */
4577static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004578xmlTextReaderSetup(xmlTextReaderPtr reader,
4579 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004580 const char *encoding, int options)
4581{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004582 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004583 return (-1);
4584
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004585 reader->doc = NULL;
4586 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004587 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004588 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004589 if ((input != NULL) && (reader->input != NULL) &&
4590 (reader->allocs & XML_TEXTREADER_INPUT)) {
4591 xmlFreeParserInputBuffer(reader->input);
4592 reader->input = NULL;
4593 reader->allocs -= XML_TEXTREADER_INPUT;
4594 }
4595 if (input != NULL) {
4596 reader->input = input;
4597 reader->allocs |= XML_TEXTREADER_INPUT;
4598 }
4599 if (reader->buffer == NULL)
4600 reader->buffer = xmlBufferCreateSize(100);
4601 if (reader->buffer == NULL) {
4602 xmlGenericError(xmlGenericErrorContext,
4603 "xmlTextReaderSetup : malloc failed\n");
4604 return (-1);
4605 }
4606 if (reader->sax == NULL)
4607 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4608 if (reader->sax == NULL) {
4609 xmlGenericError(xmlGenericErrorContext,
4610 "xmlTextReaderSetup : malloc failed\n");
4611 return (-1);
4612 }
4613 xmlSAXVersion(reader->sax, 2);
4614 reader->startElement = reader->sax->startElement;
4615 reader->sax->startElement = xmlTextReaderStartElement;
4616 reader->endElement = reader->sax->endElement;
4617 reader->sax->endElement = xmlTextReaderEndElement;
4618#ifdef LIBXML_SAX1_ENABLED
4619 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4620#endif /* LIBXML_SAX1_ENABLED */
4621 reader->startElementNs = reader->sax->startElementNs;
4622 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4623 reader->endElementNs = reader->sax->endElementNs;
4624 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4625#ifdef LIBXML_SAX1_ENABLED
4626 } else {
4627 reader->startElementNs = NULL;
4628 reader->endElementNs = NULL;
4629 }
4630#endif /* LIBXML_SAX1_ENABLED */
4631 reader->characters = reader->sax->characters;
4632 reader->sax->characters = xmlTextReaderCharacters;
4633 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4634 reader->cdataBlock = reader->sax->cdataBlock;
4635 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4636
4637 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4638 reader->node = NULL;
4639 reader->curnode = NULL;
4640 if (input != NULL) {
4641 if (reader->input->buffer->use < 4) {
4642 xmlParserInputBufferRead(input, 4);
4643 }
4644 if (reader->ctxt == NULL) {
4645 if (reader->input->buffer->use >= 4) {
4646 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4647 (const char *) reader->input->buffer->content, 4, URL);
4648 reader->base = 0;
4649 reader->cur = 4;
4650 } else {
4651 reader->ctxt =
4652 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4653 reader->base = 0;
4654 reader->cur = 0;
4655 }
4656 } else {
4657 xmlParserInputPtr inputStream;
4658 xmlParserInputBufferPtr buf;
4659 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4660
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004661 xmlCtxtReset(reader->ctxt);
4662 buf = xmlAllocParserInputBuffer(enc);
4663 if (buf == NULL) return(-1);
4664 inputStream = xmlNewInputStream(reader->ctxt);
4665 if (inputStream == NULL) {
4666 xmlFreeParserInputBuffer(buf);
4667 return(-1);
4668 }
4669
4670 if (URL == NULL)
4671 inputStream->filename = NULL;
4672 else
4673 inputStream->filename = (char *)
4674 xmlCanonicPath((const xmlChar *) URL);
4675 inputStream->buf = buf;
4676 inputStream->base = inputStream->buf->buffer->content;
4677 inputStream->cur = inputStream->buf->buffer->content;
4678 inputStream->end =
4679 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4680
4681 inputPush(reader->ctxt, inputStream);
4682 reader->cur = 0;
4683 }
4684 if (reader->ctxt == NULL) {
4685 xmlGenericError(xmlGenericErrorContext,
4686 "xmlTextReaderSetup : malloc failed\n");
4687 return (-1);
4688 }
4689 }
4690 if (reader->dict != NULL) {
4691 if (reader->ctxt->dict != NULL) {
4692 if (reader->dict != reader->ctxt->dict) {
4693 xmlDictFree(reader->dict);
4694 reader->dict = reader->ctxt->dict;
4695 }
4696 } else {
4697 reader->ctxt->dict = reader->dict;
4698 }
4699 } else {
4700 if (reader->ctxt->dict == NULL)
4701 reader->ctxt->dict = xmlDictCreate();
4702 reader->dict = reader->ctxt->dict;
4703 }
4704 reader->ctxt->_private = reader;
4705 reader->ctxt->linenumbers = 1;
4706 reader->ctxt->dictNames = 1;
4707 /*
4708 * use the parser dictionnary to allocate all elements and attributes names
4709 */
4710 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004711 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004712
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004713#ifdef LIBXML_XINCLUDE_ENABLED
4714 if (reader->xincctxt != NULL) {
4715 xmlXIncludeFreeContext(reader->xincctxt);
4716 reader->xincctxt = NULL;
4717 }
4718 if (options & XML_PARSE_XINCLUDE) {
4719 reader->xinclude = 1;
4720 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4721 options -= XML_PARSE_XINCLUDE;
4722 } else
4723 reader->xinclude = 0;
4724 reader->in_xinclude = 0;
4725#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004726#ifdef LIBXML_PATTERN_ENABLED
4727 if (reader->patternTab == NULL) {
4728 reader->patternNr = 0;
4729 reader->patternMax = 0;
4730 }
4731 while (reader->patternNr > 0) {
4732 reader->patternNr--;
4733 if (reader->patternTab[reader->patternNr] != NULL) {
4734 xmlFreePattern(reader->patternTab[reader->patternNr]);
4735 reader->patternTab[reader->patternNr] = NULL;
4736 }
4737 }
4738#endif
4739
Daniel Veillardc36965d2003-12-02 10:28:48 +00004740 if (options & XML_PARSE_DTDVALID)
4741 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4742
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004743 xmlCtxtUseOptions(reader->ctxt, options);
4744 if (encoding != NULL) {
4745 xmlCharEncodingHandlerPtr hdlr;
4746
4747 hdlr = xmlFindCharEncodingHandler(encoding);
4748 if (hdlr != NULL)
4749 xmlSwitchToEncoding(reader->ctxt, hdlr);
4750 }
4751 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4752 (reader->ctxt->input->filename == NULL))
4753 reader->ctxt->input->filename = (char *)
4754 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004755
4756 reader->doc = NULL;
4757
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004758 return (0);
4759}
4760
4761/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004762 * xmlTextReaderByteConsumed:
4763 * @reader: an XML reader
4764 *
4765 * This function provides the current index of the parser used
4766 * by the reader, relative to the start of the current entity.
4767 * This function actually just wraps a call to xmlBytesConsumed()
4768 * for the parser context associated with the reader.
4769 * See xmlBytesConsumed() for more information.
4770 *
4771 * Returns the index in bytes from the beginning of the entity or -1
4772 * in case the index could not be computed.
4773 */
4774long
4775xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4776 if ((reader == NULL) || (reader->ctxt == NULL))
4777 return(-1);
4778 return(xmlByteConsumed(reader->ctxt));
4779}
4780
4781
4782/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004783 * xmlReaderWalker:
4784 * @doc: a preparsed document
4785 *
4786 * Create an xmltextReader for a preparsed document.
4787 *
4788 * Returns the new reader or NULL in case of error.
4789 */
4790xmlTextReaderPtr
4791xmlReaderWalker(xmlDocPtr doc)
4792{
4793 xmlTextReaderPtr ret;
4794
4795 if (doc == NULL)
4796 return(NULL);
4797
4798 ret = xmlMalloc(sizeof(xmlTextReader));
4799 if (ret == NULL) {
4800 xmlGenericError(xmlGenericErrorContext,
4801 "xmlNewTextReader : malloc failed\n");
4802 return(NULL);
4803 }
4804 memset(ret, 0, sizeof(xmlTextReader));
4805 ret->entNr = 0;
4806 ret->input = NULL;
4807 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4808 ret->node = NULL;
4809 ret->curnode = NULL;
4810 ret->base = 0;
4811 ret->cur = 0;
4812 ret->allocs = XML_TEXTREADER_CTXT;
4813 ret->doc = doc;
4814 ret->state = XML_TEXTREADER_START;
4815 ret->dict = xmlDictCreate();
4816 return(ret);
4817}
4818
4819/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004820 * xmlReaderForDoc:
4821 * @cur: a pointer to a zero terminated string
4822 * @URL: the base URL to use for the document
4823 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004824 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004825 *
4826 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004827 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004828 *
4829 * Returns the new reader or NULL in case of error.
4830 */
4831xmlTextReaderPtr
4832xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4833 int options)
4834{
4835 int len;
4836
4837 if (cur == NULL)
4838 return (NULL);
4839 len = xmlStrlen(cur);
4840
4841 return (xmlReaderForMemory
4842 ((const char *) cur, len, URL, encoding, options));
4843}
4844
4845/**
4846 * xmlReaderForFile:
4847 * @filename: a file or URL
4848 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004849 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004850 *
4851 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004852 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004853 *
4854 * Returns the new reader or NULL in case of error.
4855 */
4856xmlTextReaderPtr
4857xmlReaderForFile(const char *filename, const char *encoding, int options)
4858{
4859 xmlTextReaderPtr reader;
4860
4861 reader = xmlNewTextReaderFilename(filename);
4862 if (reader == NULL)
4863 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004864 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004865 return (reader);
4866}
4867
4868/**
4869 * xmlReaderForMemory:
4870 * @buffer: a pointer to a char array
4871 * @size: the size of the array
4872 * @URL: the base URL to use for the document
4873 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004874 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004875 *
4876 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004877 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004878 *
4879 * Returns the new reader or NULL in case of error.
4880 */
4881xmlTextReaderPtr
4882xmlReaderForMemory(const char *buffer, int size, const char *URL,
4883 const char *encoding, int options)
4884{
4885 xmlTextReaderPtr reader;
4886 xmlParserInputBufferPtr buf;
4887
Daniel Veillard21924522004-02-19 16:37:07 +00004888 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004889 XML_CHAR_ENCODING_NONE);
4890 if (buf == NULL) {
4891 return (NULL);
4892 }
4893 reader = xmlNewTextReader(buf, URL);
4894 if (reader == NULL) {
4895 xmlFreeParserInputBuffer(buf);
4896 return (NULL);
4897 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004898 reader->allocs |= XML_TEXTREADER_INPUT;
4899 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004900 return (reader);
4901}
4902
4903/**
4904 * xmlReaderForFd:
4905 * @fd: an open file descriptor
4906 * @URL: the base URL to use for the document
4907 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004908 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004909 *
4910 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004911 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004912 * NOTE that the file descriptor will not be closed when the
4913 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004914 *
4915 * Returns the new reader or NULL in case of error.
4916 */
4917xmlTextReaderPtr
4918xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4919{
4920 xmlTextReaderPtr reader;
4921 xmlParserInputBufferPtr input;
4922
4923 if (fd < 0)
4924 return (NULL);
4925
4926 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4927 if (input == NULL)
4928 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004929 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004930 reader = xmlNewTextReader(input, URL);
4931 if (reader == NULL) {
4932 xmlFreeParserInputBuffer(input);
4933 return (NULL);
4934 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004935 reader->allocs |= XML_TEXTREADER_INPUT;
4936 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004937 return (reader);
4938}
4939
4940/**
4941 * xmlReaderForIO:
4942 * @ioread: an I/O read function
4943 * @ioclose: an I/O close function
4944 * @ioctx: an I/O handler
4945 * @URL: the base URL to use for the document
4946 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004947 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004948 *
4949 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004950 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004951 *
4952 * Returns the new reader or NULL in case of error.
4953 */
4954xmlTextReaderPtr
4955xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4956 void *ioctx, const char *URL, const char *encoding,
4957 int options)
4958{
4959 xmlTextReaderPtr reader;
4960 xmlParserInputBufferPtr input;
4961
4962 if (ioread == NULL)
4963 return (NULL);
4964
4965 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4966 XML_CHAR_ENCODING_NONE);
4967 if (input == NULL)
4968 return (NULL);
4969 reader = xmlNewTextReader(input, URL);
4970 if (reader == NULL) {
4971 xmlFreeParserInputBuffer(input);
4972 return (NULL);
4973 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004974 reader->allocs |= XML_TEXTREADER_INPUT;
4975 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004976 return (reader);
4977}
4978
4979/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004980 * xmlReaderNewWalker:
4981 * @reader: an XML reader
4982 * @doc: a preparsed document
4983 *
4984 * Setup an xmltextReader to parse a preparsed XML document.
4985 * This reuses the existing @reader xmlTextReader.
4986 *
4987 * Returns 0 in case of success and -1 in case of error
4988 */
4989int
4990xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4991{
4992 if (doc == NULL)
4993 return (-1);
4994 if (reader == NULL)
4995 return (-1);
4996
Daniel Veillarddd6d3002004-11-03 14:20:29 +00004997 if (reader->input != NULL) {
4998 xmlFreeParserInputBuffer(reader->input);
4999 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005000 if (reader->ctxt != NULL) {
5001 xmlCtxtReset(reader->ctxt);
5002 }
5003
5004 reader->entNr = 0;
5005 reader->input = NULL;
5006 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5007 reader->node = NULL;
5008 reader->curnode = NULL;
5009 reader->base = 0;
5010 reader->cur = 0;
5011 reader->allocs = XML_TEXTREADER_CTXT;
5012 reader->doc = doc;
5013 reader->state = XML_TEXTREADER_START;
5014 if (reader->dict == NULL) {
5015 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5016 reader->dict = reader->ctxt->dict;
5017 else
5018 reader->dict = xmlDictCreate();
5019 }
5020 return(0);
5021}
5022
5023/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005024 * xmlReaderNewDoc:
5025 * @reader: an XML reader
5026 * @cur: a pointer to a zero terminated string
5027 * @URL: the base URL to use for the document
5028 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005029 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005030 *
5031 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005032 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005033 * This reuses the existing @reader xmlTextReader.
5034 *
5035 * Returns 0 in case of success and -1 in case of error
5036 */
5037int
5038xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5039 const char *URL, const char *encoding, int options)
5040{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005041
5042 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005043
5044 if (cur == NULL)
5045 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005046 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005047 return (-1);
5048
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005049 len = xmlStrlen(cur);
5050 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5051 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005052}
5053
5054/**
5055 * xmlReaderNewFile:
5056 * @reader: an XML reader
5057 * @filename: a file or URL
5058 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005059 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005060 *
5061 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005062 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005063 * This reuses the existing @reader xmlTextReader.
5064 *
5065 * Returns 0 in case of success and -1 in case of error
5066 */
5067int
5068xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5069 const char *encoding, int options)
5070{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005071 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005072
5073 if (filename == NULL)
5074 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005075 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005076 return (-1);
5077
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005078 input =
5079 xmlParserInputBufferCreateFilename(filename,
5080 XML_CHAR_ENCODING_NONE);
5081 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005082 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005083 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005084}
5085
5086/**
5087 * xmlReaderNewMemory:
5088 * @reader: an XML reader
5089 * @buffer: a pointer to a char array
5090 * @size: the size of the array
5091 * @URL: the base URL to use for the document
5092 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005093 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005094 *
5095 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005096 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005097 * This reuses the existing @reader xmlTextReader.
5098 *
5099 * Returns 0 in case of success and -1 in case of error
5100 */
5101int
5102xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5103 const char *URL, const char *encoding, int options)
5104{
5105 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005106
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005107 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005108 return (-1);
5109 if (buffer == NULL)
5110 return (-1);
5111
Daniel Veillard21924522004-02-19 16:37:07 +00005112 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005113 XML_CHAR_ENCODING_NONE);
5114 if (input == NULL) {
5115 return (-1);
5116 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005117 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005118}
5119
5120/**
5121 * xmlReaderNewFd:
5122 * @reader: an XML reader
5123 * @fd: an open file descriptor
5124 * @URL: the base URL to use for the document
5125 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005126 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005127 *
5128 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005129 * NOTE that the file descriptor will not be closed when the
5130 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005131 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005132 * This reuses the existing @reader xmlTextReader.
5133 *
5134 * Returns 0 in case of success and -1 in case of error
5135 */
5136int
5137xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5138 const char *URL, const char *encoding, int options)
5139{
5140 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005141
5142 if (fd < 0)
5143 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005144 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005145 return (-1);
5146
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005147 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5148 if (input == NULL)
5149 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005150 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005151 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005152}
5153
5154/**
5155 * xmlReaderNewIO:
5156 * @reader: an XML reader
5157 * @ioread: an I/O read function
5158 * @ioclose: an I/O close function
5159 * @ioctx: an I/O handler
5160 * @URL: the base URL to use for the document
5161 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005162 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005163 *
5164 * Setup an xmltextReader to parse an XML document from I/O functions
5165 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005166 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005167 * This reuses the existing @reader xmlTextReader.
5168 *
5169 * Returns 0 in case of success and -1 in case of error
5170 */
5171int
5172xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5173 xmlInputCloseCallback ioclose, void *ioctx,
5174 const char *URL, const char *encoding, int options)
5175{
5176 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005177
5178 if (ioread == NULL)
5179 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005180 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005181 return (-1);
5182
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005183 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5184 XML_CHAR_ENCODING_NONE);
5185 if (input == NULL)
5186 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005187 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005188}
Daniel Veillard26f70262003-01-16 22:45:08 +00005189/************************************************************************
5190 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005191 * Utilities *
5192 * *
5193 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005194#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005195/**
5196 * xmlBase64Decode:
5197 * @in: the input buffer
5198 * @inlen: the size of the input (in), the size read from it (out)
5199 * @to: the output buffer
5200 * @tolen: the size of the output (in), the size written to (out)
5201 *
5202 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005203 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005204 *
5205 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5206 * 2 if there wasn't enough space on the output or -1 in case of error.
5207 */
5208static int
5209xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5210 unsigned char *to, unsigned long *tolen) {
5211 unsigned long incur; /* current index in in[] */
5212 unsigned long inblk; /* last block index in in[] */
5213 unsigned long outcur; /* current index in out[] */
5214 unsigned long inmax; /* size of in[] */
5215 unsigned long outmax; /* size of out[] */
5216 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005217 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005218 int nbintmp; /* number of byte in intmp[] */
5219 int is_ignore; /* cur should be ignored */
5220 int is_end = 0; /* the end of the base64 was found */
5221 int retval = 1;
5222 int i;
5223
5224 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5225 return(-1);
5226
5227 incur = 0;
5228 inblk = 0;
5229 outcur = 0;
5230 inmax = *inlen;
5231 outmax = *tolen;
5232 nbintmp = 0;
5233
5234 while (1) {
5235 if (incur >= inmax)
5236 break;
5237 cur = in[incur++];
5238 is_ignore = 0;
5239 if ((cur >= 'A') && (cur <= 'Z'))
5240 cur = cur - 'A';
5241 else if ((cur >= 'a') && (cur <= 'z'))
5242 cur = cur - 'a' + 26;
5243 else if ((cur >= '0') && (cur <= '9'))
5244 cur = cur - '0' + 52;
5245 else if (cur == '+')
5246 cur = 62;
5247 else if (cur == '/')
5248 cur = 63;
5249 else if (cur == '.')
5250 cur = 0;
5251 else if (cur == '=') /*no op , end of the base64 stream */
5252 is_end = 1;
5253 else {
5254 is_ignore = 1;
5255 if (nbintmp == 0)
5256 inblk = incur;
5257 }
5258
5259 if (!is_ignore) {
5260 int nbouttmp = 3;
5261 int is_break = 0;
5262
5263 if (is_end) {
5264 if (nbintmp == 0)
5265 break;
5266 if ((nbintmp == 1) || (nbintmp == 2))
5267 nbouttmp = 1;
5268 else
5269 nbouttmp = 2;
5270 nbintmp = 3;
5271 is_break = 1;
5272 }
5273 intmp[nbintmp++] = cur;
5274 /*
5275 * if intmp is full, push the 4byte sequence as a 3 byte
5276 * sequence out
5277 */
5278 if (nbintmp == 4) {
5279 nbintmp = 0;
5280 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5281 outtmp[1] =
5282 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5283 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5284 if (outcur + 3 >= outmax) {
5285 retval = 2;
5286 break;
5287 }
5288
5289 for (i = 0; i < nbouttmp; i++)
5290 to[outcur++] = outtmp[i];
5291 inblk = incur;
5292 }
5293
5294 if (is_break) {
5295 retval = 0;
5296 break;
5297 }
5298 }
5299 }
5300
5301 *tolen = outcur;
5302 *inlen = inblk;
5303 return (retval);
5304}
5305
5306/*
5307 * Test routine for the xmlBase64Decode function
5308 */
5309#if 0
5310int main(int argc, char **argv) {
5311 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5312 char output[100];
5313 char output2[100];
5314 char output3[100];
5315 unsigned long inlen = strlen(input);
5316 unsigned long outlen = 100;
5317 int ret;
5318 unsigned long cons, tmp, tmp2, prod;
5319
5320 /*
5321 * Direct
5322 */
5323 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5324
5325 output[outlen] = 0;
5326 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5327
5328 /*
5329 * output chunking
5330 */
5331 cons = 0;
5332 prod = 0;
5333 while (cons < inlen) {
5334 tmp = 5;
5335 tmp2 = inlen - cons;
5336
5337 printf("%ld %ld\n", cons, prod);
5338 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5339 cons += tmp2;
5340 prod += tmp;
5341 printf("%ld %ld\n", cons, prod);
5342 }
5343 output2[outlen] = 0;
5344 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5345
5346 /*
5347 * input chunking
5348 */
5349 cons = 0;
5350 prod = 0;
5351 while (cons < inlen) {
5352 tmp = 100 - prod;
5353 tmp2 = inlen - cons;
5354 if (tmp2 > 5)
5355 tmp2 = 5;
5356
5357 printf("%ld %ld\n", cons, prod);
5358 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5359 cons += tmp2;
5360 prod += tmp;
5361 printf("%ld %ld\n", cons, prod);
5362 }
5363 output3[outlen] = 0;
5364 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5365 return(0);
5366
5367}
5368#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005369#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005370#define bottom_xmlreader
5371#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005372#endif /* LIBXML_READER_ENABLED */