blob: b1bac0810326ea6dbb61d814ba583b4276a350d4 [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);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002312 if (localname == NULL) {
2313 /*
2314 * Namespace default decl
2315 */
2316 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2317 ns = reader->node->nsDef;
2318 while (ns != NULL) {
2319 if (ns->prefix == NULL) {
2320 return(xmlStrdup(ns->href));
2321 }
2322 ns = ns->next;
2323 }
2324 return NULL;
2325 }
2326 return(xmlGetNoNsProp(reader->node, name));
2327 }
2328
2329 /*
2330 * Namespace default decl
2331 */
2332 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2333 ns = reader->node->nsDef;
2334 while (ns != NULL) {
2335 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2336 ret = xmlStrdup(ns->href);
2337 break;
2338 }
2339 ns = ns->next;
2340 }
2341 } else {
2342 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2343 if (ns != NULL)
2344 ret = xmlGetNsProp(reader->node, localname, ns->href);
2345 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002346
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002347 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002348 if (prefix != NULL)
2349 xmlFree(prefix);
2350 return(ret);
2351}
2352
2353
2354/**
2355 * xmlTextReaderGetAttributeNs:
2356 * @reader: the xmlTextReaderPtr used
2357 * @localName: the local name of the attribute.
2358 * @namespaceURI: the namespace URI of the attribute.
2359 *
2360 * Provides the value of the specified attribute
2361 *
2362 * Returns a string containing the value of the specified attribute, or NULL
2363 * in case of error. The string must be deallocated by the caller.
2364 */
2365xmlChar *
2366xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2367 const xmlChar *namespaceURI) {
2368 if ((reader == NULL) || (localName == NULL))
2369 return(NULL);
2370 if (reader->node == NULL)
2371 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002372 if (reader->curnode != NULL)
2373 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002374
2375 /* TODO: handle the xmlDecl */
2376 if (reader->node->type != XML_ELEMENT_NODE)
2377 return(NULL);
2378
2379 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2380}
2381
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002382/**
2383 * xmlTextReaderGetRemainder:
2384 * @reader: the xmlTextReaderPtr used
2385 *
2386 * Method to get the remainder of the buffered XML. this method stops the
2387 * parser, set its state to End Of File and return the input stream with
2388 * what is left that the parser did not use.
2389 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002390 * The implementation is not good, the parser certainly procgressed past
2391 * what's left in reader->input, and there is an allocation problem. Best
2392 * would be to rewrite it differently.
2393 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002394 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2395 * in case of error.
2396 */
2397xmlParserInputBufferPtr
2398xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2399 xmlParserInputBufferPtr ret = NULL;
2400
2401 if (reader == NULL)
2402 return(NULL);
2403 if (reader->node == NULL)
2404 return(NULL);
2405
2406 reader->node = NULL;
2407 reader->curnode = NULL;
2408 reader->mode = XML_TEXTREADER_MODE_EOF;
2409 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002410 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002411 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002412 if (reader->preserve == 0)
2413 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002414 reader->ctxt->myDoc = NULL;
2415 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002416 }
2417 if (reader->allocs & XML_TEXTREADER_INPUT) {
2418 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002419 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002420 reader->allocs -= XML_TEXTREADER_INPUT;
2421 } else {
2422 /*
2423 * Hum, one may need to duplicate the data structure because
2424 * without reference counting the input may be freed twice:
2425 * - by the layer which allocated it.
2426 * - by the layer to which would have been returned to.
2427 */
2428 TODO
2429 return(NULL);
2430 }
2431 return(ret);
2432}
2433
2434/**
2435 * xmlTextReaderLookupNamespace:
2436 * @reader: the xmlTextReaderPtr used
2437 * @prefix: the prefix whose namespace URI is to be resolved. To return
2438 * the default namespace, specify NULL
2439 *
2440 * Resolves a namespace prefix in the scope of the current element.
2441 *
2442 * Returns a string containing the namespace URI to which the prefix maps
2443 * or NULL in case of error. The string must be deallocated by the caller.
2444 */
2445xmlChar *
2446xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2447 xmlNsPtr ns;
2448
2449 if (reader == NULL)
2450 return(NULL);
2451 if (reader->node == NULL)
2452 return(NULL);
2453
2454 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2455 if (ns == NULL)
2456 return(NULL);
2457 return(xmlStrdup(ns->href));
2458}
2459
2460/**
2461 * xmlTextReaderMoveToAttributeNo:
2462 * @reader: the xmlTextReaderPtr used
2463 * @no: the zero-based index of the attribute relative to the containing
2464 * element.
2465 *
2466 * Moves the position of the current instance to the attribute with
2467 * the specified index relative to the containing element.
2468 *
2469 * Returns 1 in case of success, -1 in case of error, 0 if not found
2470 */
2471int
2472xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2473 int i;
2474 xmlAttrPtr cur;
2475 xmlNsPtr ns;
2476
2477 if (reader == NULL)
2478 return(-1);
2479 if (reader->node == NULL)
2480 return(-1);
2481 /* TODO: handle the xmlDecl */
2482 if (reader->node->type != XML_ELEMENT_NODE)
2483 return(-1);
2484
2485 reader->curnode = NULL;
2486
2487 ns = reader->node->nsDef;
2488 for (i = 0;(i < no) && (ns != NULL);i++) {
2489 ns = ns->next;
2490 }
2491 if (ns != NULL) {
2492 reader->curnode = (xmlNodePtr) ns;
2493 return(1);
2494 }
2495
2496 cur = reader->node->properties;
2497 if (cur == NULL)
2498 return(0);
2499 for (;i < no;i++) {
2500 cur = cur->next;
2501 if (cur == NULL)
2502 return(0);
2503 }
2504 /* TODO walk the DTD if present */
2505
2506 reader->curnode = (xmlNodePtr) cur;
2507 return(1);
2508}
2509
2510/**
2511 * xmlTextReaderMoveToAttribute:
2512 * @reader: the xmlTextReaderPtr used
2513 * @name: the qualified name of the attribute.
2514 *
2515 * Moves the position of the current instance to the attribute with
2516 * the specified qualified name.
2517 *
2518 * Returns 1 in case of success, -1 in case of error, 0 if not found
2519 */
2520int
2521xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2522 xmlChar *prefix = NULL;
2523 xmlChar *localname;
2524 xmlNsPtr ns;
2525 xmlAttrPtr prop;
2526
2527 if ((reader == NULL) || (name == NULL))
2528 return(-1);
2529 if (reader->node == NULL)
2530 return(-1);
2531
2532 /* TODO: handle the xmlDecl */
2533 if (reader->node->type != XML_ELEMENT_NODE)
2534 return(0);
2535
2536 localname = xmlSplitQName2(name, &prefix);
2537 if (localname == NULL) {
2538 /*
2539 * Namespace default decl
2540 */
2541 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2542 ns = reader->node->nsDef;
2543 while (ns != NULL) {
2544 if (ns->prefix == NULL) {
2545 reader->curnode = (xmlNodePtr) ns;
2546 return(1);
2547 }
2548 ns = ns->next;
2549 }
2550 return(0);
2551 }
2552
2553 prop = reader->node->properties;
2554 while (prop != NULL) {
2555 /*
2556 * One need to have
2557 * - same attribute names
2558 * - and the attribute carrying that namespace
2559 */
2560 if ((xmlStrEqual(prop->name, name)) &&
2561 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2562 reader->curnode = (xmlNodePtr) prop;
2563 return(1);
2564 }
2565 prop = prop->next;
2566 }
2567 return(0);
2568 }
2569
2570 /*
2571 * Namespace default decl
2572 */
2573 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2574 ns = reader->node->nsDef;
2575 while (ns != NULL) {
2576 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2577 reader->curnode = (xmlNodePtr) ns;
2578 goto found;
2579 }
2580 ns = ns->next;
2581 }
2582 goto not_found;
2583 }
2584 prop = reader->node->properties;
2585 while (prop != NULL) {
2586 /*
2587 * One need to have
2588 * - same attribute names
2589 * - and the attribute carrying that namespace
2590 */
2591 if ((xmlStrEqual(prop->name, localname)) &&
2592 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2593 reader->curnode = (xmlNodePtr) prop;
2594 goto found;
2595 }
2596 prop = prop->next;
2597 }
2598not_found:
2599 if (localname != NULL)
2600 xmlFree(localname);
2601 if (prefix != NULL)
2602 xmlFree(prefix);
2603 return(0);
2604
2605found:
2606 if (localname != NULL)
2607 xmlFree(localname);
2608 if (prefix != NULL)
2609 xmlFree(prefix);
2610 return(1);
2611}
2612
2613/**
2614 * xmlTextReaderMoveToAttributeNs:
2615 * @reader: the xmlTextReaderPtr used
2616 * @localName: the local name of the attribute.
2617 * @namespaceURI: the namespace URI of the attribute.
2618 *
2619 * Moves the position of the current instance to the attribute with the
2620 * specified local name and namespace URI.
2621 *
2622 * Returns 1 in case of success, -1 in case of error, 0 if not found
2623 */
2624int
2625xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2626 const xmlChar *localName, const xmlChar *namespaceURI) {
2627 xmlAttrPtr prop;
2628 xmlNodePtr node;
2629
2630 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2631 return(-1);
2632 if (reader->node == NULL)
2633 return(-1);
2634 if (reader->node->type != XML_ELEMENT_NODE)
2635 return(0);
2636 node = reader->node;
2637
2638 /*
2639 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2640 * namespace name associated to "xmlns"
2641 */
2642 prop = node->properties;
2643 while (prop != NULL) {
2644 /*
2645 * One need to have
2646 * - same attribute names
2647 * - and the attribute carrying that namespace
2648 */
2649 if (xmlStrEqual(prop->name, localName) &&
2650 ((prop->ns != NULL) &&
2651 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2652 reader->curnode = (xmlNodePtr) prop;
2653 return(1);
2654 }
2655 prop = prop->next;
2656 }
2657 return(0);
2658}
2659
2660/**
2661 * xmlTextReaderMoveToFirstAttribute:
2662 * @reader: the xmlTextReaderPtr used
2663 *
2664 * Moves the position of the current instance to the first attribute
2665 * associated with the current node.
2666 *
2667 * Returns 1 in case of success, -1 in case of error, 0 if not found
2668 */
2669int
2670xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2671 if (reader == NULL)
2672 return(-1);
2673 if (reader->node == NULL)
2674 return(-1);
2675 if (reader->node->type != XML_ELEMENT_NODE)
2676 return(0);
2677
2678 if (reader->node->nsDef != NULL) {
2679 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2680 return(1);
2681 }
2682 if (reader->node->properties != NULL) {
2683 reader->curnode = (xmlNodePtr) reader->node->properties;
2684 return(1);
2685 }
2686 return(0);
2687}
2688
2689/**
2690 * xmlTextReaderMoveToNextAttribute:
2691 * @reader: the xmlTextReaderPtr used
2692 *
2693 * Moves the position of the current instance to the next attribute
2694 * associated with the current node.
2695 *
2696 * Returns 1 in case of success, -1 in case of error, 0 if not found
2697 */
2698int
2699xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2700 if (reader == NULL)
2701 return(-1);
2702 if (reader->node == NULL)
2703 return(-1);
2704 if (reader->node->type != XML_ELEMENT_NODE)
2705 return(0);
2706 if (reader->curnode == NULL)
2707 return(xmlTextReaderMoveToFirstAttribute(reader));
2708
2709 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2710 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2711 if (ns->next != NULL) {
2712 reader->curnode = (xmlNodePtr) ns->next;
2713 return(1);
2714 }
2715 if (reader->node->properties != NULL) {
2716 reader->curnode = (xmlNodePtr) reader->node->properties;
2717 return(1);
2718 }
2719 return(0);
2720 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2721 (reader->curnode->next != NULL)) {
2722 reader->curnode = reader->curnode->next;
2723 return(1);
2724 }
2725 return(0);
2726}
2727
2728/**
2729 * xmlTextReaderMoveToElement:
2730 * @reader: the xmlTextReaderPtr used
2731 *
2732 * Moves the position of the current instance to the node that
2733 * contains the current Attribute node.
2734 *
2735 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2736 */
2737int
2738xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2739 if (reader == NULL)
2740 return(-1);
2741 if (reader->node == NULL)
2742 return(-1);
2743 if (reader->node->type != XML_ELEMENT_NODE)
2744 return(0);
2745 if (reader->curnode != NULL) {
2746 reader->curnode = NULL;
2747 return(1);
2748 }
2749 return(0);
2750}
2751
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002752/**
2753 * xmlTextReaderReadAttributeValue:
2754 * @reader: the xmlTextReaderPtr used
2755 *
2756 * Parses an attribute value into one or more Text and EntityReference nodes.
2757 *
2758 * Returns 1 in case of success, 0 if the reader was not positionned on an
2759 * ttribute node or all the attribute values have been read, or -1
2760 * in case of error.
2761 */
2762int
2763xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2764 if (reader == NULL)
2765 return(-1);
2766 if (reader->node == NULL)
2767 return(-1);
2768 if (reader->curnode == NULL)
2769 return(0);
2770 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2771 if (reader->curnode->children == NULL)
2772 return(0);
2773 reader->curnode = reader->curnode->children;
2774 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2775 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2776
2777 if (reader->faketext == NULL) {
2778 reader->faketext = xmlNewDocText(reader->node->doc,
2779 ns->href);
2780 } else {
2781 if (reader->faketext->content != NULL)
2782 xmlFree(reader->faketext->content);
2783 reader->faketext->content = xmlStrdup(ns->href);
2784 }
2785 reader->curnode = reader->faketext;
2786 } else {
2787 if (reader->curnode->next == NULL)
2788 return(0);
2789 reader->curnode = reader->curnode->next;
2790 }
2791 return(1);
2792}
2793
Daniel Veillarde2811272004-10-19 09:04:23 +00002794/**
2795 * xmlTextReaderConstEncoding:
2796 * @reader: the xmlTextReaderPtr used
2797 *
2798 * Determine the encoding of the document being read.
2799 *
2800 * Returns a string containing the encoding of the document or NULL in
2801 * case of error. The string is deallocated with the reader.
2802 */
2803const xmlChar *
2804xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2805 xmlDocPtr doc = NULL;
2806 if (reader == NULL)
2807 return(NULL);
2808 if (reader->doc != NULL)
2809 doc = reader->doc;
2810 else if (reader->ctxt != NULL)
2811 doc = reader->ctxt->myDoc;
2812 if (doc == NULL)
2813 return(NULL);
2814
2815 if (doc->encoding == NULL)
2816 return(NULL);
2817 else
2818 return(CONSTSTR(doc->encoding));
2819}
2820
2821
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002822/************************************************************************
2823 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002824 * Acces API to the current node *
2825 * *
2826 ************************************************************************/
2827/**
2828 * xmlTextReaderAttributeCount:
2829 * @reader: the xmlTextReaderPtr used
2830 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002831 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002832 *
2833 * Returns 0 i no attributes, -1 in case of error or the attribute count
2834 */
2835int
2836xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2837 int ret;
2838 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002839 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002840 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002841
2842 if (reader == NULL)
2843 return(-1);
2844 if (reader->node == NULL)
2845 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002846
2847 if (reader->curnode != NULL)
2848 node = reader->curnode;
2849 else
2850 node = reader->node;
2851
2852 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002853 return(0);
2854 if ((reader->state == XML_TEXTREADER_END) ||
2855 (reader->state == XML_TEXTREADER_BACKTRACK))
2856 return(0);
2857 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002858 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002859 while (attr != NULL) {
2860 ret++;
2861 attr = attr->next;
2862 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002863 ns = node->nsDef;
2864 while (ns != NULL) {
2865 ret++;
2866 ns = ns->next;
2867 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002868 return(ret);
2869}
2870
2871/**
2872 * xmlTextReaderNodeType:
2873 * @reader: the xmlTextReaderPtr used
2874 *
2875 * Get the node type of the current node
2876 * Reference:
2877 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2878 *
2879 * Returns the xmlNodeType of the current node or -1 in case of error
2880 */
2881int
2882xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002883 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002884
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002885 if (reader == NULL)
2886 return(-1);
2887 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002888 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002889 if (reader->curnode != NULL)
2890 node = reader->curnode;
2891 else
2892 node = reader->node;
2893 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002894 case XML_ELEMENT_NODE:
2895 if ((reader->state == XML_TEXTREADER_END) ||
2896 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002897 return(XML_READER_TYPE_END_ELEMENT);
2898 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002899 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002900 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002901 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002902 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002903 if (xmlIsBlankNode(reader->node)) {
2904 if (xmlNodeGetSpacePreserve(reader->node))
2905 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2906 else
2907 return(XML_READER_TYPE_WHITESPACE);
2908 } else {
2909 return(XML_READER_TYPE_TEXT);
2910 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002911 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002912 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002913 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002914 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002915 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002916 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002917 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002918 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002920 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002921 case XML_DOCUMENT_NODE:
2922 case XML_HTML_DOCUMENT_NODE:
2923#ifdef LIBXML_DOCB_ENABLED
2924 case XML_DOCB_DOCUMENT_NODE:
2925#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002926 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002927 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002928 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002929 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002930 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002931 case XML_DOCUMENT_TYPE_NODE:
2932 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002933 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002934
2935 case XML_ELEMENT_DECL:
2936 case XML_ATTRIBUTE_DECL:
2937 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002938 case XML_XINCLUDE_START:
2939 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002940 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002941 }
2942 return(-1);
2943}
2944
2945/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002946 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002947 * @reader: the xmlTextReaderPtr used
2948 *
2949 * Check if the current node is empty
2950 *
2951 * Returns 1 if empty, 0 if not and -1 in case of error
2952 */
2953int
2954xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2955 if ((reader == NULL) || (reader->node == NULL))
2956 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002957 if (reader->node->type != XML_ELEMENT_NODE)
2958 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002959 if (reader->curnode != NULL)
2960 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002961 if (reader->node->children != NULL)
2962 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002963 if (reader->state == XML_TEXTREADER_END)
2964 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002965 if (reader->doc != NULL)
2966 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002967#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002968 if (reader->in_xinclude > 0)
2969 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002970#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002971 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002972}
2973
2974/**
2975 * xmlTextReaderLocalName:
2976 * @reader: the xmlTextReaderPtr used
2977 *
2978 * The local name of the node.
2979 *
2980 * Returns the local name or NULL if not available
2981 */
2982xmlChar *
2983xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002984 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985 if ((reader == NULL) || (reader->node == NULL))
2986 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002987 if (reader->curnode != NULL)
2988 node = reader->curnode;
2989 else
2990 node = reader->node;
2991 if (node->type == XML_NAMESPACE_DECL) {
2992 xmlNsPtr ns = (xmlNsPtr) node;
2993 if (ns->prefix == NULL)
2994 return(xmlStrdup(BAD_CAST "xmlns"));
2995 else
2996 return(xmlStrdup(ns->prefix));
2997 }
2998 if ((node->type != XML_ELEMENT_NODE) &&
2999 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003000 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003001 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003002}
3003
3004/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003005 * xmlTextReaderConstLocalName:
3006 * @reader: the xmlTextReaderPtr used
3007 *
3008 * The local name of the node.
3009 *
3010 * Returns the local name or NULL if not available, the
3011 * string will be deallocated with the reader.
3012 */
3013const xmlChar *
3014xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3015 xmlNodePtr node;
3016 if ((reader == NULL) || (reader->node == NULL))
3017 return(NULL);
3018 if (reader->curnode != NULL)
3019 node = reader->curnode;
3020 else
3021 node = reader->node;
3022 if (node->type == XML_NAMESPACE_DECL) {
3023 xmlNsPtr ns = (xmlNsPtr) node;
3024 if (ns->prefix == NULL)
3025 return(CONSTSTR(BAD_CAST "xmlns"));
3026 else
3027 return(ns->prefix);
3028 }
3029 if ((node->type != XML_ELEMENT_NODE) &&
3030 (node->type != XML_ATTRIBUTE_NODE))
3031 return(xmlTextReaderConstName(reader));
3032 return(node->name);
3033}
3034
3035/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003036 * xmlTextReaderName:
3037 * @reader: the xmlTextReaderPtr used
3038 *
3039 * The qualified name of the node, equal to Prefix :LocalName.
3040 *
3041 * Returns the local name or NULL if not available
3042 */
3043xmlChar *
3044xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003045 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046 xmlChar *ret;
3047
3048 if ((reader == NULL) || (reader->node == NULL))
3049 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003050 if (reader->curnode != NULL)
3051 node = reader->curnode;
3052 else
3053 node = reader->node;
3054 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003055 case XML_ELEMENT_NODE:
3056 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003057 if ((node->ns == NULL) ||
3058 (node->ns->prefix == NULL))
3059 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003060
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003061 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003062 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003063 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003064 return(ret);
3065 case XML_TEXT_NODE:
3066 return(xmlStrdup(BAD_CAST "#text"));
3067 case XML_CDATA_SECTION_NODE:
3068 return(xmlStrdup(BAD_CAST "#cdata-section"));
3069 case XML_ENTITY_NODE:
3070 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003071 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003072 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003073 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003074 case XML_COMMENT_NODE:
3075 return(xmlStrdup(BAD_CAST "#comment"));
3076 case XML_DOCUMENT_NODE:
3077 case XML_HTML_DOCUMENT_NODE:
3078#ifdef LIBXML_DOCB_ENABLED
3079 case XML_DOCB_DOCUMENT_NODE:
3080#endif
3081 return(xmlStrdup(BAD_CAST "#document"));
3082 case XML_DOCUMENT_FRAG_NODE:
3083 return(xmlStrdup(BAD_CAST "#document-fragment"));
3084 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003085 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003086 case XML_DOCUMENT_TYPE_NODE:
3087 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003088 return(xmlStrdup(node->name));
3089 case XML_NAMESPACE_DECL: {
3090 xmlNsPtr ns = (xmlNsPtr) node;
3091
3092 ret = xmlStrdup(BAD_CAST "xmlns");
3093 if (ns->prefix == NULL)
3094 return(ret);
3095 ret = xmlStrcat(ret, BAD_CAST ":");
3096 ret = xmlStrcat(ret, ns->prefix);
3097 return(ret);
3098 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003099
3100 case XML_ELEMENT_DECL:
3101 case XML_ATTRIBUTE_DECL:
3102 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003103 case XML_XINCLUDE_START:
3104 case XML_XINCLUDE_END:
3105 return(NULL);
3106 }
3107 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003108}
3109
3110/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003111 * xmlTextReaderConstName:
3112 * @reader: the xmlTextReaderPtr used
3113 *
3114 * The qualified name of the node, equal to Prefix :LocalName.
3115 *
3116 * Returns the local name or NULL if not available, the string is
3117 * deallocated with the reader.
3118 */
3119const xmlChar *
3120xmlTextReaderConstName(xmlTextReaderPtr reader) {
3121 xmlNodePtr node;
3122
3123 if ((reader == NULL) || (reader->node == NULL))
3124 return(NULL);
3125 if (reader->curnode != NULL)
3126 node = reader->curnode;
3127 else
3128 node = reader->node;
3129 switch (node->type) {
3130 case XML_ELEMENT_NODE:
3131 case XML_ATTRIBUTE_NODE:
3132 if ((node->ns == NULL) ||
3133 (node->ns->prefix == NULL))
3134 return(node->name);
3135 return(CONSTQSTR(node->ns->prefix, node->name));
3136 case XML_TEXT_NODE:
3137 return(CONSTSTR(BAD_CAST "#text"));
3138 case XML_CDATA_SECTION_NODE:
3139 return(CONSTSTR(BAD_CAST "#cdata-section"));
3140 case XML_ENTITY_NODE:
3141 case XML_ENTITY_REF_NODE:
3142 return(CONSTSTR(node->name));
3143 case XML_PI_NODE:
3144 return(CONSTSTR(node->name));
3145 case XML_COMMENT_NODE:
3146 return(CONSTSTR(BAD_CAST "#comment"));
3147 case XML_DOCUMENT_NODE:
3148 case XML_HTML_DOCUMENT_NODE:
3149#ifdef LIBXML_DOCB_ENABLED
3150 case XML_DOCB_DOCUMENT_NODE:
3151#endif
3152 return(CONSTSTR(BAD_CAST "#document"));
3153 case XML_DOCUMENT_FRAG_NODE:
3154 return(CONSTSTR(BAD_CAST "#document-fragment"));
3155 case XML_NOTATION_NODE:
3156 return(CONSTSTR(node->name));
3157 case XML_DOCUMENT_TYPE_NODE:
3158 case XML_DTD_NODE:
3159 return(CONSTSTR(node->name));
3160 case XML_NAMESPACE_DECL: {
3161 xmlNsPtr ns = (xmlNsPtr) node;
3162
3163 if (ns->prefix == NULL)
3164 return(CONSTSTR(BAD_CAST "xmlns"));
3165 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3166 }
3167
3168 case XML_ELEMENT_DECL:
3169 case XML_ATTRIBUTE_DECL:
3170 case XML_ENTITY_DECL:
3171 case XML_XINCLUDE_START:
3172 case XML_XINCLUDE_END:
3173 return(NULL);
3174 }
3175 return(NULL);
3176}
3177
3178/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003179 * xmlTextReaderPrefix:
3180 * @reader: the xmlTextReaderPtr used
3181 *
3182 * A shorthand reference to the namespace associated with the node.
3183 *
3184 * Returns the prefix or NULL if not available
3185 */
3186xmlChar *
3187xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003188 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003189 if ((reader == NULL) || (reader->node == NULL))
3190 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003191 if (reader->curnode != NULL)
3192 node = reader->curnode;
3193 else
3194 node = reader->node;
3195 if (node->type == XML_NAMESPACE_DECL) {
3196 xmlNsPtr ns = (xmlNsPtr) node;
3197 if (ns->prefix == NULL)
3198 return(NULL);
3199 return(xmlStrdup(BAD_CAST "xmlns"));
3200 }
3201 if ((node->type != XML_ELEMENT_NODE) &&
3202 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003203 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003204 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003205 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003206 return(NULL);
3207}
3208
3209/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003210 * xmlTextReaderConstPrefix:
3211 * @reader: the xmlTextReaderPtr used
3212 *
3213 * A shorthand reference to the namespace associated with the node.
3214 *
3215 * Returns the prefix or NULL if not available, the string is deallocated
3216 * with the reader.
3217 */
3218const xmlChar *
3219xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3220 xmlNodePtr node;
3221 if ((reader == NULL) || (reader->node == NULL))
3222 return(NULL);
3223 if (reader->curnode != NULL)
3224 node = reader->curnode;
3225 else
3226 node = reader->node;
3227 if (node->type == XML_NAMESPACE_DECL) {
3228 xmlNsPtr ns = (xmlNsPtr) node;
3229 if (ns->prefix == NULL)
3230 return(NULL);
3231 return(CONSTSTR(BAD_CAST "xmlns"));
3232 }
3233 if ((node->type != XML_ELEMENT_NODE) &&
3234 (node->type != XML_ATTRIBUTE_NODE))
3235 return(NULL);
3236 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3237 return(CONSTSTR(node->ns->prefix));
3238 return(NULL);
3239}
3240
3241/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003242 * xmlTextReaderNamespaceUri:
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
3248 */
3249xmlChar *
3250xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003251 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003252 if ((reader == NULL) || (reader->node == NULL))
3253 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003254 if (reader->curnode != NULL)
3255 node = reader->curnode;
3256 else
3257 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003258 if (node->type == XML_NAMESPACE_DECL)
3259 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003260 if ((node->type != XML_ELEMENT_NODE) &&
3261 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003262 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003263 if (node->ns != NULL)
3264 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003265 return(NULL);
3266}
3267
3268/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003269 * xmlTextReaderConstNamespaceUri:
3270 * @reader: the xmlTextReaderPtr used
3271 *
3272 * The URI defining the namespace associated with the node.
3273 *
3274 * Returns the namespace URI or NULL if not available, the string
3275 * will be deallocated with the reader
3276 */
3277const xmlChar *
3278xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3279 xmlNodePtr node;
3280 if ((reader == NULL) || (reader->node == NULL))
3281 return(NULL);
3282 if (reader->curnode != NULL)
3283 node = reader->curnode;
3284 else
3285 node = reader->node;
3286 if (node->type == XML_NAMESPACE_DECL)
3287 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3288 if ((node->type != XML_ELEMENT_NODE) &&
3289 (node->type != XML_ATTRIBUTE_NODE))
3290 return(NULL);
3291 if (node->ns != NULL)
3292 return(CONSTSTR(node->ns->href));
3293 return(NULL);
3294}
3295
3296/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003297 * xmlTextReaderBaseUri:
3298 * @reader: the xmlTextReaderPtr used
3299 *
3300 * The base URI of the node.
3301 *
3302 * Returns the base URI or NULL if not available
3303 */
3304xmlChar *
3305xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3306 if ((reader == NULL) || (reader->node == NULL))
3307 return(NULL);
3308 return(xmlNodeGetBase(NULL, reader->node));
3309}
3310
3311/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003312 * xmlTextReaderConstBaseUri:
3313 * @reader: the xmlTextReaderPtr used
3314 *
3315 * The base URI of the node.
3316 *
3317 * Returns the base URI or NULL if not available, the string
3318 * will be deallocated with the reader
3319 */
3320const xmlChar *
3321xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3322 xmlChar *tmp;
3323 const xmlChar *ret;
3324
3325 if ((reader == NULL) || (reader->node == NULL))
3326 return(NULL);
3327 tmp = xmlNodeGetBase(NULL, reader->node);
3328 if (tmp == NULL)
3329 return(NULL);
3330 ret = CONSTSTR(tmp);
3331 xmlFree(tmp);
3332 return(ret);
3333}
3334
3335/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003336 * xmlTextReaderDepth:
3337 * @reader: the xmlTextReaderPtr used
3338 *
3339 * The depth of the node in the tree.
3340 *
3341 * Returns the depth or -1 in case of error
3342 */
3343int
3344xmlTextReaderDepth(xmlTextReaderPtr reader) {
3345 if (reader == NULL)
3346 return(-1);
3347 if (reader->node == NULL)
3348 return(0);
3349
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003350 if (reader->curnode != NULL) {
3351 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3352 (reader->curnode->type == XML_NAMESPACE_DECL))
3353 return(reader->depth + 1);
3354 return(reader->depth + 2);
3355 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003356 return(reader->depth);
3357}
3358
3359/**
3360 * xmlTextReaderHasAttributes:
3361 * @reader: the xmlTextReaderPtr used
3362 *
3363 * Whether the node has attributes.
3364 *
3365 * Returns 1 if true, 0 if false, and -1 in case or error
3366 */
3367int
3368xmlTextReaderHasAttributes(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 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003380 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003381 return(1);
3382 /* TODO: handle the xmlDecl */
3383 return(0);
3384}
3385
3386/**
3387 * xmlTextReaderHasValue:
3388 * @reader: the xmlTextReaderPtr used
3389 *
3390 * Whether the node can have a text value.
3391 *
3392 * Returns 1 if true, 0 if false, and -1 in case or error
3393 */
3394int
3395xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003396 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003397 if (reader == NULL)
3398 return(-1);
3399 if (reader->node == NULL)
3400 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003401 if (reader->curnode != NULL)
3402 node = reader->curnode;
3403 else
3404 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003405
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003406 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003407 case XML_ATTRIBUTE_NODE:
3408 case XML_TEXT_NODE:
3409 case XML_CDATA_SECTION_NODE:
3410 case XML_PI_NODE:
3411 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003412 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003413 return(1);
3414 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003415 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003416 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003417 return(0);
3418}
3419
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003420/**
3421 * xmlTextReaderValue:
3422 * @reader: the xmlTextReaderPtr used
3423 *
3424 * Provides the text value of the node if present
3425 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003426 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003427 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003428 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003429xmlChar *
3430xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003431 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003432 if (reader == NULL)
3433 return(NULL);
3434 if (reader->node == NULL)
3435 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003436 if (reader->curnode != NULL)
3437 node = reader->curnode;
3438 else
3439 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003440
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003441 switch (node->type) {
3442 case XML_NAMESPACE_DECL:
3443 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003444 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003445 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003446
3447 if (attr->parent != NULL)
3448 return (xmlNodeListGetString
3449 (attr->parent->doc, attr->children, 1));
3450 else
3451 return (xmlNodeListGetString(NULL, attr->children, 1));
3452 break;
3453 }
3454 case XML_TEXT_NODE:
3455 case XML_CDATA_SECTION_NODE:
3456 case XML_PI_NODE:
3457 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003458 if (node->content != NULL)
3459 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003460 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003461 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003462 }
3463 return(NULL);
3464}
3465
3466/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003467 * xmlTextReaderConstValue:
3468 * @reader: the xmlTextReaderPtr used
3469 *
3470 * Provides the text value of the node if present
3471 *
3472 * Returns the string or NULL if not available. The result will be
3473 * deallocated on the next Read() operation.
3474 */
3475const xmlChar *
3476xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3477 xmlNodePtr node;
3478 if (reader == NULL)
3479 return(NULL);
3480 if (reader->node == NULL)
3481 return(NULL);
3482 if (reader->curnode != NULL)
3483 node = reader->curnode;
3484 else
3485 node = reader->node;
3486
3487 switch (node->type) {
3488 case XML_NAMESPACE_DECL:
3489 return(((xmlNsPtr) node)->href);
3490 case XML_ATTRIBUTE_NODE:{
3491 xmlAttrPtr attr = (xmlAttrPtr) node;
3492
3493 if ((attr->children != NULL) &&
3494 (attr->children->type == XML_TEXT_NODE) &&
3495 (attr->children->next == NULL))
3496 return(attr->children->content);
3497 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003498 if (reader->buffer == NULL)
3499 reader->buffer = xmlBufferCreateSize(100);
3500 if (reader->buffer == NULL) {
3501 xmlGenericError(xmlGenericErrorContext,
3502 "xmlTextReaderSetup : malloc failed\n");
3503 return (NULL);
3504 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003505 reader->buffer->use = 0;
3506 xmlNodeBufGetContent(reader->buffer, node);
3507 return(reader->buffer->content);
3508 }
3509 break;
3510 }
3511 case XML_TEXT_NODE:
3512 case XML_CDATA_SECTION_NODE:
3513 case XML_PI_NODE:
3514 case XML_COMMENT_NODE:
3515 return(node->content);
3516 default:
3517 break;
3518 }
3519 return(NULL);
3520}
3521
3522/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003523 * xmlTextReaderIsDefault:
3524 * @reader: the xmlTextReaderPtr used
3525 *
3526 * Whether an Attribute node was generated from the default value
3527 * defined in the DTD or schema.
3528 *
3529 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3530 */
3531int
3532xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3533 if (reader == NULL)
3534 return(-1);
3535 return(0);
3536}
3537
3538/**
3539 * xmlTextReaderQuoteChar:
3540 * @reader: the xmlTextReaderPtr used
3541 *
3542 * The quotation mark character used to enclose the value of an attribute.
3543 *
3544 * Returns " or ' and -1 in case of error
3545 */
3546int
3547xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3548 if (reader == NULL)
3549 return(-1);
3550 /* TODO maybe lookup the attribute value for " first */
3551 return((int) '"');
3552}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003553
3554/**
3555 * xmlTextReaderXmlLang:
3556 * @reader: the xmlTextReaderPtr used
3557 *
3558 * The xml:lang scope within which the node resides.
3559 *
3560 * Returns the xml:lang value or NULL if none exists.
3561 */
3562xmlChar *
3563xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3564 if (reader == NULL)
3565 return(NULL);
3566 if (reader->node == NULL)
3567 return(NULL);
3568 return(xmlNodeGetLang(reader->node));
3569}
3570
Daniel Veillard67df8092002-12-16 22:04:11 +00003571/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003572 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003573 * @reader: the xmlTextReaderPtr used
3574 *
3575 * The xml:lang scope within which the node resides.
3576 *
3577 * Returns the xml:lang value or NULL if none exists.
3578 */
3579const xmlChar *
3580xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3581 xmlChar *tmp;
3582 const xmlChar *ret;
3583
3584 if (reader == NULL)
3585 return(NULL);
3586 if (reader->node == NULL)
3587 return(NULL);
3588 tmp = xmlNodeGetLang(reader->node);
3589 if (tmp == NULL)
3590 return(NULL);
3591 ret = CONSTSTR(tmp);
3592 xmlFree(tmp);
3593 return(ret);
3594}
3595
3596/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003597 * xmlTextReaderConstString:
3598 * @reader: the xmlTextReaderPtr used
3599 * @str: the string to intern.
3600 *
3601 * Get an interned string from the reader, allows for example to
3602 * speedup string name comparisons
3603 *
3604 * Returns an interned copy of the string or NULL in case of error. The
3605 * string will be deallocated with the reader.
3606 */
3607const xmlChar *
3608xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3609 if (reader == NULL)
3610 return(NULL);
3611 return(CONSTSTR(str));
3612}
3613
3614/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003615 * xmlTextReaderNormalization:
3616 * @reader: the xmlTextReaderPtr used
3617 *
3618 * The value indicating whether to normalize white space and attribute values.
3619 * Since attribute value and end of line normalizations are a MUST in the XML
3620 * specification only the value true is accepted. The broken bahaviour of
3621 * accepting out of range character entities like &#0; is of course not
3622 * supported either.
3623 *
3624 * Returns 1 or -1 in case of error.
3625 */
3626int
3627xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3628 if (reader == NULL)
3629 return(-1);
3630 return(1);
3631}
3632
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003633/************************************************************************
3634 * *
3635 * Extensions to the base APIs *
3636 * *
3637 ************************************************************************/
3638
3639/**
3640 * xmlTextReaderSetParserProp:
3641 * @reader: the xmlTextReaderPtr used
3642 * @prop: the xmlParserProperties to set
3643 * @value: usually 0 or 1 to (de)activate it
3644 *
3645 * Change the parser processing behaviour by changing some of its internal
3646 * properties. Note that some properties can only be changed before any
3647 * read has been done.
3648 *
3649 * Returns 0 if the call was successful, or -1 in case of error
3650 */
3651int
3652xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3653 xmlParserProperties p = (xmlParserProperties) prop;
3654 xmlParserCtxtPtr ctxt;
3655
3656 if ((reader == NULL) || (reader->ctxt == NULL))
3657 return(-1);
3658 ctxt = reader->ctxt;
3659
3660 switch (p) {
3661 case XML_PARSER_LOADDTD:
3662 if (value != 0) {
3663 if (ctxt->loadsubset == 0) {
3664 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3665 return(-1);
3666 ctxt->loadsubset = XML_DETECT_IDS;
3667 }
3668 } else {
3669 ctxt->loadsubset = 0;
3670 }
3671 return(0);
3672 case XML_PARSER_DEFAULTATTRS:
3673 if (value != 0) {
3674 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3675 } else {
3676 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3677 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3678 }
3679 return(0);
3680 case XML_PARSER_VALIDATE:
3681 if (value != 0) {
3682 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003683 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003684 } else {
3685 ctxt->validate = 0;
3686 }
3687 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003688 case XML_PARSER_SUBST_ENTITIES:
3689 if (value != 0) {
3690 ctxt->replaceEntities = 1;
3691 } else {
3692 ctxt->replaceEntities = 0;
3693 }
3694 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003695 }
3696 return(-1);
3697}
3698
3699/**
3700 * xmlTextReaderGetParserProp:
3701 * @reader: the xmlTextReaderPtr used
3702 * @prop: the xmlParserProperties to get
3703 *
3704 * Read the parser internal property.
3705 *
3706 * Returns the value, usually 0 or 1, or -1 in case of error.
3707 */
3708int
3709xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3710 xmlParserProperties p = (xmlParserProperties) prop;
3711 xmlParserCtxtPtr ctxt;
3712
3713 if ((reader == NULL) || (reader->ctxt == NULL))
3714 return(-1);
3715 ctxt = reader->ctxt;
3716
3717 switch (p) {
3718 case XML_PARSER_LOADDTD:
3719 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3720 return(1);
3721 return(0);
3722 case XML_PARSER_DEFAULTATTRS:
3723 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3724 return(1);
3725 return(0);
3726 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003727 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003728 case XML_PARSER_SUBST_ENTITIES:
3729 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003730 }
3731 return(-1);
3732}
3733
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003734
Daniel Veillarde18fc182002-12-28 22:56:33 +00003735/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003736 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003737 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003738 *
3739 * Provide the line number of the current parsing point.
3740 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003741 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003742 */
3743int
3744xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3745{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003746 if ((reader == NULL) || (reader->ctxt == NULL) ||
3747 (reader->ctxt->input == NULL)) {
3748 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003749 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003750 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003751}
3752
3753/**
3754 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003755 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003756 *
3757 * Provide the column number of the current parsing point.
3758 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003759 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003760 */
3761int
3762xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3763{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003764 if ((reader == NULL) || (reader->ctxt == NULL) ||
3765 (reader->ctxt->input == NULL)) {
3766 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003767 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003768 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003769}
3770
3771/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003772 * xmlTextReaderCurrentNode:
3773 * @reader: the xmlTextReaderPtr used
3774 *
3775 * Hacking interface allowing to get the xmlNodePtr correponding to the
3776 * current node being accessed by the xmlTextReader. This is dangerous
3777 * because the underlying node may be destroyed on the next Reads.
3778 *
3779 * Returns the xmlNodePtr or NULL in case of error.
3780 */
3781xmlNodePtr
3782xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3783 if (reader == NULL)
3784 return(NULL);
3785
3786 if (reader->curnode != NULL)
3787 return(reader->curnode);
3788 return(reader->node);
3789}
3790
3791/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003792 * xmlTextReaderPreserve:
3793 * @reader: the xmlTextReaderPtr used
3794 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003795 * This tells the XML Reader to preserve the current node.
3796 * The caller must also use xmlTextReaderCurrentDoc() to
3797 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003798 *
3799 * Returns the xmlNodePtr or NULL in case of error.
3800 */
3801xmlNodePtr
3802xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3803 xmlNodePtr cur, parent;
3804
3805 if (reader == NULL)
3806 return(NULL);
3807
3808 if (reader->curnode != NULL)
3809 cur = reader->curnode;
3810 else
3811 cur = reader->node;
3812 if (cur == NULL)
3813 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003814
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003815 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003816 cur->extra |= NODE_IS_PRESERVED;
3817 cur->extra |= NODE_IS_SPRESERVED;
3818 }
3819 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003820
3821 parent = cur->parent;;
3822 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003823 if (parent->type == XML_ELEMENT_NODE)
3824 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003825 parent = parent->parent;
3826 }
3827 return(cur);
3828}
3829
Daniel Veillard1e906612003-12-05 14:57:46 +00003830#ifdef LIBXML_PATTERN_ENABLED
3831/**
3832 * xmlTextReaderPreservePattern:
3833 * @reader: the xmlTextReaderPtr used
3834 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003835 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003836 *
3837 * This tells the XML Reader to preserve all nodes matched by the
3838 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3839 * keep an handle on the resulting document once parsing has finished
3840 *
3841 * Returns a positive number in case of success and -1 in case of error
3842 */
3843int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003844xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3845 const xmlChar **namespaces)
3846{
Daniel Veillard1e906612003-12-05 14:57:46 +00003847 xmlPatternPtr comp;
3848
3849 if ((reader == NULL) || (pattern == NULL))
3850 return(-1);
3851
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003852 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003853 if (comp == NULL)
3854 return(-1);
3855
3856 if (reader->patternMax <= 0) {
3857 reader->patternMax = 4;
3858 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3859 sizeof(reader->patternTab[0]));
3860 if (reader->patternTab == NULL) {
3861 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3862 return (-1);
3863 }
3864 }
3865 if (reader->patternNr >= reader->patternMax) {
3866 xmlPatternPtr *tmp;
3867 reader->patternMax *= 2;
3868 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3869 reader->patternMax *
3870 sizeof(reader->patternTab[0]));
3871 if (tmp == NULL) {
3872 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3873 reader->patternMax /= 2;
3874 return (-1);
3875 }
3876 reader->patternTab = tmp;
3877 }
3878 reader->patternTab[reader->patternNr] = comp;
3879 return(reader->patternNr++);
3880}
3881#endif
3882
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003883/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003884 * xmlTextReaderCurrentDoc:
3885 * @reader: the xmlTextReaderPtr used
3886 *
3887 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003888 * current document being accessed by the xmlTextReader.
3889 * NOTE: as a result of this call, the reader will not destroy the
3890 * associated XML document and calling xmlFreeDoc() on the result
3891 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003892 *
3893 * Returns the xmlDocPtr or NULL in case of error.
3894 */
3895xmlDocPtr
3896xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003897 if (reader == NULL)
3898 return(NULL);
3899 if (reader->doc != NULL)
3900 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003901 if ((reader == NULL) || (reader->ctxt == NULL) ||
3902 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003903 return(NULL);
3904
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003905 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003906 return(reader->ctxt->myDoc);
3907}
3908
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003909#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003910
3911static char *
3912xmlTextReaderBuildMessage(const char *msg, va_list ap);
3913
Daniel Veillardffa3c742005-07-21 13:24:09 +00003914static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003915xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3916
Daniel Veillardffa3c742005-07-21 13:24:09 +00003917static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003918xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3919
Daniel Veillardffa3c742005-07-21 13:24:09 +00003920static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003921{
3922 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3923 char * str;
3924 va_list ap;
3925
3926 va_start(ap,msg);
3927 str = xmlTextReaderBuildMessage(msg,ap);
3928 if (!reader->errorFunc) {
3929 xmlTextReaderValidityError(ctx, "%s", str);
3930 } else {
3931 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3932 }
3933 if (str != NULL)
3934 xmlFree(str);
3935 va_end(ap);
3936}
3937
Daniel Veillardffa3c742005-07-21 13:24:09 +00003938static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003939{
3940 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3941 char * str;
3942 va_list ap;
3943
3944 va_start(ap,msg);
3945 str = xmlTextReaderBuildMessage(msg,ap);
3946 if (!reader->errorFunc) {
3947 xmlTextReaderValidityWarning(ctx, "%s", str);
3948 } else {
3949 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3950 }
3951 if (str != NULL)
3952 xmlFree(str);
3953 va_end(ap);
3954}
3955
3956static void
3957xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
3958
3959static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
3960{
3961 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
3962
3963 if (reader->sErrorFunc) {
3964 reader->sErrorFunc(reader->errorFuncArg, error);
3965 } else {
3966 xmlTextReaderStructuredError(reader, error);
3967 }
3968}
3969
Daniel Veillardf4e55762003-04-15 23:32:22 +00003970/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003971 * xmlTextReaderRelaxNGSetSchema:
3972 * @reader: the xmlTextReaderPtr used
3973 * @schema: a precompiled RelaxNG schema
3974 *
3975 * Use RelaxNG to validate the document as it is processed.
3976 * Activation is only possible before the first Read().
3977 * if @schema is NULL, then RelaxNG validation is desactivated.
3978 @ The @schema should not be freed until the reader is deallocated
3979 * or its use has been deactivated.
3980 *
3981 * Returns 0 in case the RelaxNG validation could be (des)activated and
3982 * -1 in case of error.
3983 */
3984int
3985xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00003986 if (reader == NULL)
3987 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003988 if (schema == NULL) {
3989 if (reader->rngSchemas != NULL) {
3990 xmlRelaxNGFree(reader->rngSchemas);
3991 reader->rngSchemas = NULL;
3992 }
3993 if (reader->rngValidCtxt != NULL) {
3994 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3995 reader->rngValidCtxt = NULL;
3996 }
3997 return(0);
3998 }
3999 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4000 return(-1);
4001 if (reader->rngSchemas != NULL) {
4002 xmlRelaxNGFree(reader->rngSchemas);
4003 reader->rngSchemas = NULL;
4004 }
4005 if (reader->rngValidCtxt != NULL) {
4006 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4007 reader->rngValidCtxt = NULL;
4008 }
4009 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4010 if (reader->rngValidCtxt == NULL)
4011 return(-1);
4012 if (reader->errorFunc != NULL) {
4013 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004014 xmlTextReaderValidityErrorRelay,
4015 xmlTextReaderValidityWarningRelay,
4016 reader);
4017 }
4018 if (reader->sErrorFunc != NULL) {
4019 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4020 xmlTextReaderValidityStructuredRelay,
4021 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004022 }
4023 reader->rngValidErrors = 0;
4024 reader->rngFullNode = NULL;
4025 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4026 return(0);
4027}
4028
4029/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004030 * xmlTextReaderSetSchema:
4031 * @reader: the xmlTextReaderPtr used
4032 * @schema: a precompiled Schema schema
4033 *
4034 * Use XSD Schema to validate the document as it is processed.
4035 * Activation is only possible before the first Read().
4036 * if @schema is NULL, then Schema validation is desactivated.
4037 @ The @schema should not be freed until the reader is deallocated
4038 * or its use has been deactivated.
4039 *
4040 * Returns 0 in case the Schema validation could be (des)activated and
4041 * -1 in case of error.
4042 */
4043int
4044xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4045 if (reader == NULL)
4046 return(-1);
4047 if (schema == NULL) {
4048 if (reader->xsdPlug != NULL) {
4049 xmlSchemaSAXUnplug(reader->xsdPlug);
4050 reader->xsdPlug = NULL;
4051 }
4052 if (reader->xsdValidCtxt != NULL) {
4053 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4054 reader->xsdValidCtxt = NULL;
4055 }
4056 if (reader->xsdSchemas != NULL) {
4057 xmlSchemaFree(reader->xsdSchemas);
4058 reader->xsdSchemas = NULL;
4059 }
4060 return(0);
4061 }
4062 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4063 return(-1);
4064 if (reader->xsdPlug != NULL) {
4065 xmlSchemaSAXUnplug(reader->xsdPlug);
4066 reader->xsdPlug = NULL;
4067 }
4068 if (reader->xsdValidCtxt != NULL) {
4069 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4070 reader->xsdValidCtxt = NULL;
4071 }
4072 if (reader->xsdSchemas != NULL) {
4073 xmlSchemaFree(reader->xsdSchemas);
4074 reader->xsdSchemas = NULL;
4075 }
4076 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4077 if (reader->xsdValidCtxt == NULL) {
4078 xmlSchemaFree(reader->xsdSchemas);
4079 reader->xsdSchemas = NULL;
4080 return(-1);
4081 }
4082 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4083 &(reader->ctxt->sax),
4084 &(reader->ctxt->userData));
4085 if (reader->xsdPlug == NULL) {
4086 xmlSchemaFree(reader->xsdSchemas);
4087 reader->xsdSchemas = NULL;
4088 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4089 reader->xsdValidCtxt = NULL;
4090 return(-1);
4091 }
4092 if (reader->errorFunc != NULL) {
4093 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004094 xmlTextReaderValidityErrorRelay,
4095 xmlTextReaderValidityWarningRelay,
4096 reader);
4097 }
4098 if (reader->sErrorFunc != NULL) {
4099 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4100 xmlTextReaderValidityStructuredRelay,
4101 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004102 }
4103 reader->xsdValidErrors = 0;
4104 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4105 return(0);
4106}
4107
4108/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004109 * xmlTextReaderRelaxNGValidate:
4110 * @reader: the xmlTextReaderPtr used
4111 * @rng: the path to a RelaxNG schema or NULL
4112 *
4113 * Use RelaxNG to validate the document as it is processed.
4114 * Activation is only possible before the first Read().
4115 * if @rng is NULL, then RelaxNG validation is desactivated.
4116 *
4117 * Returns 0 in case the RelaxNG validation could be (des)activated and
4118 * -1 in case of error.
4119 */
4120int
4121xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4122 xmlRelaxNGParserCtxtPtr ctxt;
4123
4124 if (reader == NULL)
4125 return(-1);
4126
4127 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004128 if (reader->rngValidCtxt != NULL) {
4129 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4130 reader->rngValidCtxt = NULL;
4131 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004132 if (reader->rngSchemas != NULL) {
4133 xmlRelaxNGFree(reader->rngSchemas);
4134 reader->rngSchemas = NULL;
4135 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004136 return(0);
4137 }
4138 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4139 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004140 if (reader->rngSchemas != NULL) {
4141 xmlRelaxNGFree(reader->rngSchemas);
4142 reader->rngSchemas = NULL;
4143 }
4144 if (reader->rngValidCtxt != NULL) {
4145 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4146 reader->rngValidCtxt = NULL;
4147 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004148 ctxt = xmlRelaxNGNewParserCtxt(rng);
4149 if (reader->errorFunc != NULL) {
4150 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004151 xmlTextReaderValidityErrorRelay,
4152 xmlTextReaderValidityWarningRelay,
4153 reader);
4154 }
4155 if (reader->sErrorFunc != NULL) {
4156 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4157 xmlTextReaderValidityStructuredRelay,
4158 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004159 }
4160 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4161 xmlRelaxNGFreeParserCtxt(ctxt);
4162 if (reader->rngSchemas == NULL)
4163 return(-1);
4164 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004165 if (reader->rngValidCtxt == NULL) {
4166 xmlRelaxNGFree(reader->rngSchemas);
4167 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004168 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004169 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004170 if (reader->errorFunc != NULL) {
4171 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004172 xmlTextReaderValidityErrorRelay,
4173 xmlTextReaderValidityWarningRelay,
4174 reader);
4175 }
4176 if (reader->sErrorFunc != NULL) {
4177 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4178 xmlTextReaderValidityStructuredRelay,
4179 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004180 }
4181 reader->rngValidErrors = 0;
4182 reader->rngFullNode = NULL;
4183 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4184 return(0);
4185}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004186
4187/**
4188 * xmlTextReaderSchemaValidate:
4189 * @reader: the xmlTextReaderPtr used
4190 * @xsd: the path to a W3C XSD schema or NULL
4191 *
4192 * Use W3C XSD schema to validate the document as it is processed.
4193 * Activation is only possible before the first Read().
4194 * if @xsd is NULL, then RelaxNG validation is desactivated.
4195 *
4196 * Returns 0 in case the schemas validation could be (des)activated and
4197 * -1 in case of error.
4198 */
4199int
4200xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4201 xmlSchemaParserCtxtPtr ctxt;
4202
4203 if (reader == NULL)
4204 return(-1);
4205
4206 if (xsd == NULL) {
4207 if (reader->xsdPlug != NULL) {
4208 xmlSchemaSAXUnplug(reader->xsdPlug);
4209 reader->xsdPlug = NULL;
4210 }
4211 if (reader->xsdSchemas != NULL) {
4212 xmlSchemaFree(reader->xsdSchemas);
4213 reader->xsdSchemas = NULL;
4214 }
4215 if (reader->xsdValidCtxt != NULL) {
4216 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4217 reader->xsdValidCtxt = NULL;
4218 }
4219 return(0);
4220 }
4221 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4222 (reader->ctxt == NULL))
4223 return(-1);
4224 if (reader->xsdPlug != NULL) {
4225 xmlSchemaSAXUnplug(reader->xsdPlug);
4226 reader->xsdPlug = NULL;
4227 }
4228 if (reader->xsdValidCtxt != NULL) {
4229 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4230 reader->xsdValidCtxt = NULL;
4231 }
4232 if (reader->xsdSchemas != NULL) {
4233 xmlSchemaFree(reader->xsdSchemas);
4234 reader->xsdSchemas = NULL;
4235 }
4236 ctxt = xmlSchemaNewParserCtxt(xsd);
4237 if (reader->errorFunc != NULL) {
4238 xmlSchemaSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004239 xmlTextReaderValidityErrorRelay,
4240 xmlTextReaderValidityWarningRelay,
4241 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004242 }
4243 reader->xsdSchemas = xmlSchemaParse(ctxt);
4244 xmlSchemaFreeParserCtxt(ctxt);
4245 if (reader->xsdSchemas == NULL)
4246 return(-1);
4247 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4248 if (reader->xsdValidCtxt == NULL) {
4249 xmlSchemaFree(reader->xsdSchemas);
4250 reader->xsdSchemas = NULL;
4251 return(-1);
4252 }
4253 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4254 &(reader->ctxt->sax),
4255 &(reader->ctxt->userData));
4256 if (reader->xsdPlug == NULL) {
4257 xmlSchemaFree(reader->xsdSchemas);
4258 reader->xsdSchemas = NULL;
4259 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4260 reader->xsdValidCtxt = NULL;
4261 return(-1);
4262 }
4263 if (reader->errorFunc != NULL) {
4264 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004265 xmlTextReaderValidityErrorRelay,
4266 xmlTextReaderValidityWarningRelay,
4267 reader);
4268 }
4269 if (reader->sErrorFunc != NULL) {
4270 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4271 xmlTextReaderValidityStructuredRelay,
4272 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004273 }
4274 reader->xsdValidErrors = 0;
4275 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4276 return(0);
4277}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004278#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004279
Daniel Veillarde2811272004-10-19 09:04:23 +00004280/**
4281 * xmlTextReaderIsNamespaceDecl:
4282 * @reader: the xmlTextReaderPtr used
4283 *
4284 * Determine whether the current node is a namespace declaration
4285 * rather than a regular attribute.
4286 *
4287 * Returns 1 if the current node is a namespace declaration, 0 if it
4288 * is a regular attribute or other type of node, or -1 in case of
4289 * error.
4290 */
4291int
4292xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4293 xmlNodePtr node;
4294 if (reader == NULL)
4295 return(-1);
4296 if (reader->node == NULL)
4297 return(-1);
4298 if (reader->curnode != NULL)
4299 node = reader->curnode;
4300 else
4301 node = reader->node;
4302
4303 if (XML_NAMESPACE_DECL == node->type)
4304 return(1);
4305 else
4306 return(0);
4307}
4308
4309/**
4310 * xmlTextReaderConstXmlVersion:
4311 * @reader: the xmlTextReaderPtr used
4312 *
4313 * Determine the XML version of the document being read.
4314 *
4315 * Returns a string containing the XML version of the document or NULL
4316 * in case of error. The string is deallocated with the reader.
4317 */
4318const xmlChar *
4319xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4320 xmlDocPtr doc = NULL;
4321 if (reader == NULL)
4322 return(NULL);
4323 if (reader->doc != NULL)
4324 doc = reader->doc;
4325 else if (reader->ctxt != NULL)
4326 doc = reader->ctxt->myDoc;
4327 if (doc == NULL)
4328 return(NULL);
4329
4330 if (doc->version == NULL)
4331 return(NULL);
4332 else
4333 return(CONSTSTR(doc->version));
4334}
4335
4336/**
4337 * xmlTextReaderStandalone:
4338 * @reader: the xmlTextReaderPtr used
4339 *
4340 * Determine the standalone status of the document being read.
4341 *
4342 * Returns 1 if the document was declared to be standalone, 0 if it
4343 * was declared to be not standalone, or -1 if the document did not
4344 * specify its standalone status or in case of error.
4345 */
4346int
4347xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4348 xmlDocPtr doc = NULL;
4349 if (reader == NULL)
4350 return(-1);
4351 if (reader->doc != NULL)
4352 doc = reader->doc;
4353 else if (reader->ctxt != NULL)
4354 doc = reader->ctxt->myDoc;
4355 if (doc == NULL)
4356 return(-1);
4357
4358 return(doc->standalone);
4359}
4360
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004361/************************************************************************
4362 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004363 * Error Handling Extensions *
4364 * *
4365 ************************************************************************/
4366
4367/* helper to build a xmlMalloc'ed string from a format and va_list */
4368static char *
4369xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4370 int size;
4371 int chars;
4372 char *larger;
4373 char *str;
4374
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004375 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004376 if (str == NULL) {
4377 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4378 return NULL;
4379 }
4380
4381 size = 150;
4382
4383 while (1) {
4384 chars = vsnprintf(str, size, msg, ap);
4385 if ((chars > -1) && (chars < size))
4386 break;
4387 if (chars > -1)
4388 size += chars + 1;
4389 else
4390 size += 100;
4391 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4392 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4393 xmlFree(str);
4394 return NULL;
4395 }
4396 str = larger;
4397 }
4398
4399 return str;
4400}
4401
Daniel Veillard417be3a2003-01-20 21:26:34 +00004402/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004403 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004404 * @locator: the xmlTextReaderLocatorPtr used
4405 *
4406 * Obtain the line number for the given locator.
4407 *
4408 * Returns the line number or -1 in case of error.
4409 */
4410int
4411xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4412 /* we know that locator is a xmlParserCtxtPtr */
4413 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4414 int ret = -1;
4415
Daniel Veillardce682bc2004-11-05 17:22:25 +00004416 if (locator == NULL)
4417 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004418 if (ctx->node != NULL) {
4419 ret = xmlGetLineNo(ctx->node);
4420 }
4421 else {
4422 /* inspired from error.c */
4423 xmlParserInputPtr input;
4424 input = ctx->input;
4425 if ((input->filename == NULL) && (ctx->inputNr > 1))
4426 input = ctx->inputTab[ctx->inputNr - 2];
4427 if (input != NULL) {
4428 ret = input->line;
4429 }
4430 else {
4431 ret = -1;
4432 }
4433 }
4434
4435 return ret;
4436}
4437
4438/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004439 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004440 * @locator: the xmlTextReaderLocatorPtr used
4441 *
4442 * Obtain the base URI for the given locator.
4443 *
4444 * Returns the base URI or NULL in case of error.
4445 */
4446xmlChar *
4447xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4448 /* we know that locator is a xmlParserCtxtPtr */
4449 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4450 xmlChar *ret = NULL;
4451
Daniel Veillardce682bc2004-11-05 17:22:25 +00004452 if (locator == NULL)
4453 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004454 if (ctx->node != NULL) {
4455 ret = xmlNodeGetBase(NULL,ctx->node);
4456 }
4457 else {
4458 /* inspired from error.c */
4459 xmlParserInputPtr input;
4460 input = ctx->input;
4461 if ((input->filename == NULL) && (ctx->inputNr > 1))
4462 input = ctx->inputTab[ctx->inputNr - 2];
4463 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004464 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004465 }
4466 else {
4467 ret = NULL;
4468 }
4469 }
4470
4471 return ret;
4472}
4473
Daniel Veillard26f70262003-01-16 22:45:08 +00004474static void
William M. Brack899e64a2003-09-26 18:03:42 +00004475xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004476 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4477 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4478
William M. Bracka3215c72004-07-31 16:24:01 +00004479 if (str != NULL) {
4480 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004481 reader->errorFunc(reader->errorFuncArg,
4482 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004483 severity,
4484 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004485 xmlFree(str);
4486 }
4487}
4488
4489static void
William M. Brack93d004f2004-02-03 00:14:10 +00004490xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4491 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4492 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4493
4494 if (error && reader->sErrorFunc) {
4495 reader->sErrorFunc(reader->errorFuncArg,
4496 (xmlErrorPtr) error);
4497 }
4498}
4499
Daniel Veillardffa3c742005-07-21 13:24:09 +00004500static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004501xmlTextReaderError(void *ctxt, const char *msg, ...) {
4502 va_list ap;
4503
4504 va_start(ap,msg);
4505 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004506 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004507 xmlTextReaderBuildMessage(msg,ap));
4508 va_end(ap);
4509
4510}
4511
Daniel Veillardffa3c742005-07-21 13:24:09 +00004512static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004513xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4514 va_list ap;
4515
4516 va_start(ap,msg);
4517 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004518 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004519 xmlTextReaderBuildMessage(msg,ap));
4520 va_end(ap);
4521}
4522
Daniel Veillardffa3c742005-07-21 13:24:09 +00004523static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004524xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4525 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004526 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004527
Daniel Veillard417be3a2003-01-20 21:26:34 +00004528 if ((len > 1) && (msg[len - 2] != ':')) {
4529 /*
4530 * some callbacks only report locator information:
4531 * skip them (mimicking behaviour in error.c)
4532 */
4533 va_start(ap,msg);
4534 xmlTextReaderGenericError(ctxt,
4535 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4536 xmlTextReaderBuildMessage(msg,ap));
4537 va_end(ap);
4538 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004539}
4540
Daniel Veillardffa3c742005-07-21 13:24:09 +00004541static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004542xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4543 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004544 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004545
Daniel Veillard417be3a2003-01-20 21:26:34 +00004546 if ((len != 0) && (msg[len - 1] != ':')) {
4547 /*
4548 * some callbacks only report locator information:
4549 * skip them (mimicking behaviour in error.c)
4550 */
4551 va_start(ap,msg);
4552 xmlTextReaderGenericError(ctxt,
4553 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4554 xmlTextReaderBuildMessage(msg,ap));
4555 va_end(ap);
4556 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004557}
4558
4559/**
4560 * xmlTextReaderSetErrorHandler:
4561 * @reader: the xmlTextReaderPtr used
4562 * @f: the callback function to call on error and warnings
4563 * @arg: a user argument to pass to the callback function
4564 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004565 * Register a callback function that will be called on error and warnings.
4566 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004567 * If @f is NULL, the default error and warning handlers are restored.
4568 */
4569void
4570xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4571 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004572 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004573 if (f != NULL) {
4574 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004575 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004576 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4577 reader->ctxt->sax->warning = xmlTextReaderWarning;
4578 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4579 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004580 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004581 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004582#ifdef LIBXML_SCHEMAS_ENABLED
4583 if (reader->rngValidCtxt) {
4584 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4585 xmlTextReaderValidityErrorRelay,
4586 xmlTextReaderValidityWarningRelay,
4587 reader);
4588 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4589 }
4590 if (reader->xsdValidCtxt) {
4591 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4592 xmlTextReaderValidityErrorRelay,
4593 xmlTextReaderValidityWarningRelay,
4594 reader);
4595 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4596 }
4597#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004598 }
4599 else {
4600 /* restore defaults */
4601 reader->ctxt->sax->error = xmlParserError;
4602 reader->ctxt->vctxt.error = xmlParserValidityError;
4603 reader->ctxt->sax->warning = xmlParserWarning;
4604 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4605 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004606 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004607 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004608#ifdef LIBXML_SCHEMAS_ENABLED
4609 if (reader->rngValidCtxt) {
4610 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4611 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4612 }
4613 if (reader->xsdValidCtxt) {
4614 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4615 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4616 }
4617#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004618 }
4619}
4620
Daniel Veillard417be3a2003-01-20 21:26:34 +00004621/**
William M. Brack93d004f2004-02-03 00:14:10 +00004622* xmlTextReaderSetStructuredErrorHandler:
4623 * @reader: the xmlTextReaderPtr used
4624 * @f: the callback function to call on error and warnings
4625 * @arg: a user argument to pass to the callback function
4626 *
4627 * Register a callback function that will be called on error and warnings.
4628 *
4629 * If @f is NULL, the default error and warning handlers are restored.
4630 */
4631void
4632xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4633 xmlStructuredErrorFunc f,
4634 void *arg) {
4635 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004636 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004637 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4638 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4639 reader->ctxt->sax->warning = xmlTextReaderWarning;
4640 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4641 reader->sErrorFunc = f;
4642 reader->errorFunc = NULL;
4643 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004644#ifdef LIBXML_SCHEMAS_ENABLED
4645 if (reader->rngValidCtxt) {
4646 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4647 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4648 xmlTextReaderValidityStructuredRelay,
4649 reader);
4650 }
4651 if (reader->xsdValidCtxt) {
4652 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4653 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4654 xmlTextReaderValidityStructuredRelay,
4655 reader);
4656 }
4657#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004658 }
4659 else {
4660 /* restore defaults */
4661 reader->ctxt->sax->error = xmlParserError;
4662 reader->ctxt->sax->serror = NULL;
4663 reader->ctxt->vctxt.error = xmlParserValidityError;
4664 reader->ctxt->sax->warning = xmlParserWarning;
4665 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4666 reader->errorFunc = NULL;
4667 reader->sErrorFunc = NULL;
4668 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004669#ifdef LIBXML_SCHEMAS_ENABLED
4670 if (reader->rngValidCtxt) {
4671 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4672 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4673 }
4674 if (reader->xsdValidCtxt) {
4675 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4676 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4677 }
4678#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004679 }
4680}
4681
4682/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004683 * xmlTextReaderIsValid:
4684 * @reader: the xmlTextReaderPtr used
4685 *
4686 * Retrieve the validity status from the parser context
4687 *
4688 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4689 */
4690int
4691xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004692 if (reader == NULL) return(-1);
4693#ifdef LIBXML_SCHEMAS_ENABLED
4694 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4695 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004696 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4697 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004698#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004699 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004700 return(reader->ctxt->valid);
4701 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004702}
4703
4704/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004705 * xmlTextReaderGetErrorHandler:
4706 * @reader: the xmlTextReaderPtr used
4707 * @f: the callback function or NULL is no callback has been registered
4708 * @arg: a user argument
4709 *
4710 * Retrieve the error callback function and user argument.
4711 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004712void
4713xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4714 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004715 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004716 if (f != NULL) *f = reader->errorFunc;
4717 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004718}
4719
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004720
4721/************************************************************************
4722 * *
4723 * New set (2.6.0) of simpler and more flexible APIs *
4724 * *
4725 ************************************************************************/
4726
4727/**
4728 * xmlTextReaderSetup:
4729 * @reader: an XML reader
4730 * @URL: the base URL to use for the document
4731 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004732 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004733 * @reuse: keep the context for reuse
4734 *
4735 * Setup an XML reader with new options
4736 *
4737 * Returns 0 in case of success and -1 in case of error.
4738 */
4739static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004740xmlTextReaderSetup(xmlTextReaderPtr reader,
4741 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004742 const char *encoding, int options)
4743{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004744 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004745 return (-1);
4746
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004747 reader->doc = NULL;
4748 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004749 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004750 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004751 if ((input != NULL) && (reader->input != NULL) &&
4752 (reader->allocs & XML_TEXTREADER_INPUT)) {
4753 xmlFreeParserInputBuffer(reader->input);
4754 reader->input = NULL;
4755 reader->allocs -= XML_TEXTREADER_INPUT;
4756 }
4757 if (input != NULL) {
4758 reader->input = input;
4759 reader->allocs |= XML_TEXTREADER_INPUT;
4760 }
4761 if (reader->buffer == NULL)
4762 reader->buffer = xmlBufferCreateSize(100);
4763 if (reader->buffer == NULL) {
4764 xmlGenericError(xmlGenericErrorContext,
4765 "xmlTextReaderSetup : malloc failed\n");
4766 return (-1);
4767 }
4768 if (reader->sax == NULL)
4769 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4770 if (reader->sax == NULL) {
4771 xmlGenericError(xmlGenericErrorContext,
4772 "xmlTextReaderSetup : malloc failed\n");
4773 return (-1);
4774 }
4775 xmlSAXVersion(reader->sax, 2);
4776 reader->startElement = reader->sax->startElement;
4777 reader->sax->startElement = xmlTextReaderStartElement;
4778 reader->endElement = reader->sax->endElement;
4779 reader->sax->endElement = xmlTextReaderEndElement;
4780#ifdef LIBXML_SAX1_ENABLED
4781 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4782#endif /* LIBXML_SAX1_ENABLED */
4783 reader->startElementNs = reader->sax->startElementNs;
4784 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4785 reader->endElementNs = reader->sax->endElementNs;
4786 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4787#ifdef LIBXML_SAX1_ENABLED
4788 } else {
4789 reader->startElementNs = NULL;
4790 reader->endElementNs = NULL;
4791 }
4792#endif /* LIBXML_SAX1_ENABLED */
4793 reader->characters = reader->sax->characters;
4794 reader->sax->characters = xmlTextReaderCharacters;
4795 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4796 reader->cdataBlock = reader->sax->cdataBlock;
4797 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4798
4799 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4800 reader->node = NULL;
4801 reader->curnode = NULL;
4802 if (input != NULL) {
4803 if (reader->input->buffer->use < 4) {
4804 xmlParserInputBufferRead(input, 4);
4805 }
4806 if (reader->ctxt == NULL) {
4807 if (reader->input->buffer->use >= 4) {
4808 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4809 (const char *) reader->input->buffer->content, 4, URL);
4810 reader->base = 0;
4811 reader->cur = 4;
4812 } else {
4813 reader->ctxt =
4814 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4815 reader->base = 0;
4816 reader->cur = 0;
4817 }
4818 } else {
4819 xmlParserInputPtr inputStream;
4820 xmlParserInputBufferPtr buf;
4821 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4822
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004823 xmlCtxtReset(reader->ctxt);
4824 buf = xmlAllocParserInputBuffer(enc);
4825 if (buf == NULL) return(-1);
4826 inputStream = xmlNewInputStream(reader->ctxt);
4827 if (inputStream == NULL) {
4828 xmlFreeParserInputBuffer(buf);
4829 return(-1);
4830 }
4831
4832 if (URL == NULL)
4833 inputStream->filename = NULL;
4834 else
4835 inputStream->filename = (char *)
4836 xmlCanonicPath((const xmlChar *) URL);
4837 inputStream->buf = buf;
4838 inputStream->base = inputStream->buf->buffer->content;
4839 inputStream->cur = inputStream->buf->buffer->content;
4840 inputStream->end =
4841 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4842
4843 inputPush(reader->ctxt, inputStream);
4844 reader->cur = 0;
4845 }
4846 if (reader->ctxt == NULL) {
4847 xmlGenericError(xmlGenericErrorContext,
4848 "xmlTextReaderSetup : malloc failed\n");
4849 return (-1);
4850 }
4851 }
4852 if (reader->dict != NULL) {
4853 if (reader->ctxt->dict != NULL) {
4854 if (reader->dict != reader->ctxt->dict) {
4855 xmlDictFree(reader->dict);
4856 reader->dict = reader->ctxt->dict;
4857 }
4858 } else {
4859 reader->ctxt->dict = reader->dict;
4860 }
4861 } else {
4862 if (reader->ctxt->dict == NULL)
4863 reader->ctxt->dict = xmlDictCreate();
4864 reader->dict = reader->ctxt->dict;
4865 }
4866 reader->ctxt->_private = reader;
4867 reader->ctxt->linenumbers = 1;
4868 reader->ctxt->dictNames = 1;
4869 /*
4870 * use the parser dictionnary to allocate all elements and attributes names
4871 */
4872 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004873 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004874
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004875#ifdef LIBXML_XINCLUDE_ENABLED
4876 if (reader->xincctxt != NULL) {
4877 xmlXIncludeFreeContext(reader->xincctxt);
4878 reader->xincctxt = NULL;
4879 }
4880 if (options & XML_PARSE_XINCLUDE) {
4881 reader->xinclude = 1;
4882 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4883 options -= XML_PARSE_XINCLUDE;
4884 } else
4885 reader->xinclude = 0;
4886 reader->in_xinclude = 0;
4887#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004888#ifdef LIBXML_PATTERN_ENABLED
4889 if (reader->patternTab == NULL) {
4890 reader->patternNr = 0;
4891 reader->patternMax = 0;
4892 }
4893 while (reader->patternNr > 0) {
4894 reader->patternNr--;
4895 if (reader->patternTab[reader->patternNr] != NULL) {
4896 xmlFreePattern(reader->patternTab[reader->patternNr]);
4897 reader->patternTab[reader->patternNr] = NULL;
4898 }
4899 }
4900#endif
4901
Daniel Veillardc36965d2003-12-02 10:28:48 +00004902 if (options & XML_PARSE_DTDVALID)
4903 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4904
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004905 xmlCtxtUseOptions(reader->ctxt, options);
4906 if (encoding != NULL) {
4907 xmlCharEncodingHandlerPtr hdlr;
4908
4909 hdlr = xmlFindCharEncodingHandler(encoding);
4910 if (hdlr != NULL)
4911 xmlSwitchToEncoding(reader->ctxt, hdlr);
4912 }
4913 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4914 (reader->ctxt->input->filename == NULL))
4915 reader->ctxt->input->filename = (char *)
4916 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004917
4918 reader->doc = NULL;
4919
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004920 return (0);
4921}
4922
4923/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004924 * xmlTextReaderByteConsumed:
4925 * @reader: an XML reader
4926 *
4927 * This function provides the current index of the parser used
4928 * by the reader, relative to the start of the current entity.
4929 * This function actually just wraps a call to xmlBytesConsumed()
4930 * for the parser context associated with the reader.
4931 * See xmlBytesConsumed() for more information.
4932 *
4933 * Returns the index in bytes from the beginning of the entity or -1
4934 * in case the index could not be computed.
4935 */
4936long
4937xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4938 if ((reader == NULL) || (reader->ctxt == NULL))
4939 return(-1);
4940 return(xmlByteConsumed(reader->ctxt));
4941}
4942
4943
4944/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004945 * xmlReaderWalker:
4946 * @doc: a preparsed document
4947 *
4948 * Create an xmltextReader for a preparsed document.
4949 *
4950 * Returns the new reader or NULL in case of error.
4951 */
4952xmlTextReaderPtr
4953xmlReaderWalker(xmlDocPtr doc)
4954{
4955 xmlTextReaderPtr ret;
4956
4957 if (doc == NULL)
4958 return(NULL);
4959
4960 ret = xmlMalloc(sizeof(xmlTextReader));
4961 if (ret == NULL) {
4962 xmlGenericError(xmlGenericErrorContext,
4963 "xmlNewTextReader : malloc failed\n");
4964 return(NULL);
4965 }
4966 memset(ret, 0, sizeof(xmlTextReader));
4967 ret->entNr = 0;
4968 ret->input = NULL;
4969 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4970 ret->node = NULL;
4971 ret->curnode = NULL;
4972 ret->base = 0;
4973 ret->cur = 0;
4974 ret->allocs = XML_TEXTREADER_CTXT;
4975 ret->doc = doc;
4976 ret->state = XML_TEXTREADER_START;
4977 ret->dict = xmlDictCreate();
4978 return(ret);
4979}
4980
4981/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004982 * xmlReaderForDoc:
4983 * @cur: a pointer to a zero terminated string
4984 * @URL: the base URL to use for the document
4985 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004986 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004987 *
4988 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004989 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004990 *
4991 * Returns the new reader or NULL in case of error.
4992 */
4993xmlTextReaderPtr
4994xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4995 int options)
4996{
4997 int len;
4998
4999 if (cur == NULL)
5000 return (NULL);
5001 len = xmlStrlen(cur);
5002
5003 return (xmlReaderForMemory
5004 ((const char *) cur, len, URL, encoding, options));
5005}
5006
5007/**
5008 * xmlReaderForFile:
5009 * @filename: a file or URL
5010 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005011 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005012 *
5013 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005014 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005015 *
5016 * Returns the new reader or NULL in case of error.
5017 */
5018xmlTextReaderPtr
5019xmlReaderForFile(const char *filename, const char *encoding, int options)
5020{
5021 xmlTextReaderPtr reader;
5022
5023 reader = xmlNewTextReaderFilename(filename);
5024 if (reader == NULL)
5025 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005026 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005027 return (reader);
5028}
5029
5030/**
5031 * xmlReaderForMemory:
5032 * @buffer: a pointer to a char array
5033 * @size: the size of the array
5034 * @URL: the base URL to use for the document
5035 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005036 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005037 *
5038 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005039 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005040 *
5041 * Returns the new reader or NULL in case of error.
5042 */
5043xmlTextReaderPtr
5044xmlReaderForMemory(const char *buffer, int size, const char *URL,
5045 const char *encoding, int options)
5046{
5047 xmlTextReaderPtr reader;
5048 xmlParserInputBufferPtr buf;
5049
Daniel Veillard21924522004-02-19 16:37:07 +00005050 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005051 XML_CHAR_ENCODING_NONE);
5052 if (buf == NULL) {
5053 return (NULL);
5054 }
5055 reader = xmlNewTextReader(buf, URL);
5056 if (reader == NULL) {
5057 xmlFreeParserInputBuffer(buf);
5058 return (NULL);
5059 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005060 reader->allocs |= XML_TEXTREADER_INPUT;
5061 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005062 return (reader);
5063}
5064
5065/**
5066 * xmlReaderForFd:
5067 * @fd: an open file descriptor
5068 * @URL: the base URL to use for the document
5069 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005070 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005071 *
5072 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005073 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005074 * NOTE that the file descriptor will not be closed when the
5075 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005076 *
5077 * Returns the new reader or NULL in case of error.
5078 */
5079xmlTextReaderPtr
5080xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5081{
5082 xmlTextReaderPtr reader;
5083 xmlParserInputBufferPtr input;
5084
5085 if (fd < 0)
5086 return (NULL);
5087
5088 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5089 if (input == NULL)
5090 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005091 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005092 reader = xmlNewTextReader(input, URL);
5093 if (reader == NULL) {
5094 xmlFreeParserInputBuffer(input);
5095 return (NULL);
5096 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005097 reader->allocs |= XML_TEXTREADER_INPUT;
5098 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005099 return (reader);
5100}
5101
5102/**
5103 * xmlReaderForIO:
5104 * @ioread: an I/O read function
5105 * @ioclose: an I/O close function
5106 * @ioctx: an I/O handler
5107 * @URL: the base URL to use for the document
5108 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005109 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005110 *
5111 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005112 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005113 *
5114 * Returns the new reader or NULL in case of error.
5115 */
5116xmlTextReaderPtr
5117xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5118 void *ioctx, const char *URL, const char *encoding,
5119 int options)
5120{
5121 xmlTextReaderPtr reader;
5122 xmlParserInputBufferPtr input;
5123
5124 if (ioread == NULL)
5125 return (NULL);
5126
5127 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5128 XML_CHAR_ENCODING_NONE);
5129 if (input == NULL)
5130 return (NULL);
5131 reader = xmlNewTextReader(input, URL);
5132 if (reader == NULL) {
5133 xmlFreeParserInputBuffer(input);
5134 return (NULL);
5135 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005136 reader->allocs |= XML_TEXTREADER_INPUT;
5137 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005138 return (reader);
5139}
5140
5141/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005142 * xmlReaderNewWalker:
5143 * @reader: an XML reader
5144 * @doc: a preparsed document
5145 *
5146 * Setup an xmltextReader to parse a preparsed XML document.
5147 * This reuses the existing @reader xmlTextReader.
5148 *
5149 * Returns 0 in case of success and -1 in case of error
5150 */
5151int
5152xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5153{
5154 if (doc == NULL)
5155 return (-1);
5156 if (reader == NULL)
5157 return (-1);
5158
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005159 if (reader->input != NULL) {
5160 xmlFreeParserInputBuffer(reader->input);
5161 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005162 if (reader->ctxt != NULL) {
5163 xmlCtxtReset(reader->ctxt);
5164 }
5165
5166 reader->entNr = 0;
5167 reader->input = NULL;
5168 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5169 reader->node = NULL;
5170 reader->curnode = NULL;
5171 reader->base = 0;
5172 reader->cur = 0;
5173 reader->allocs = XML_TEXTREADER_CTXT;
5174 reader->doc = doc;
5175 reader->state = XML_TEXTREADER_START;
5176 if (reader->dict == NULL) {
5177 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5178 reader->dict = reader->ctxt->dict;
5179 else
5180 reader->dict = xmlDictCreate();
5181 }
5182 return(0);
5183}
5184
5185/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005186 * xmlReaderNewDoc:
5187 * @reader: an XML reader
5188 * @cur: a pointer to a zero terminated string
5189 * @URL: the base URL to use for the document
5190 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005191 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005192 *
5193 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005194 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005195 * This reuses the existing @reader xmlTextReader.
5196 *
5197 * Returns 0 in case of success and -1 in case of error
5198 */
5199int
5200xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5201 const char *URL, const char *encoding, int options)
5202{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005203
5204 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005205
5206 if (cur == NULL)
5207 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005208 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005209 return (-1);
5210
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005211 len = xmlStrlen(cur);
5212 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5213 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005214}
5215
5216/**
5217 * xmlReaderNewFile:
5218 * @reader: an XML reader
5219 * @filename: a file or URL
5220 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005221 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005222 *
5223 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005224 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005225 * This reuses the existing @reader xmlTextReader.
5226 *
5227 * Returns 0 in case of success and -1 in case of error
5228 */
5229int
5230xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5231 const char *encoding, int options)
5232{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005233 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005234
5235 if (filename == NULL)
5236 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005237 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005238 return (-1);
5239
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005240 input =
5241 xmlParserInputBufferCreateFilename(filename,
5242 XML_CHAR_ENCODING_NONE);
5243 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005244 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005245 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005246}
5247
5248/**
5249 * xmlReaderNewMemory:
5250 * @reader: an XML reader
5251 * @buffer: a pointer to a char array
5252 * @size: the size of the array
5253 * @URL: the base URL to use for the document
5254 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005255 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005256 *
5257 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005258 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005259 * This reuses the existing @reader xmlTextReader.
5260 *
5261 * Returns 0 in case of success and -1 in case of error
5262 */
5263int
5264xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5265 const char *URL, const char *encoding, int options)
5266{
5267 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005268
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005269 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005270 return (-1);
5271 if (buffer == NULL)
5272 return (-1);
5273
Daniel Veillard21924522004-02-19 16:37:07 +00005274 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005275 XML_CHAR_ENCODING_NONE);
5276 if (input == NULL) {
5277 return (-1);
5278 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005279 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005280}
5281
5282/**
5283 * xmlReaderNewFd:
5284 * @reader: an XML reader
5285 * @fd: an open file descriptor
5286 * @URL: the base URL to use for the document
5287 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005288 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005289 *
5290 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005291 * NOTE that the file descriptor will not be closed when the
5292 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005293 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005294 * This reuses the existing @reader xmlTextReader.
5295 *
5296 * Returns 0 in case of success and -1 in case of error
5297 */
5298int
5299xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5300 const char *URL, const char *encoding, int options)
5301{
5302 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005303
5304 if (fd < 0)
5305 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005306 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005307 return (-1);
5308
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005309 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5310 if (input == NULL)
5311 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005312 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005313 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005314}
5315
5316/**
5317 * xmlReaderNewIO:
5318 * @reader: an XML reader
5319 * @ioread: an I/O read function
5320 * @ioclose: an I/O close function
5321 * @ioctx: an I/O handler
5322 * @URL: the base URL to use for the document
5323 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005324 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005325 *
5326 * Setup an xmltextReader to parse an XML document from I/O functions
5327 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005328 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005329 * This reuses the existing @reader xmlTextReader.
5330 *
5331 * Returns 0 in case of success and -1 in case of error
5332 */
5333int
5334xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5335 xmlInputCloseCallback ioclose, void *ioctx,
5336 const char *URL, const char *encoding, int options)
5337{
5338 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005339
5340 if (ioread == NULL)
5341 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005342 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005343 return (-1);
5344
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005345 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5346 XML_CHAR_ENCODING_NONE);
5347 if (input == NULL)
5348 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005349 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005350}
Daniel Veillard26f70262003-01-16 22:45:08 +00005351/************************************************************************
5352 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005353 * Utilities *
5354 * *
5355 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005356#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005357/**
5358 * xmlBase64Decode:
5359 * @in: the input buffer
5360 * @inlen: the size of the input (in), the size read from it (out)
5361 * @to: the output buffer
5362 * @tolen: the size of the output (in), the size written to (out)
5363 *
5364 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005365 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005366 *
5367 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5368 * 2 if there wasn't enough space on the output or -1 in case of error.
5369 */
5370static int
5371xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5372 unsigned char *to, unsigned long *tolen) {
5373 unsigned long incur; /* current index in in[] */
5374 unsigned long inblk; /* last block index in in[] */
5375 unsigned long outcur; /* current index in out[] */
5376 unsigned long inmax; /* size of in[] */
5377 unsigned long outmax; /* size of out[] */
5378 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005379 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005380 int nbintmp; /* number of byte in intmp[] */
5381 int is_ignore; /* cur should be ignored */
5382 int is_end = 0; /* the end of the base64 was found */
5383 int retval = 1;
5384 int i;
5385
5386 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5387 return(-1);
5388
5389 incur = 0;
5390 inblk = 0;
5391 outcur = 0;
5392 inmax = *inlen;
5393 outmax = *tolen;
5394 nbintmp = 0;
5395
5396 while (1) {
5397 if (incur >= inmax)
5398 break;
5399 cur = in[incur++];
5400 is_ignore = 0;
5401 if ((cur >= 'A') && (cur <= 'Z'))
5402 cur = cur - 'A';
5403 else if ((cur >= 'a') && (cur <= 'z'))
5404 cur = cur - 'a' + 26;
5405 else if ((cur >= '0') && (cur <= '9'))
5406 cur = cur - '0' + 52;
5407 else if (cur == '+')
5408 cur = 62;
5409 else if (cur == '/')
5410 cur = 63;
5411 else if (cur == '.')
5412 cur = 0;
5413 else if (cur == '=') /*no op , end of the base64 stream */
5414 is_end = 1;
5415 else {
5416 is_ignore = 1;
5417 if (nbintmp == 0)
5418 inblk = incur;
5419 }
5420
5421 if (!is_ignore) {
5422 int nbouttmp = 3;
5423 int is_break = 0;
5424
5425 if (is_end) {
5426 if (nbintmp == 0)
5427 break;
5428 if ((nbintmp == 1) || (nbintmp == 2))
5429 nbouttmp = 1;
5430 else
5431 nbouttmp = 2;
5432 nbintmp = 3;
5433 is_break = 1;
5434 }
5435 intmp[nbintmp++] = cur;
5436 /*
5437 * if intmp is full, push the 4byte sequence as a 3 byte
5438 * sequence out
5439 */
5440 if (nbintmp == 4) {
5441 nbintmp = 0;
5442 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5443 outtmp[1] =
5444 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5445 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5446 if (outcur + 3 >= outmax) {
5447 retval = 2;
5448 break;
5449 }
5450
5451 for (i = 0; i < nbouttmp; i++)
5452 to[outcur++] = outtmp[i];
5453 inblk = incur;
5454 }
5455
5456 if (is_break) {
5457 retval = 0;
5458 break;
5459 }
5460 }
5461 }
5462
5463 *tolen = outcur;
5464 *inlen = inblk;
5465 return (retval);
5466}
5467
5468/*
5469 * Test routine for the xmlBase64Decode function
5470 */
5471#if 0
5472int main(int argc, char **argv) {
5473 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5474 char output[100];
5475 char output2[100];
5476 char output3[100];
5477 unsigned long inlen = strlen(input);
5478 unsigned long outlen = 100;
5479 int ret;
5480 unsigned long cons, tmp, tmp2, prod;
5481
5482 /*
5483 * Direct
5484 */
5485 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5486
5487 output[outlen] = 0;
5488 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5489
5490 /*
5491 * output chunking
5492 */
5493 cons = 0;
5494 prod = 0;
5495 while (cons < inlen) {
5496 tmp = 5;
5497 tmp2 = inlen - cons;
5498
5499 printf("%ld %ld\n", cons, prod);
5500 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5501 cons += tmp2;
5502 prod += tmp;
5503 printf("%ld %ld\n", cons, prod);
5504 }
5505 output2[outlen] = 0;
5506 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5507
5508 /*
5509 * input chunking
5510 */
5511 cons = 0;
5512 prod = 0;
5513 while (cons < inlen) {
5514 tmp = 100 - prod;
5515 tmp2 = inlen - cons;
5516 if (tmp2 > 5)
5517 tmp2 = 5;
5518
5519 printf("%ld %ld\n", cons, prod);
5520 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5521 cons += tmp2;
5522 prod += tmp;
5523 printf("%ld %ld\n", cons, prod);
5524 }
5525 output3[outlen] = 0;
5526 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5527 return(0);
5528
5529}
5530#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005531#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005532#define bottom_xmlreader
5533#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005534#endif /* LIBXML_READER_ENABLED */