blob: f3b5520fc3c9f9611412542ca6345e63aa78545b [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)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000601 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000602 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];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000608 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000609 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);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002175 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002176 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 Veillardda0aa4c2005-07-13 23:07:49 +00003883
3884static char *
3885xmlTextReaderBuildMessage(const char *msg, va_list ap);
3886
Daniel Veillardffa3c742005-07-21 13:24:09 +00003887static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003888xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3889
Daniel Veillardffa3c742005-07-21 13:24:09 +00003890static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003891xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3892
Daniel Veillardffa3c742005-07-21 13:24:09 +00003893static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003894{
3895 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3896 char * str;
3897 va_list ap;
3898
3899 va_start(ap,msg);
3900 str = xmlTextReaderBuildMessage(msg,ap);
3901 if (!reader->errorFunc) {
3902 xmlTextReaderValidityError(ctx, "%s", str);
3903 } else {
3904 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3905 }
3906 if (str != NULL)
3907 xmlFree(str);
3908 va_end(ap);
3909}
3910
Daniel Veillardffa3c742005-07-21 13:24:09 +00003911static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003912{
3913 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3914 char * str;
3915 va_list ap;
3916
3917 va_start(ap,msg);
3918 str = xmlTextReaderBuildMessage(msg,ap);
3919 if (!reader->errorFunc) {
3920 xmlTextReaderValidityWarning(ctx, "%s", str);
3921 } else {
3922 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3923 }
3924 if (str != NULL)
3925 xmlFree(str);
3926 va_end(ap);
3927}
3928
3929static void
3930xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
3931
3932static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
3933{
3934 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
3935
3936 if (reader->sErrorFunc) {
3937 reader->sErrorFunc(reader->errorFuncArg, error);
3938 } else {
3939 xmlTextReaderStructuredError(reader, error);
3940 }
3941}
3942
Daniel Veillardf4e55762003-04-15 23:32:22 +00003943/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003944 * xmlTextReaderRelaxNGSetSchema:
3945 * @reader: the xmlTextReaderPtr used
3946 * @schema: a precompiled RelaxNG schema
3947 *
3948 * Use RelaxNG to validate the document as it is processed.
3949 * Activation is only possible before the first Read().
3950 * if @schema is NULL, then RelaxNG validation is desactivated.
3951 @ The @schema should not be freed until the reader is deallocated
3952 * or its use has been deactivated.
3953 *
3954 * Returns 0 in case the RelaxNG validation could be (des)activated and
3955 * -1 in case of error.
3956 */
3957int
3958xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00003959 if (reader == NULL)
3960 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003961 if (schema == NULL) {
3962 if (reader->rngSchemas != NULL) {
3963 xmlRelaxNGFree(reader->rngSchemas);
3964 reader->rngSchemas = NULL;
3965 }
3966 if (reader->rngValidCtxt != NULL) {
3967 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3968 reader->rngValidCtxt = NULL;
3969 }
3970 return(0);
3971 }
3972 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3973 return(-1);
3974 if (reader->rngSchemas != NULL) {
3975 xmlRelaxNGFree(reader->rngSchemas);
3976 reader->rngSchemas = NULL;
3977 }
3978 if (reader->rngValidCtxt != NULL) {
3979 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3980 reader->rngValidCtxt = NULL;
3981 }
3982 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3983 if (reader->rngValidCtxt == NULL)
3984 return(-1);
3985 if (reader->errorFunc != NULL) {
3986 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003987 xmlTextReaderValidityErrorRelay,
3988 xmlTextReaderValidityWarningRelay,
3989 reader);
3990 }
3991 if (reader->sErrorFunc != NULL) {
3992 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
3993 xmlTextReaderValidityStructuredRelay,
3994 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00003995 }
3996 reader->rngValidErrors = 0;
3997 reader->rngFullNode = NULL;
3998 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3999 return(0);
4000}
4001
4002/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004003 * xmlTextReaderSetSchema:
4004 * @reader: the xmlTextReaderPtr used
4005 * @schema: a precompiled Schema schema
4006 *
4007 * Use XSD Schema to validate the document as it is processed.
4008 * Activation is only possible before the first Read().
4009 * if @schema is NULL, then Schema validation is desactivated.
4010 @ The @schema should not be freed until the reader is deallocated
4011 * or its use has been deactivated.
4012 *
4013 * Returns 0 in case the Schema validation could be (des)activated and
4014 * -1 in case of error.
4015 */
4016int
4017xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4018 if (reader == NULL)
4019 return(-1);
4020 if (schema == NULL) {
4021 if (reader->xsdPlug != NULL) {
4022 xmlSchemaSAXUnplug(reader->xsdPlug);
4023 reader->xsdPlug = NULL;
4024 }
4025 if (reader->xsdValidCtxt != NULL) {
4026 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4027 reader->xsdValidCtxt = NULL;
4028 }
4029 if (reader->xsdSchemas != NULL) {
4030 xmlSchemaFree(reader->xsdSchemas);
4031 reader->xsdSchemas = NULL;
4032 }
4033 return(0);
4034 }
4035 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4036 return(-1);
4037 if (reader->xsdPlug != NULL) {
4038 xmlSchemaSAXUnplug(reader->xsdPlug);
4039 reader->xsdPlug = NULL;
4040 }
4041 if (reader->xsdValidCtxt != NULL) {
4042 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4043 reader->xsdValidCtxt = NULL;
4044 }
4045 if (reader->xsdSchemas != NULL) {
4046 xmlSchemaFree(reader->xsdSchemas);
4047 reader->xsdSchemas = NULL;
4048 }
4049 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4050 if (reader->xsdValidCtxt == NULL) {
4051 xmlSchemaFree(reader->xsdSchemas);
4052 reader->xsdSchemas = NULL;
4053 return(-1);
4054 }
4055 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4056 &(reader->ctxt->sax),
4057 &(reader->ctxt->userData));
4058 if (reader->xsdPlug == NULL) {
4059 xmlSchemaFree(reader->xsdSchemas);
4060 reader->xsdSchemas = NULL;
4061 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4062 reader->xsdValidCtxt = NULL;
4063 return(-1);
4064 }
4065 if (reader->errorFunc != NULL) {
4066 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004067 xmlTextReaderValidityErrorRelay,
4068 xmlTextReaderValidityWarningRelay,
4069 reader);
4070 }
4071 if (reader->sErrorFunc != NULL) {
4072 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4073 xmlTextReaderValidityStructuredRelay,
4074 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004075 }
4076 reader->xsdValidErrors = 0;
4077 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4078 return(0);
4079}
4080
4081/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004082 * xmlTextReaderRelaxNGValidate:
4083 * @reader: the xmlTextReaderPtr used
4084 * @rng: the path to a RelaxNG schema or NULL
4085 *
4086 * Use RelaxNG to validate the document as it is processed.
4087 * Activation is only possible before the first Read().
4088 * if @rng is NULL, then RelaxNG validation is desactivated.
4089 *
4090 * Returns 0 in case the RelaxNG validation could be (des)activated and
4091 * -1 in case of error.
4092 */
4093int
4094xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4095 xmlRelaxNGParserCtxtPtr ctxt;
4096
4097 if (reader == NULL)
4098 return(-1);
4099
4100 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004101 if (reader->rngValidCtxt != NULL) {
4102 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4103 reader->rngValidCtxt = NULL;
4104 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004105 if (reader->rngSchemas != NULL) {
4106 xmlRelaxNGFree(reader->rngSchemas);
4107 reader->rngSchemas = NULL;
4108 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004109 return(0);
4110 }
4111 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4112 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004113 if (reader->rngSchemas != NULL) {
4114 xmlRelaxNGFree(reader->rngSchemas);
4115 reader->rngSchemas = NULL;
4116 }
4117 if (reader->rngValidCtxt != NULL) {
4118 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4119 reader->rngValidCtxt = NULL;
4120 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004121 ctxt = xmlRelaxNGNewParserCtxt(rng);
4122 if (reader->errorFunc != NULL) {
4123 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004124 xmlTextReaderValidityErrorRelay,
4125 xmlTextReaderValidityWarningRelay,
4126 reader);
4127 }
4128 if (reader->sErrorFunc != NULL) {
4129 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4130 xmlTextReaderValidityStructuredRelay,
4131 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004132 }
4133 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4134 xmlRelaxNGFreeParserCtxt(ctxt);
4135 if (reader->rngSchemas == NULL)
4136 return(-1);
4137 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004138 if (reader->rngValidCtxt == NULL) {
4139 xmlRelaxNGFree(reader->rngSchemas);
4140 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004141 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004142 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004143 if (reader->errorFunc != NULL) {
4144 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004145 xmlTextReaderValidityErrorRelay,
4146 xmlTextReaderValidityWarningRelay,
4147 reader);
4148 }
4149 if (reader->sErrorFunc != NULL) {
4150 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4151 xmlTextReaderValidityStructuredRelay,
4152 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004153 }
4154 reader->rngValidErrors = 0;
4155 reader->rngFullNode = NULL;
4156 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4157 return(0);
4158}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004159
4160/**
4161 * xmlTextReaderSchemaValidate:
4162 * @reader: the xmlTextReaderPtr used
4163 * @xsd: the path to a W3C XSD schema or NULL
4164 *
4165 * Use W3C XSD schema to validate the document as it is processed.
4166 * Activation is only possible before the first Read().
4167 * if @xsd is NULL, then RelaxNG validation is desactivated.
4168 *
4169 * Returns 0 in case the schemas validation could be (des)activated and
4170 * -1 in case of error.
4171 */
4172int
4173xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4174 xmlSchemaParserCtxtPtr ctxt;
4175
4176 if (reader == NULL)
4177 return(-1);
4178
4179 if (xsd == NULL) {
4180 if (reader->xsdPlug != NULL) {
4181 xmlSchemaSAXUnplug(reader->xsdPlug);
4182 reader->xsdPlug = NULL;
4183 }
4184 if (reader->xsdSchemas != NULL) {
4185 xmlSchemaFree(reader->xsdSchemas);
4186 reader->xsdSchemas = NULL;
4187 }
4188 if (reader->xsdValidCtxt != NULL) {
4189 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4190 reader->xsdValidCtxt = NULL;
4191 }
4192 return(0);
4193 }
4194 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4195 (reader->ctxt == NULL))
4196 return(-1);
4197 if (reader->xsdPlug != NULL) {
4198 xmlSchemaSAXUnplug(reader->xsdPlug);
4199 reader->xsdPlug = NULL;
4200 }
4201 if (reader->xsdValidCtxt != NULL) {
4202 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4203 reader->xsdValidCtxt = NULL;
4204 }
4205 if (reader->xsdSchemas != NULL) {
4206 xmlSchemaFree(reader->xsdSchemas);
4207 reader->xsdSchemas = NULL;
4208 }
4209 ctxt = xmlSchemaNewParserCtxt(xsd);
4210 if (reader->errorFunc != NULL) {
4211 xmlSchemaSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004212 xmlTextReaderValidityErrorRelay,
4213 xmlTextReaderValidityWarningRelay,
4214 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004215 }
4216 reader->xsdSchemas = xmlSchemaParse(ctxt);
4217 xmlSchemaFreeParserCtxt(ctxt);
4218 if (reader->xsdSchemas == NULL)
4219 return(-1);
4220 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4221 if (reader->xsdValidCtxt == NULL) {
4222 xmlSchemaFree(reader->xsdSchemas);
4223 reader->xsdSchemas = NULL;
4224 return(-1);
4225 }
4226 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4227 &(reader->ctxt->sax),
4228 &(reader->ctxt->userData));
4229 if (reader->xsdPlug == NULL) {
4230 xmlSchemaFree(reader->xsdSchemas);
4231 reader->xsdSchemas = NULL;
4232 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4233 reader->xsdValidCtxt = NULL;
4234 return(-1);
4235 }
4236 if (reader->errorFunc != NULL) {
4237 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004238 xmlTextReaderValidityErrorRelay,
4239 xmlTextReaderValidityWarningRelay,
4240 reader);
4241 }
4242 if (reader->sErrorFunc != NULL) {
4243 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4244 xmlTextReaderValidityStructuredRelay,
4245 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004246 }
4247 reader->xsdValidErrors = 0;
4248 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4249 return(0);
4250}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004251#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004252
Daniel Veillarde2811272004-10-19 09:04:23 +00004253/**
4254 * xmlTextReaderIsNamespaceDecl:
4255 * @reader: the xmlTextReaderPtr used
4256 *
4257 * Determine whether the current node is a namespace declaration
4258 * rather than a regular attribute.
4259 *
4260 * Returns 1 if the current node is a namespace declaration, 0 if it
4261 * is a regular attribute or other type of node, or -1 in case of
4262 * error.
4263 */
4264int
4265xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4266 xmlNodePtr node;
4267 if (reader == NULL)
4268 return(-1);
4269 if (reader->node == NULL)
4270 return(-1);
4271 if (reader->curnode != NULL)
4272 node = reader->curnode;
4273 else
4274 node = reader->node;
4275
4276 if (XML_NAMESPACE_DECL == node->type)
4277 return(1);
4278 else
4279 return(0);
4280}
4281
4282/**
4283 * xmlTextReaderConstXmlVersion:
4284 * @reader: the xmlTextReaderPtr used
4285 *
4286 * Determine the XML version of the document being read.
4287 *
4288 * Returns a string containing the XML version of the document or NULL
4289 * in case of error. The string is deallocated with the reader.
4290 */
4291const xmlChar *
4292xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4293 xmlDocPtr doc = NULL;
4294 if (reader == NULL)
4295 return(NULL);
4296 if (reader->doc != NULL)
4297 doc = reader->doc;
4298 else if (reader->ctxt != NULL)
4299 doc = reader->ctxt->myDoc;
4300 if (doc == NULL)
4301 return(NULL);
4302
4303 if (doc->version == NULL)
4304 return(NULL);
4305 else
4306 return(CONSTSTR(doc->version));
4307}
4308
4309/**
4310 * xmlTextReaderStandalone:
4311 * @reader: the xmlTextReaderPtr used
4312 *
4313 * Determine the standalone status of the document being read.
4314 *
4315 * Returns 1 if the document was declared to be standalone, 0 if it
4316 * was declared to be not standalone, or -1 if the document did not
4317 * specify its standalone status or in case of error.
4318 */
4319int
4320xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4321 xmlDocPtr doc = NULL;
4322 if (reader == NULL)
4323 return(-1);
4324 if (reader->doc != NULL)
4325 doc = reader->doc;
4326 else if (reader->ctxt != NULL)
4327 doc = reader->ctxt->myDoc;
4328 if (doc == NULL)
4329 return(-1);
4330
4331 return(doc->standalone);
4332}
4333
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004334/************************************************************************
4335 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004336 * Error Handling Extensions *
4337 * *
4338 ************************************************************************/
4339
4340/* helper to build a xmlMalloc'ed string from a format and va_list */
4341static char *
4342xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4343 int size;
4344 int chars;
4345 char *larger;
4346 char *str;
4347
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004348 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004349 if (str == NULL) {
4350 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4351 return NULL;
4352 }
4353
4354 size = 150;
4355
4356 while (1) {
4357 chars = vsnprintf(str, size, msg, ap);
4358 if ((chars > -1) && (chars < size))
4359 break;
4360 if (chars > -1)
4361 size += chars + 1;
4362 else
4363 size += 100;
4364 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4365 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4366 xmlFree(str);
4367 return NULL;
4368 }
4369 str = larger;
4370 }
4371
4372 return str;
4373}
4374
Daniel Veillard417be3a2003-01-20 21:26:34 +00004375/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004376 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004377 * @locator: the xmlTextReaderLocatorPtr used
4378 *
4379 * Obtain the line number for the given locator.
4380 *
4381 * Returns the line number or -1 in case of error.
4382 */
4383int
4384xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4385 /* we know that locator is a xmlParserCtxtPtr */
4386 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4387 int ret = -1;
4388
Daniel Veillardce682bc2004-11-05 17:22:25 +00004389 if (locator == NULL)
4390 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004391 if (ctx->node != NULL) {
4392 ret = xmlGetLineNo(ctx->node);
4393 }
4394 else {
4395 /* inspired from error.c */
4396 xmlParserInputPtr input;
4397 input = ctx->input;
4398 if ((input->filename == NULL) && (ctx->inputNr > 1))
4399 input = ctx->inputTab[ctx->inputNr - 2];
4400 if (input != NULL) {
4401 ret = input->line;
4402 }
4403 else {
4404 ret = -1;
4405 }
4406 }
4407
4408 return ret;
4409}
4410
4411/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004412 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004413 * @locator: the xmlTextReaderLocatorPtr used
4414 *
4415 * Obtain the base URI for the given locator.
4416 *
4417 * Returns the base URI or NULL in case of error.
4418 */
4419xmlChar *
4420xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4421 /* we know that locator is a xmlParserCtxtPtr */
4422 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4423 xmlChar *ret = NULL;
4424
Daniel Veillardce682bc2004-11-05 17:22:25 +00004425 if (locator == NULL)
4426 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004427 if (ctx->node != NULL) {
4428 ret = xmlNodeGetBase(NULL,ctx->node);
4429 }
4430 else {
4431 /* inspired from error.c */
4432 xmlParserInputPtr input;
4433 input = ctx->input;
4434 if ((input->filename == NULL) && (ctx->inputNr > 1))
4435 input = ctx->inputTab[ctx->inputNr - 2];
4436 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004437 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004438 }
4439 else {
4440 ret = NULL;
4441 }
4442 }
4443
4444 return ret;
4445}
4446
Daniel Veillard26f70262003-01-16 22:45:08 +00004447static void
William M. Brack899e64a2003-09-26 18:03:42 +00004448xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004449 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4450 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4451
William M. Bracka3215c72004-07-31 16:24:01 +00004452 if (str != NULL) {
4453 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004454 reader->errorFunc(reader->errorFuncArg,
4455 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004456 severity,
4457 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004458 xmlFree(str);
4459 }
4460}
4461
4462static void
William M. Brack93d004f2004-02-03 00:14:10 +00004463xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4464 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4465 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4466
4467 if (error && reader->sErrorFunc) {
4468 reader->sErrorFunc(reader->errorFuncArg,
4469 (xmlErrorPtr) error);
4470 }
4471}
4472
Daniel Veillardffa3c742005-07-21 13:24:09 +00004473static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004474xmlTextReaderError(void *ctxt, const char *msg, ...) {
4475 va_list ap;
4476
4477 va_start(ap,msg);
4478 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004479 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004480 xmlTextReaderBuildMessage(msg,ap));
4481 va_end(ap);
4482
4483}
4484
Daniel Veillardffa3c742005-07-21 13:24:09 +00004485static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004486xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4487 va_list ap;
4488
4489 va_start(ap,msg);
4490 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004491 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004492 xmlTextReaderBuildMessage(msg,ap));
4493 va_end(ap);
4494}
4495
Daniel Veillardffa3c742005-07-21 13:24:09 +00004496static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004497xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4498 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004499 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004500
Daniel Veillard417be3a2003-01-20 21:26:34 +00004501 if ((len > 1) && (msg[len - 2] != ':')) {
4502 /*
4503 * some callbacks only report locator information:
4504 * skip them (mimicking behaviour in error.c)
4505 */
4506 va_start(ap,msg);
4507 xmlTextReaderGenericError(ctxt,
4508 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4509 xmlTextReaderBuildMessage(msg,ap));
4510 va_end(ap);
4511 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004512}
4513
Daniel Veillardffa3c742005-07-21 13:24:09 +00004514static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004515xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4516 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004517 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004518
Daniel Veillard417be3a2003-01-20 21:26:34 +00004519 if ((len != 0) && (msg[len - 1] != ':')) {
4520 /*
4521 * some callbacks only report locator information:
4522 * skip them (mimicking behaviour in error.c)
4523 */
4524 va_start(ap,msg);
4525 xmlTextReaderGenericError(ctxt,
4526 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4527 xmlTextReaderBuildMessage(msg,ap));
4528 va_end(ap);
4529 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004530}
4531
4532/**
4533 * xmlTextReaderSetErrorHandler:
4534 * @reader: the xmlTextReaderPtr used
4535 * @f: the callback function to call on error and warnings
4536 * @arg: a user argument to pass to the callback function
4537 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004538 * Register a callback function that will be called on error and warnings.
4539 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004540 * If @f is NULL, the default error and warning handlers are restored.
4541 */
4542void
4543xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4544 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004545 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004546 if (f != NULL) {
4547 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004548 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004549 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4550 reader->ctxt->sax->warning = xmlTextReaderWarning;
4551 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4552 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004553 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004554 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004555#ifdef LIBXML_SCHEMAS_ENABLED
4556 if (reader->rngValidCtxt) {
4557 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4558 xmlTextReaderValidityErrorRelay,
4559 xmlTextReaderValidityWarningRelay,
4560 reader);
4561 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4562 }
4563 if (reader->xsdValidCtxt) {
4564 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4565 xmlTextReaderValidityErrorRelay,
4566 xmlTextReaderValidityWarningRelay,
4567 reader);
4568 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4569 }
4570#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004571 }
4572 else {
4573 /* restore defaults */
4574 reader->ctxt->sax->error = xmlParserError;
4575 reader->ctxt->vctxt.error = xmlParserValidityError;
4576 reader->ctxt->sax->warning = xmlParserWarning;
4577 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4578 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004579 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004580 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004581#ifdef LIBXML_SCHEMAS_ENABLED
4582 if (reader->rngValidCtxt) {
4583 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4584 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4585 }
4586 if (reader->xsdValidCtxt) {
4587 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4588 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4589 }
4590#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004591 }
4592}
4593
Daniel Veillard417be3a2003-01-20 21:26:34 +00004594/**
William M. Brack93d004f2004-02-03 00:14:10 +00004595* xmlTextReaderSetStructuredErrorHandler:
4596 * @reader: the xmlTextReaderPtr used
4597 * @f: the callback function to call on error and warnings
4598 * @arg: a user argument to pass to the callback function
4599 *
4600 * Register a callback function that will be called on error and warnings.
4601 *
4602 * If @f is NULL, the default error and warning handlers are restored.
4603 */
4604void
4605xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4606 xmlStructuredErrorFunc f,
4607 void *arg) {
4608 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004609 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004610 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4611 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4612 reader->ctxt->sax->warning = xmlTextReaderWarning;
4613 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4614 reader->sErrorFunc = f;
4615 reader->errorFunc = NULL;
4616 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004617#ifdef LIBXML_SCHEMAS_ENABLED
4618 if (reader->rngValidCtxt) {
4619 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4620 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4621 xmlTextReaderValidityStructuredRelay,
4622 reader);
4623 }
4624 if (reader->xsdValidCtxt) {
4625 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4626 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4627 xmlTextReaderValidityStructuredRelay,
4628 reader);
4629 }
4630#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004631 }
4632 else {
4633 /* restore defaults */
4634 reader->ctxt->sax->error = xmlParserError;
4635 reader->ctxt->sax->serror = NULL;
4636 reader->ctxt->vctxt.error = xmlParserValidityError;
4637 reader->ctxt->sax->warning = xmlParserWarning;
4638 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4639 reader->errorFunc = NULL;
4640 reader->sErrorFunc = NULL;
4641 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004642#ifdef LIBXML_SCHEMAS_ENABLED
4643 if (reader->rngValidCtxt) {
4644 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4645 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4646 }
4647 if (reader->xsdValidCtxt) {
4648 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4649 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4650 }
4651#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004652 }
4653}
4654
4655/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004656 * xmlTextReaderIsValid:
4657 * @reader: the xmlTextReaderPtr used
4658 *
4659 * Retrieve the validity status from the parser context
4660 *
4661 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4662 */
4663int
4664xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004665 if (reader == NULL) return(-1);
4666#ifdef LIBXML_SCHEMAS_ENABLED
4667 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4668 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004669 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4670 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004671#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004672 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004673 return(reader->ctxt->valid);
4674 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004675}
4676
4677/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004678 * xmlTextReaderGetErrorHandler:
4679 * @reader: the xmlTextReaderPtr used
4680 * @f: the callback function or NULL is no callback has been registered
4681 * @arg: a user argument
4682 *
4683 * Retrieve the error callback function and user argument.
4684 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004685void
4686xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4687 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004688 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004689 if (f != NULL) *f = reader->errorFunc;
4690 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004691}
4692
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004693
4694/************************************************************************
4695 * *
4696 * New set (2.6.0) of simpler and more flexible APIs *
4697 * *
4698 ************************************************************************/
4699
4700/**
4701 * xmlTextReaderSetup:
4702 * @reader: an XML reader
4703 * @URL: the base URL to use for the document
4704 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004705 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004706 * @reuse: keep the context for reuse
4707 *
4708 * Setup an XML reader with new options
4709 *
4710 * Returns 0 in case of success and -1 in case of error.
4711 */
4712static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004713xmlTextReaderSetup(xmlTextReaderPtr reader,
4714 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004715 const char *encoding, int options)
4716{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004717 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004718 return (-1);
4719
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004720 reader->doc = NULL;
4721 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004722 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004723 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004724 if ((input != NULL) && (reader->input != NULL) &&
4725 (reader->allocs & XML_TEXTREADER_INPUT)) {
4726 xmlFreeParserInputBuffer(reader->input);
4727 reader->input = NULL;
4728 reader->allocs -= XML_TEXTREADER_INPUT;
4729 }
4730 if (input != NULL) {
4731 reader->input = input;
4732 reader->allocs |= XML_TEXTREADER_INPUT;
4733 }
4734 if (reader->buffer == NULL)
4735 reader->buffer = xmlBufferCreateSize(100);
4736 if (reader->buffer == NULL) {
4737 xmlGenericError(xmlGenericErrorContext,
4738 "xmlTextReaderSetup : malloc failed\n");
4739 return (-1);
4740 }
4741 if (reader->sax == NULL)
4742 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4743 if (reader->sax == NULL) {
4744 xmlGenericError(xmlGenericErrorContext,
4745 "xmlTextReaderSetup : malloc failed\n");
4746 return (-1);
4747 }
4748 xmlSAXVersion(reader->sax, 2);
4749 reader->startElement = reader->sax->startElement;
4750 reader->sax->startElement = xmlTextReaderStartElement;
4751 reader->endElement = reader->sax->endElement;
4752 reader->sax->endElement = xmlTextReaderEndElement;
4753#ifdef LIBXML_SAX1_ENABLED
4754 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4755#endif /* LIBXML_SAX1_ENABLED */
4756 reader->startElementNs = reader->sax->startElementNs;
4757 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4758 reader->endElementNs = reader->sax->endElementNs;
4759 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4760#ifdef LIBXML_SAX1_ENABLED
4761 } else {
4762 reader->startElementNs = NULL;
4763 reader->endElementNs = NULL;
4764 }
4765#endif /* LIBXML_SAX1_ENABLED */
4766 reader->characters = reader->sax->characters;
4767 reader->sax->characters = xmlTextReaderCharacters;
4768 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4769 reader->cdataBlock = reader->sax->cdataBlock;
4770 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4771
4772 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4773 reader->node = NULL;
4774 reader->curnode = NULL;
4775 if (input != NULL) {
4776 if (reader->input->buffer->use < 4) {
4777 xmlParserInputBufferRead(input, 4);
4778 }
4779 if (reader->ctxt == NULL) {
4780 if (reader->input->buffer->use >= 4) {
4781 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4782 (const char *) reader->input->buffer->content, 4, URL);
4783 reader->base = 0;
4784 reader->cur = 4;
4785 } else {
4786 reader->ctxt =
4787 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4788 reader->base = 0;
4789 reader->cur = 0;
4790 }
4791 } else {
4792 xmlParserInputPtr inputStream;
4793 xmlParserInputBufferPtr buf;
4794 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4795
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004796 xmlCtxtReset(reader->ctxt);
4797 buf = xmlAllocParserInputBuffer(enc);
4798 if (buf == NULL) return(-1);
4799 inputStream = xmlNewInputStream(reader->ctxt);
4800 if (inputStream == NULL) {
4801 xmlFreeParserInputBuffer(buf);
4802 return(-1);
4803 }
4804
4805 if (URL == NULL)
4806 inputStream->filename = NULL;
4807 else
4808 inputStream->filename = (char *)
4809 xmlCanonicPath((const xmlChar *) URL);
4810 inputStream->buf = buf;
4811 inputStream->base = inputStream->buf->buffer->content;
4812 inputStream->cur = inputStream->buf->buffer->content;
4813 inputStream->end =
4814 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4815
4816 inputPush(reader->ctxt, inputStream);
4817 reader->cur = 0;
4818 }
4819 if (reader->ctxt == NULL) {
4820 xmlGenericError(xmlGenericErrorContext,
4821 "xmlTextReaderSetup : malloc failed\n");
4822 return (-1);
4823 }
4824 }
4825 if (reader->dict != NULL) {
4826 if (reader->ctxt->dict != NULL) {
4827 if (reader->dict != reader->ctxt->dict) {
4828 xmlDictFree(reader->dict);
4829 reader->dict = reader->ctxt->dict;
4830 }
4831 } else {
4832 reader->ctxt->dict = reader->dict;
4833 }
4834 } else {
4835 if (reader->ctxt->dict == NULL)
4836 reader->ctxt->dict = xmlDictCreate();
4837 reader->dict = reader->ctxt->dict;
4838 }
4839 reader->ctxt->_private = reader;
4840 reader->ctxt->linenumbers = 1;
4841 reader->ctxt->dictNames = 1;
4842 /*
4843 * use the parser dictionnary to allocate all elements and attributes names
4844 */
4845 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004846 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004847
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004848#ifdef LIBXML_XINCLUDE_ENABLED
4849 if (reader->xincctxt != NULL) {
4850 xmlXIncludeFreeContext(reader->xincctxt);
4851 reader->xincctxt = NULL;
4852 }
4853 if (options & XML_PARSE_XINCLUDE) {
4854 reader->xinclude = 1;
4855 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4856 options -= XML_PARSE_XINCLUDE;
4857 } else
4858 reader->xinclude = 0;
4859 reader->in_xinclude = 0;
4860#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004861#ifdef LIBXML_PATTERN_ENABLED
4862 if (reader->patternTab == NULL) {
4863 reader->patternNr = 0;
4864 reader->patternMax = 0;
4865 }
4866 while (reader->patternNr > 0) {
4867 reader->patternNr--;
4868 if (reader->patternTab[reader->patternNr] != NULL) {
4869 xmlFreePattern(reader->patternTab[reader->patternNr]);
4870 reader->patternTab[reader->patternNr] = NULL;
4871 }
4872 }
4873#endif
4874
Daniel Veillardc36965d2003-12-02 10:28:48 +00004875 if (options & XML_PARSE_DTDVALID)
4876 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4877
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004878 xmlCtxtUseOptions(reader->ctxt, options);
4879 if (encoding != NULL) {
4880 xmlCharEncodingHandlerPtr hdlr;
4881
4882 hdlr = xmlFindCharEncodingHandler(encoding);
4883 if (hdlr != NULL)
4884 xmlSwitchToEncoding(reader->ctxt, hdlr);
4885 }
4886 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4887 (reader->ctxt->input->filename == NULL))
4888 reader->ctxt->input->filename = (char *)
4889 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004890
4891 reader->doc = NULL;
4892
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004893 return (0);
4894}
4895
4896/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004897 * xmlTextReaderByteConsumed:
4898 * @reader: an XML reader
4899 *
4900 * This function provides the current index of the parser used
4901 * by the reader, relative to the start of the current entity.
4902 * This function actually just wraps a call to xmlBytesConsumed()
4903 * for the parser context associated with the reader.
4904 * See xmlBytesConsumed() for more information.
4905 *
4906 * Returns the index in bytes from the beginning of the entity or -1
4907 * in case the index could not be computed.
4908 */
4909long
4910xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4911 if ((reader == NULL) || (reader->ctxt == NULL))
4912 return(-1);
4913 return(xmlByteConsumed(reader->ctxt));
4914}
4915
4916
4917/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004918 * xmlReaderWalker:
4919 * @doc: a preparsed document
4920 *
4921 * Create an xmltextReader for a preparsed document.
4922 *
4923 * Returns the new reader or NULL in case of error.
4924 */
4925xmlTextReaderPtr
4926xmlReaderWalker(xmlDocPtr doc)
4927{
4928 xmlTextReaderPtr ret;
4929
4930 if (doc == NULL)
4931 return(NULL);
4932
4933 ret = xmlMalloc(sizeof(xmlTextReader));
4934 if (ret == NULL) {
4935 xmlGenericError(xmlGenericErrorContext,
4936 "xmlNewTextReader : malloc failed\n");
4937 return(NULL);
4938 }
4939 memset(ret, 0, sizeof(xmlTextReader));
4940 ret->entNr = 0;
4941 ret->input = NULL;
4942 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4943 ret->node = NULL;
4944 ret->curnode = NULL;
4945 ret->base = 0;
4946 ret->cur = 0;
4947 ret->allocs = XML_TEXTREADER_CTXT;
4948 ret->doc = doc;
4949 ret->state = XML_TEXTREADER_START;
4950 ret->dict = xmlDictCreate();
4951 return(ret);
4952}
4953
4954/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004955 * xmlReaderForDoc:
4956 * @cur: a pointer to a zero terminated string
4957 * @URL: the base URL to use for the document
4958 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004959 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004960 *
4961 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004962 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004963 *
4964 * Returns the new reader or NULL in case of error.
4965 */
4966xmlTextReaderPtr
4967xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4968 int options)
4969{
4970 int len;
4971
4972 if (cur == NULL)
4973 return (NULL);
4974 len = xmlStrlen(cur);
4975
4976 return (xmlReaderForMemory
4977 ((const char *) cur, len, URL, encoding, options));
4978}
4979
4980/**
4981 * xmlReaderForFile:
4982 * @filename: a file or URL
4983 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004984 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004985 *
4986 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004987 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004988 *
4989 * Returns the new reader or NULL in case of error.
4990 */
4991xmlTextReaderPtr
4992xmlReaderForFile(const char *filename, const char *encoding, int options)
4993{
4994 xmlTextReaderPtr reader;
4995
4996 reader = xmlNewTextReaderFilename(filename);
4997 if (reader == NULL)
4998 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004999 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005000 return (reader);
5001}
5002
5003/**
5004 * xmlReaderForMemory:
5005 * @buffer: a pointer to a char array
5006 * @size: the size of the array
5007 * @URL: the base URL to use for the document
5008 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005009 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005010 *
5011 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005012 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005013 *
5014 * Returns the new reader or NULL in case of error.
5015 */
5016xmlTextReaderPtr
5017xmlReaderForMemory(const char *buffer, int size, const char *URL,
5018 const char *encoding, int options)
5019{
5020 xmlTextReaderPtr reader;
5021 xmlParserInputBufferPtr buf;
5022
Daniel Veillard21924522004-02-19 16:37:07 +00005023 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005024 XML_CHAR_ENCODING_NONE);
5025 if (buf == NULL) {
5026 return (NULL);
5027 }
5028 reader = xmlNewTextReader(buf, URL);
5029 if (reader == NULL) {
5030 xmlFreeParserInputBuffer(buf);
5031 return (NULL);
5032 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005033 reader->allocs |= XML_TEXTREADER_INPUT;
5034 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005035 return (reader);
5036}
5037
5038/**
5039 * xmlReaderForFd:
5040 * @fd: an open file descriptor
5041 * @URL: the base URL to use for the document
5042 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005043 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005044 *
5045 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005046 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005047 * NOTE that the file descriptor will not be closed when the
5048 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005049 *
5050 * Returns the new reader or NULL in case of error.
5051 */
5052xmlTextReaderPtr
5053xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5054{
5055 xmlTextReaderPtr reader;
5056 xmlParserInputBufferPtr input;
5057
5058 if (fd < 0)
5059 return (NULL);
5060
5061 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5062 if (input == NULL)
5063 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005064 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005065 reader = xmlNewTextReader(input, URL);
5066 if (reader == NULL) {
5067 xmlFreeParserInputBuffer(input);
5068 return (NULL);
5069 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005070 reader->allocs |= XML_TEXTREADER_INPUT;
5071 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005072 return (reader);
5073}
5074
5075/**
5076 * xmlReaderForIO:
5077 * @ioread: an I/O read function
5078 * @ioclose: an I/O close function
5079 * @ioctx: an I/O handler
5080 * @URL: the base URL to use for the document
5081 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005082 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005083 *
5084 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005085 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005086 *
5087 * Returns the new reader or NULL in case of error.
5088 */
5089xmlTextReaderPtr
5090xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5091 void *ioctx, const char *URL, const char *encoding,
5092 int options)
5093{
5094 xmlTextReaderPtr reader;
5095 xmlParserInputBufferPtr input;
5096
5097 if (ioread == NULL)
5098 return (NULL);
5099
5100 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5101 XML_CHAR_ENCODING_NONE);
5102 if (input == NULL)
5103 return (NULL);
5104 reader = xmlNewTextReader(input, URL);
5105 if (reader == NULL) {
5106 xmlFreeParserInputBuffer(input);
5107 return (NULL);
5108 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005109 reader->allocs |= XML_TEXTREADER_INPUT;
5110 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005111 return (reader);
5112}
5113
5114/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005115 * xmlReaderNewWalker:
5116 * @reader: an XML reader
5117 * @doc: a preparsed document
5118 *
5119 * Setup an xmltextReader to parse a preparsed XML document.
5120 * This reuses the existing @reader xmlTextReader.
5121 *
5122 * Returns 0 in case of success and -1 in case of error
5123 */
5124int
5125xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5126{
5127 if (doc == NULL)
5128 return (-1);
5129 if (reader == NULL)
5130 return (-1);
5131
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005132 if (reader->input != NULL) {
5133 xmlFreeParserInputBuffer(reader->input);
5134 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005135 if (reader->ctxt != NULL) {
5136 xmlCtxtReset(reader->ctxt);
5137 }
5138
5139 reader->entNr = 0;
5140 reader->input = NULL;
5141 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5142 reader->node = NULL;
5143 reader->curnode = NULL;
5144 reader->base = 0;
5145 reader->cur = 0;
5146 reader->allocs = XML_TEXTREADER_CTXT;
5147 reader->doc = doc;
5148 reader->state = XML_TEXTREADER_START;
5149 if (reader->dict == NULL) {
5150 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5151 reader->dict = reader->ctxt->dict;
5152 else
5153 reader->dict = xmlDictCreate();
5154 }
5155 return(0);
5156}
5157
5158/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005159 * xmlReaderNewDoc:
5160 * @reader: an XML reader
5161 * @cur: a pointer to a zero terminated string
5162 * @URL: the base URL to use for the document
5163 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005164 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005165 *
5166 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005167 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005168 * This reuses the existing @reader xmlTextReader.
5169 *
5170 * Returns 0 in case of success and -1 in case of error
5171 */
5172int
5173xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5174 const char *URL, const char *encoding, int options)
5175{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005176
5177 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005178
5179 if (cur == NULL)
5180 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005181 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005182 return (-1);
5183
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005184 len = xmlStrlen(cur);
5185 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5186 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005187}
5188
5189/**
5190 * xmlReaderNewFile:
5191 * @reader: an XML reader
5192 * @filename: a file or URL
5193 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005194 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005195 *
5196 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005197 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005198 * This reuses the existing @reader xmlTextReader.
5199 *
5200 * Returns 0 in case of success and -1 in case of error
5201 */
5202int
5203xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5204 const char *encoding, int options)
5205{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005206 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005207
5208 if (filename == NULL)
5209 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005210 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005211 return (-1);
5212
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005213 input =
5214 xmlParserInputBufferCreateFilename(filename,
5215 XML_CHAR_ENCODING_NONE);
5216 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005217 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005218 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005219}
5220
5221/**
5222 * xmlReaderNewMemory:
5223 * @reader: an XML reader
5224 * @buffer: a pointer to a char array
5225 * @size: the size of the array
5226 * @URL: the base URL to use for the document
5227 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005228 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005229 *
5230 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005231 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005232 * This reuses the existing @reader xmlTextReader.
5233 *
5234 * Returns 0 in case of success and -1 in case of error
5235 */
5236int
5237xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5238 const char *URL, const char *encoding, int options)
5239{
5240 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005241
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005242 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005243 return (-1);
5244 if (buffer == NULL)
5245 return (-1);
5246
Daniel Veillard21924522004-02-19 16:37:07 +00005247 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005248 XML_CHAR_ENCODING_NONE);
5249 if (input == NULL) {
5250 return (-1);
5251 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005252 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005253}
5254
5255/**
5256 * xmlReaderNewFd:
5257 * @reader: an XML reader
5258 * @fd: an open file descriptor
5259 * @URL: the base URL to use for the document
5260 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005261 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005262 *
5263 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005264 * NOTE that the file descriptor will not be closed when the
5265 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005266 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005267 * This reuses the existing @reader xmlTextReader.
5268 *
5269 * Returns 0 in case of success and -1 in case of error
5270 */
5271int
5272xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5273 const char *URL, const char *encoding, int options)
5274{
5275 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005276
5277 if (fd < 0)
5278 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005279 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005280 return (-1);
5281
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005282 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5283 if (input == NULL)
5284 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005285 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005286 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005287}
5288
5289/**
5290 * xmlReaderNewIO:
5291 * @reader: an XML reader
5292 * @ioread: an I/O read function
5293 * @ioclose: an I/O close function
5294 * @ioctx: an I/O handler
5295 * @URL: the base URL to use for the document
5296 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005297 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005298 *
5299 * Setup an xmltextReader to parse an XML document from I/O functions
5300 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005301 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005302 * This reuses the existing @reader xmlTextReader.
5303 *
5304 * Returns 0 in case of success and -1 in case of error
5305 */
5306int
5307xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5308 xmlInputCloseCallback ioclose, void *ioctx,
5309 const char *URL, const char *encoding, int options)
5310{
5311 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005312
5313 if (ioread == NULL)
5314 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005315 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005316 return (-1);
5317
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005318 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5319 XML_CHAR_ENCODING_NONE);
5320 if (input == NULL)
5321 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005322 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005323}
Daniel Veillard26f70262003-01-16 22:45:08 +00005324/************************************************************************
5325 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005326 * Utilities *
5327 * *
5328 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005329#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005330/**
5331 * xmlBase64Decode:
5332 * @in: the input buffer
5333 * @inlen: the size of the input (in), the size read from it (out)
5334 * @to: the output buffer
5335 * @tolen: the size of the output (in), the size written to (out)
5336 *
5337 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005338 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005339 *
5340 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5341 * 2 if there wasn't enough space on the output or -1 in case of error.
5342 */
5343static int
5344xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5345 unsigned char *to, unsigned long *tolen) {
5346 unsigned long incur; /* current index in in[] */
5347 unsigned long inblk; /* last block index in in[] */
5348 unsigned long outcur; /* current index in out[] */
5349 unsigned long inmax; /* size of in[] */
5350 unsigned long outmax; /* size of out[] */
5351 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005352 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005353 int nbintmp; /* number of byte in intmp[] */
5354 int is_ignore; /* cur should be ignored */
5355 int is_end = 0; /* the end of the base64 was found */
5356 int retval = 1;
5357 int i;
5358
5359 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5360 return(-1);
5361
5362 incur = 0;
5363 inblk = 0;
5364 outcur = 0;
5365 inmax = *inlen;
5366 outmax = *tolen;
5367 nbintmp = 0;
5368
5369 while (1) {
5370 if (incur >= inmax)
5371 break;
5372 cur = in[incur++];
5373 is_ignore = 0;
5374 if ((cur >= 'A') && (cur <= 'Z'))
5375 cur = cur - 'A';
5376 else if ((cur >= 'a') && (cur <= 'z'))
5377 cur = cur - 'a' + 26;
5378 else if ((cur >= '0') && (cur <= '9'))
5379 cur = cur - '0' + 52;
5380 else if (cur == '+')
5381 cur = 62;
5382 else if (cur == '/')
5383 cur = 63;
5384 else if (cur == '.')
5385 cur = 0;
5386 else if (cur == '=') /*no op , end of the base64 stream */
5387 is_end = 1;
5388 else {
5389 is_ignore = 1;
5390 if (nbintmp == 0)
5391 inblk = incur;
5392 }
5393
5394 if (!is_ignore) {
5395 int nbouttmp = 3;
5396 int is_break = 0;
5397
5398 if (is_end) {
5399 if (nbintmp == 0)
5400 break;
5401 if ((nbintmp == 1) || (nbintmp == 2))
5402 nbouttmp = 1;
5403 else
5404 nbouttmp = 2;
5405 nbintmp = 3;
5406 is_break = 1;
5407 }
5408 intmp[nbintmp++] = cur;
5409 /*
5410 * if intmp is full, push the 4byte sequence as a 3 byte
5411 * sequence out
5412 */
5413 if (nbintmp == 4) {
5414 nbintmp = 0;
5415 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5416 outtmp[1] =
5417 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5418 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5419 if (outcur + 3 >= outmax) {
5420 retval = 2;
5421 break;
5422 }
5423
5424 for (i = 0; i < nbouttmp; i++)
5425 to[outcur++] = outtmp[i];
5426 inblk = incur;
5427 }
5428
5429 if (is_break) {
5430 retval = 0;
5431 break;
5432 }
5433 }
5434 }
5435
5436 *tolen = outcur;
5437 *inlen = inblk;
5438 return (retval);
5439}
5440
5441/*
5442 * Test routine for the xmlBase64Decode function
5443 */
5444#if 0
5445int main(int argc, char **argv) {
5446 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5447 char output[100];
5448 char output2[100];
5449 char output3[100];
5450 unsigned long inlen = strlen(input);
5451 unsigned long outlen = 100;
5452 int ret;
5453 unsigned long cons, tmp, tmp2, prod;
5454
5455 /*
5456 * Direct
5457 */
5458 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5459
5460 output[outlen] = 0;
5461 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5462
5463 /*
5464 * output chunking
5465 */
5466 cons = 0;
5467 prod = 0;
5468 while (cons < inlen) {
5469 tmp = 5;
5470 tmp2 = inlen - cons;
5471
5472 printf("%ld %ld\n", cons, prod);
5473 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5474 cons += tmp2;
5475 prod += tmp;
5476 printf("%ld %ld\n", cons, prod);
5477 }
5478 output2[outlen] = 0;
5479 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5480
5481 /*
5482 * input chunking
5483 */
5484 cons = 0;
5485 prod = 0;
5486 while (cons < inlen) {
5487 tmp = 100 - prod;
5488 tmp2 = inlen - cons;
5489 if (tmp2 > 5)
5490 tmp2 = 5;
5491
5492 printf("%ld %ld\n", cons, prod);
5493 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5494 cons += tmp2;
5495 prod += tmp;
5496 printf("%ld %ld\n", cons, prod);
5497 }
5498 output3[outlen] = 0;
5499 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5500 return(0);
5501
5502}
5503#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005504#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005505#define bottom_xmlreader
5506#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005507#endif /* LIBXML_READER_ENABLED */