blob: e0138a75d4694d037abaf92adf225bf14883007c [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard067bae52003-01-05 01:27:54 +000015 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000016 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000017#define IN_LIBXML
18#include "libxml.h"
19
Daniel Veillard81273902003-09-30 00:43:48 +000020#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000022#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023
24#ifdef HAVE_CTYPE_H
25#include <ctype.h>
26#endif
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#include <libxml/xmlmemory.h>
32#include <libxml/xmlIO.h>
33#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000034#include <libxml/parserInternals.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000035#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +000036#include <libxml/relaxng.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000037#include <libxml/xmlschemas.h>
38#endif
Daniel Veillard198c1bf2003-10-20 17:07:41 +000039#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000040#ifdef LIBXML_XINCLUDE_ENABLED
41#include <libxml/xinclude.h>
42#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000046
47/* #define DEBUG_CALLBACKS */
48/* #define DEBUG_READER */
49
50/**
51 * TODO:
52 *
53 * macro to flag unimplemented blocks
54 */
55#define TODO \
56 xmlGenericError(xmlGenericErrorContext, \
57 "Unimplemented block at %s:%d\n", \
58 __FILE__, __LINE__);
59
60#ifdef DEBUG_READER
61#define DUMP_READER xmlTextReaderDebug(reader);
62#else
63#define DUMP_READER
64#endif
65
Daniel Veillarda880b122003-04-21 21:36:41 +000066#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000067/************************************************************************
68 * *
69 * The parser: maps the Text Reader API on top of the existing *
70 * parsing routines building a tree *
71 * *
72 ************************************************************************/
73
74#define XML_TEXTREADER_INPUT 1
75#define XML_TEXTREADER_CTXT 2
76
77typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +000078 XML_TEXTREADER_NONE = -1,
79 XML_TEXTREADER_START= 0,
80 XML_TEXTREADER_ELEMENT= 1,
81 XML_TEXTREADER_END= 2,
82 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000083 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000084 XML_TEXTREADER_DONE= 5,
85 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000086} xmlTextReaderState;
87
Daniel Veillardf4e55762003-04-15 23:32:22 +000088typedef enum {
89 XML_TEXTREADER_NOT_VALIDATE = 0,
90 XML_TEXTREADER_VALIDATE_DTD = 1,
Daniel Veillardf10ae122005-07-10 19:03:16 +000091 XML_TEXTREADER_VALIDATE_RNG = 2,
92 XML_TEXTREADER_VALIDATE_XSD = 4
Daniel Veillardf4e55762003-04-15 23:32:22 +000093} xmlTextReaderValidate;
94
Daniel Veillarde1ca5032002-12-09 14:13:43 +000095struct _xmlTextReader {
96 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +000097 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +000098 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000099 int allocs; /* what structure were deallocated */
100 xmlTextReaderState state;
101 xmlParserCtxtPtr ctxt; /* the parser context */
102 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
103 xmlParserInputBufferPtr input; /* the input */
104 startElementSAXFunc startElement;/* initial SAX callbacks */
105 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000106 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000107 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000108 charactersSAXFunc characters;
109 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000110 unsigned int base; /* base of the segment in the input */
111 unsigned int cur; /* current position in the input */
112 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000113 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000114 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000115 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000117 xmlBufferPtr buffer; /* used to return const xmlChar * */
118 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000119
120 /* entity stack when traversing entities content */
121 xmlNodePtr ent; /* Current Entity Ref Node */
122 int entNr; /* Depth of the entities stack */
123 int entMax; /* Max depth of the entities stack */
124 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000125
126 /* error handling */
127 xmlTextReaderErrorFunc errorFunc; /* callback function */
128 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000129
130#ifdef LIBXML_SCHEMAS_ENABLED
131 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000132 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
133 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
134 int rngValidErrors;/* The number of errors detected */
135 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000136 /* Handling of Schemas validation */
137 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
138 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
139 int xsdValidErrors;/* The number of errors detected */
140 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000141#endif
142#ifdef LIBXML_XINCLUDE_ENABLED
143 /* Handling of XInclude processing */
144 int xinclude; /* is xinclude asked for */
145 const xmlChar * xinclude_name; /* the xinclude name from dict */
146 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
147 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000148#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000149#ifdef LIBXML_PATTERN_ENABLED
150 int patternNr; /* number of preserve patterns */
151 int patternMax; /* max preserve patterns */
152 xmlPatternPtr *patternTab; /* array of preserve patterns */
153#endif
154 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000155 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000156 /* Structured error handling */
157 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000158};
159
Daniel Veillarde8039df2003-10-27 11:25:13 +0000160#define NODE_IS_EMPTY 0x1
161#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000162#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000163
Daniel Veillarde72c5082003-09-19 12:44:05 +0000164/**
165 * CONSTSTR:
166 *
167 * Macro used to return an interned string
168 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000169#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
170#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
171
172static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
173static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000174
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000175/************************************************************************
176 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000177 * Our own version of the freeing routines as we recycle nodes *
178 * *
179 ************************************************************************/
180/**
181 * DICT_FREE:
182 * @str: a string
183 *
184 * Free a string if it is not owned by the "dict" dictionnary in the
185 * current scope
186 */
187#define DICT_FREE(str) \
188 if ((str) && ((!dict) || \
189 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
190 xmlFree((char *)(str));
191
192static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
193static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
194
195/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000196 * xmlFreeID:
197 * @not: A id
198 *
199 * Deallocate the memory used by an id definition
200 */
201static void
202xmlFreeID(xmlIDPtr id) {
203 xmlDictPtr dict = NULL;
204
205 if (id == NULL) return;
206
207 if (id->doc != NULL)
208 dict = id->doc->dict;
209
210 if (id->value != NULL)
211 DICT_FREE(id->value)
212 xmlFree(id);
213}
214
215/**
216 * xmlTextReaderRemoveID:
217 * @doc: the document
218 * @attr: the attribute
219 *
220 * Remove the given attribute from the ID table maintained internally.
221 *
222 * Returns -1 if the lookup failed and 0 otherwise
223 */
224static int
225xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
226 xmlIDTablePtr table;
227 xmlIDPtr id;
228 xmlChar *ID;
229
230 if (doc == NULL) return(-1);
231 if (attr == NULL) return(-1);
232 table = (xmlIDTablePtr) doc->ids;
233 if (table == NULL)
234 return(-1);
235
236 if (attr == NULL)
237 return(-1);
238 ID = xmlNodeListGetString(doc, attr->children, 1);
239 if (ID == NULL)
240 return(-1);
241 id = xmlHashLookup(table, ID);
242 xmlFree(ID);
243 if (id == NULL || id->attr != attr) {
244 return(-1);
245 }
246 id->name = attr->name;
247 id->attr = NULL;
248 return(0);
249}
250
251/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000252 * xmlTextReaderFreeProp:
253 * @reader: the xmlTextReaderPtr used
254 * @cur: the node
255 *
256 * Free a node.
257 */
258static void
259xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
260 xmlDictPtr dict;
261
262 dict = reader->ctxt->dict;
263 if (cur == NULL) return;
264
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000265 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
266 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
267
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000268 /* Check for ID removal -> leading to invalid references ! */
269 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
270 ((cur->parent->doc->intSubset != NULL) ||
271 (cur->parent->doc->extSubset != NULL))) {
272 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000273 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000274 }
275 if (cur->children != NULL)
276 xmlTextReaderFreeNodeList(reader, cur->children);
277
278 DICT_FREE(cur->name);
279 if ((reader != NULL) && (reader->ctxt != NULL) &&
280 (reader->ctxt->freeAttrsNr < 100)) {
281 cur->next = reader->ctxt->freeAttrs;
282 reader->ctxt->freeAttrs = cur;
283 reader->ctxt->freeAttrsNr++;
284 } else {
285 xmlFree(cur);
286 }
287}
288
289/**
290 * xmlTextReaderFreePropList:
291 * @reader: the xmlTextReaderPtr used
292 * @cur: the first property in the list
293 *
294 * Free a property and all its siblings, all the children are freed too.
295 */
296static void
297xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
298 xmlAttrPtr next;
299 if (cur == NULL) return;
300 while (cur != NULL) {
301 next = cur->next;
302 xmlTextReaderFreeProp(reader, cur);
303 cur = next;
304 }
305}
306
307/**
308 * xmlTextReaderFreeNodeList:
309 * @reader: the xmlTextReaderPtr used
310 * @cur: the first node in the list
311 *
312 * Free a node and all its siblings, this is a recursive behaviour, all
313 * the children are freed too.
314 */
315static void
316xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
317 xmlNodePtr next;
318 xmlDictPtr dict;
319
320 dict = reader->ctxt->dict;
321 if (cur == NULL) return;
322 if (cur->type == XML_NAMESPACE_DECL) {
323 xmlFreeNsList((xmlNsPtr) cur);
324 return;
325 }
326 if ((cur->type == XML_DOCUMENT_NODE) ||
327 (cur->type == XML_HTML_DOCUMENT_NODE)) {
328 xmlFreeDoc((xmlDocPtr) cur);
329 return;
330 }
331 while (cur != NULL) {
332 next = cur->next;
333 /* unroll to speed up freeing the document */
334 if (cur->type != XML_DTD_NODE) {
335
336 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000337 (cur->type != XML_ENTITY_REF_NODE)) {
338 if (cur->children->parent == cur)
339 xmlTextReaderFreeNodeList(reader, cur->children);
340 cur->children = NULL;
341 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000342
343 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
344 xmlDeregisterNodeDefaultValue(cur);
345
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000346 if (((cur->type == XML_ELEMENT_NODE) ||
347 (cur->type == XML_XINCLUDE_START) ||
348 (cur->type == XML_XINCLUDE_END)) &&
349 (cur->properties != NULL))
350 xmlTextReaderFreePropList(reader, cur->properties);
351 if ((cur->type != XML_ELEMENT_NODE) &&
352 (cur->type != XML_XINCLUDE_START) &&
353 (cur->type != XML_XINCLUDE_END) &&
354 (cur->type != XML_ENTITY_REF_NODE)) {
355 DICT_FREE(cur->content);
356 }
357 if (((cur->type == XML_ELEMENT_NODE) ||
358 (cur->type == XML_XINCLUDE_START) ||
359 (cur->type == XML_XINCLUDE_END)) &&
360 (cur->nsDef != NULL))
361 xmlFreeNsList(cur->nsDef);
362
363 /*
364 * we don't free element names here they are interned now
365 */
366 if ((cur->type != XML_TEXT_NODE) &&
367 (cur->type != XML_COMMENT_NODE))
368 DICT_FREE(cur->name);
369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_TEXT_NODE)) &&
371 (reader != NULL) && (reader->ctxt != NULL) &&
372 (reader->ctxt->freeElemsNr < 100)) {
373 cur->next = reader->ctxt->freeElems;
374 reader->ctxt->freeElems = cur;
375 reader->ctxt->freeElemsNr++;
376 } else {
377 xmlFree(cur);
378 }
379 }
380 cur = next;
381 }
382}
383
384/**
385 * xmlTextReaderFreeNode:
386 * @reader: the xmlTextReaderPtr used
387 * @cur: the node
388 *
389 * Free a node, this is a recursive behaviour, all the children are freed too.
390 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
391 */
392static void
393xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
394 xmlDictPtr dict;
395
396 dict = reader->ctxt->dict;
397 if (cur->type == XML_DTD_NODE) {
398 xmlFreeDtd((xmlDtdPtr) cur);
399 return;
400 }
401 if (cur->type == XML_NAMESPACE_DECL) {
402 xmlFreeNs((xmlNsPtr) cur);
403 return;
404 }
405 if (cur->type == XML_ATTRIBUTE_NODE) {
406 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
407 return;
408 }
409
410 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000411 (cur->type != XML_ENTITY_REF_NODE)) {
412 if (cur->children->parent == cur)
413 xmlTextReaderFreeNodeList(reader, cur->children);
414 cur->children = NULL;
415 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000416
417 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
418 xmlDeregisterNodeDefaultValue(cur);
419
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000420 if (((cur->type == XML_ELEMENT_NODE) ||
421 (cur->type == XML_XINCLUDE_START) ||
422 (cur->type == XML_XINCLUDE_END)) &&
423 (cur->properties != NULL))
424 xmlTextReaderFreePropList(reader, cur->properties);
425 if ((cur->type != XML_ELEMENT_NODE) &&
426 (cur->type != XML_XINCLUDE_START) &&
427 (cur->type != XML_XINCLUDE_END) &&
428 (cur->type != XML_ENTITY_REF_NODE)) {
429 DICT_FREE(cur->content);
430 }
431 if (((cur->type == XML_ELEMENT_NODE) ||
432 (cur->type == XML_XINCLUDE_START) ||
433 (cur->type == XML_XINCLUDE_END)) &&
434 (cur->nsDef != NULL))
435 xmlFreeNsList(cur->nsDef);
436
437 /*
438 * we don't free names here they are interned now
439 */
440 if ((cur->type != XML_TEXT_NODE) &&
441 (cur->type != XML_COMMENT_NODE))
442 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000443
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000444 if (((cur->type == XML_ELEMENT_NODE) ||
445 (cur->type == XML_TEXT_NODE)) &&
446 (reader != NULL) && (reader->ctxt != NULL) &&
447 (reader->ctxt->freeElemsNr < 100)) {
448 cur->next = reader->ctxt->freeElems;
449 reader->ctxt->freeElems = cur;
450 reader->ctxt->freeElemsNr++;
451 } else {
452 xmlFree(cur);
453 }
454}
455
456/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000457 * xmlTextReaderFreeIDTable:
458 * @table: An id table
459 *
460 * Deallocate the memory used by an ID hash table.
461 */
William M. Brack60f394e2003-11-16 06:25:42 +0000462static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000463xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
464 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
465}
466
467/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000468 * xmlTextReaderFreeDoc:
469 * @reader: the xmlTextReaderPtr used
470 * @cur: pointer to the document
471 *
472 * Free up all the structures used by a document, tree included.
473 */
474static void
475xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
476 xmlDtdPtr extSubset, intSubset;
477
478 if (cur == NULL) return;
479
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000480 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
481 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
482
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000483 /*
484 * Do this before freeing the children list to avoid ID lookups
485 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000486 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000487 cur->ids = NULL;
488 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
489 cur->refs = NULL;
490 extSubset = cur->extSubset;
491 intSubset = cur->intSubset;
492 if (intSubset == extSubset)
493 extSubset = NULL;
494 if (extSubset != NULL) {
495 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
496 cur->extSubset = NULL;
497 xmlFreeDtd(extSubset);
498 }
499 if (intSubset != NULL) {
500 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
501 cur->intSubset = NULL;
502 xmlFreeDtd(intSubset);
503 }
504
505 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
506
507 if (cur->version != NULL) xmlFree((char *) cur->version);
508 if (cur->name != NULL) xmlFree((char *) cur->name);
509 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
510 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
511 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000512 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000513
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000514 xmlFree(cur);
515}
516
517/************************************************************************
518 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000519 * The reader core parser *
520 * *
521 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000522#ifdef DEBUG_READER
523static void
524xmlTextReaderDebug(xmlTextReaderPtr reader) {
525 if ((reader == NULL) || (reader->ctxt == NULL)) {
526 fprintf(stderr, "xmlTextReader NULL\n");
527 return;
528 }
529 fprintf(stderr, "xmlTextReader: state %d depth %d ",
530 reader->state, reader->depth);
531 if (reader->node == NULL) {
532 fprintf(stderr, "node = NULL\n");
533 } else {
534 fprintf(stderr, "node %s\n", reader->node->name);
535 }
536 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
537 reader->base, reader->cur, reader->ctxt->nodeNr);
538 if (reader->input->buffer == NULL) {
539 fprintf(stderr, "buffer is NULL\n");
540 } else {
541#ifdef LIBXML_DEBUG_ENABLED
542 xmlDebugDumpString(stderr,
543 &reader->input->buffer->content[reader->cur]);
544#endif
545 fprintf(stderr, "\n");
546 }
547}
548#endif
549
550/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000551 * xmlTextReaderEntPush:
552 * @reader: the xmlTextReaderPtr used
553 * @value: the entity reference node
554 *
555 * Pushes a new entity reference node on top of the entities stack
556 *
557 * Returns 0 in case of error, the index in the stack otherwise
558 */
559static int
560xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
561{
562 if (reader->entMax <= 0) {
563 reader->entMax = 10;
564 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
565 sizeof(reader->entTab[0]));
566 if (reader->entTab == NULL) {
567 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
568 return (0);
569 }
570 }
571 if (reader->entNr >= reader->entMax) {
572 reader->entMax *= 2;
573 reader->entTab =
574 (xmlNodePtr *) xmlRealloc(reader->entTab,
575 reader->entMax *
576 sizeof(reader->entTab[0]));
577 if (reader->entTab == NULL) {
578 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
579 return (0);
580 }
581 }
582 reader->entTab[reader->entNr] = value;
583 reader->ent = value;
584 return (reader->entNr++);
585}
586
587/**
588 * xmlTextReaderEntPop:
589 * @reader: the xmlTextReaderPtr used
590 *
591 * Pops the top element entity from the entities stack
592 *
593 * Returns the entity just removed
594 */
595static xmlNodePtr
596xmlTextReaderEntPop(xmlTextReaderPtr reader)
597{
598 xmlNodePtr ret;
599
600 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000601 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000602 reader->entNr--;
603 if (reader->entNr > 0)
604 reader->ent = reader->entTab[reader->entNr - 1];
605 else
606 reader->ent = NULL;
607 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000608 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000609 return (ret);
610}
611
612/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000613 * xmlTextReaderStartElement:
614 * @ctx: the user data (XML parser context)
615 * @fullname: The element name, including namespace prefix
616 * @atts: An array of name/value attributes pairs, NULL terminated
617 *
618 * called when an opening tag has been processed.
619 */
620static void
621xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
622 const xmlChar **atts) {
623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
624 xmlTextReaderPtr reader = ctxt->_private;
625
626#ifdef DEBUG_CALLBACKS
627 printf("xmlTextReaderStartElement(%s)\n", fullname);
628#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000629 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000630 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000631 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
632 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
633 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000634 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000635 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000636 if (reader != NULL)
637 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000638}
639
640/**
641 * xmlTextReaderEndElement:
642 * @ctx: the user data (XML parser context)
643 * @fullname: The element name, including namespace prefix
644 *
645 * called when an ending tag has been processed.
646 */
647static void
648xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
649 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
650 xmlTextReaderPtr reader = ctxt->_private;
651
652#ifdef DEBUG_CALLBACKS
653 printf("xmlTextReaderEndElement(%s)\n", fullname);
654#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000655 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000656 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000657 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000658}
659
660/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000661 * xmlTextReaderStartElementNs:
662 * @ctx: the user data (XML parser context)
663 * @localname: the local name of the element
664 * @prefix: the element namespace prefix if available
665 * @URI: the element namespace name if available
666 * @nb_namespaces: number of namespace definitions on that node
667 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
668 * @nb_attributes: the number of attributes on that node
669 * nb_defaulted: the number of defaulted attributes.
670 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
671 * attribute values.
672 *
673 * called when an opening tag has been processed.
674 */
675static void
676xmlTextReaderStartElementNs(void *ctx,
677 const xmlChar *localname,
678 const xmlChar *prefix,
679 const xmlChar *URI,
680 int nb_namespaces,
681 const xmlChar **namespaces,
682 int nb_attributes,
683 int nb_defaulted,
684 const xmlChar **attributes)
685{
686 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
687 xmlTextReaderPtr reader = ctxt->_private;
688
689#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000690 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000691#endif
692 if ((reader != NULL) && (reader->startElementNs != NULL)) {
693 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
694 namespaces, nb_attributes, nb_defaulted,
695 attributes);
696 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
697 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
698 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000699 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000700 }
701 if (reader != NULL)
702 reader->state = XML_TEXTREADER_ELEMENT;
703}
704
705/**
706 * xmlTextReaderEndElementNs:
707 * @ctx: the user data (XML parser context)
708 * @localname: the local name of the element
709 * @prefix: the element namespace prefix if available
710 * @URI: the element namespace name if available
711 *
712 * called when an ending tag has been processed.
713 */
714static void
715xmlTextReaderEndElementNs(void *ctx,
716 const xmlChar * localname,
717 const xmlChar * prefix,
718 const xmlChar * URI)
719{
720 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
721 xmlTextReaderPtr reader = ctxt->_private;
722
723#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000724 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000725#endif
726 if ((reader != NULL) && (reader->endElementNs != NULL)) {
727 reader->endElementNs(ctx, localname, prefix, URI);
728 }
729}
730
731
732/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000733 * xmlTextReaderCharacters:
734 * @ctx: the user data (XML parser context)
735 * @ch: a xmlChar string
736 * @len: the number of xmlChar
737 *
738 * receiving some chars from the parser.
739 */
740static void
741xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
742{
743 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
744 xmlTextReaderPtr reader = ctxt->_private;
745
746#ifdef DEBUG_CALLBACKS
747 printf("xmlTextReaderCharacters()\n");
748#endif
749 if ((reader != NULL) && (reader->characters != NULL)) {
750 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000751 }
752}
753
754/**
755 * xmlTextReaderCDataBlock:
756 * @ctx: the user data (XML parser context)
757 * @value: The pcdata content
758 * @len: the block length
759 *
760 * called when a pcdata block has been parsed
761 */
762static void
763xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
764{
765 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
766 xmlTextReaderPtr reader = ctxt->_private;
767
768#ifdef DEBUG_CALLBACKS
769 printf("xmlTextReaderCDataBlock()\n");
770#endif
771 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
772 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000773 }
774}
775
776/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000777 * xmlTextReaderPushData:
778 * @reader: the xmlTextReaderPtr used
779 *
780 * Push data down the progressive parser until a significant callback
781 * got raised.
782 *
783 * Returns -1 in case of failure, 0 otherwise
784 */
785static int
786xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000787 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000788 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000789 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000790
791 if ((reader->input == NULL) || (reader->input->buffer == NULL))
792 return(-1);
793
Daniel Veillardea7751d2002-12-20 00:16:24 +0000794 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000795 reader->state = XML_TEXTREADER_NONE;
796 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000797
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000799 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000800 /*
801 * Refill the buffer unless we are at the end of the stream
802 */
803 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
804 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000805 if ((val == 0) &&
806 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
807 if (inbuf->use == reader->cur) {
808 reader->mode = XML_TEXTREADER_MODE_EOF;
809 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000810 }
811 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000812 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000813 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000814 if ((oldstate != XML_TEXTREADER_START) ||
815 (reader->ctxt->myDoc != NULL))
816 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000817 } else if (val == 0) {
818 /* mark the end of the stream and process the remains */
819 reader->mode = XML_TEXTREADER_MODE_EOF;
820 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000822
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000823 } else
824 break;
825 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000826 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000827 * parse by block of CHUNK_SIZE bytes, various tests show that
828 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000829 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000831 val = xmlParseChunk(reader->ctxt,
832 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000833 CHUNK_SIZE, 0);
834 reader->cur += CHUNK_SIZE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000835 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000836 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000837 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000838 s = inbuf->use - reader->cur;
839 val = xmlParseChunk(reader->ctxt,
840 (const char *) &inbuf->content[reader->cur],
841 s, 0);
842 reader->cur += s;
William M. Brack9f797ab2004-07-28 07:40:12 +0000843 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000844 return(-1);
845 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000846 }
847 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000848
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000849 /*
850 * Discard the consumed input when needed and possible
851 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000852 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000853 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
854 if ((reader->cur >= 4096) &&
855 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
856 val = xmlBufferShrink(inbuf, reader->cur);
857 if (val >= 0) {
858 reader->cur -= val;
859 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000860 }
861 }
862 }
863
864 /*
865 * At the end of the stream signal that the work is done to the Push
866 * parser.
867 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000868 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000869 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000870 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000871 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000872 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000873 s, 1);
874 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000875 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +0000876 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000877 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000878 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000879 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000880 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000881 return(0);
882}
883
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000884#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000885/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000886 * xmlTextReaderValidatePush:
887 * @reader: the xmlTextReaderPtr used
888 *
889 * Push the current node for validation
890 */
891static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000892xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000893 xmlNodePtr node = reader->node;
894
Daniel Veillardf54cd532004-02-25 11:52:31 +0000895#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000896 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
897 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
898 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
899 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
900 reader->ctxt->myDoc, node, node->name);
901 } else {
902 /* TODO use the BuildQName interface */
903 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000904
Daniel Veillardf4e55762003-04-15 23:32:22 +0000905 qname = xmlStrdup(node->ns->prefix);
906 qname = xmlStrcat(qname, BAD_CAST ":");
907 qname = xmlStrcat(qname, node->name);
908 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
909 reader->ctxt->myDoc, node, qname);
910 if (qname != NULL)
911 xmlFree(qname);
912 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000913 }
914#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000915#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000916 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000917 (reader->rngValidCtxt != NULL)) {
918 int ret;
919
920 if (reader->rngFullNode != NULL) return;
921 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
922 reader->ctxt->myDoc,
923 node);
924 if (ret == 0) {
925 /*
926 * this element requires a full tree
927 */
928 node = xmlTextReaderExpand(reader);
929 if (node == NULL) {
930printf("Expand failed !\n");
931 ret = -1;
932 } else {
933 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
934 reader->ctxt->myDoc,
935 node);
936 reader->rngFullNode = node;
937 }
938 }
939 if (ret != 1)
940 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000941 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000942#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000943}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000944
945/**
946 * xmlTextReaderValidateCData:
947 * @reader: the xmlTextReaderPtr used
948 * @data: pointer to the CData
949 * @len: lenght of the CData block in bytes.
950 *
951 * Push some CData for validation
952 */
953static void
954xmlTextReaderValidateCData(xmlTextReaderPtr reader,
955 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000956#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000957 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
958 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
959 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
960 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000961 }
962#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000963#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000964 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965 (reader->rngValidCtxt != NULL)) {
966 int ret;
967
968 if (reader->rngFullNode != NULL) return;
969 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
970 if (ret != 1)
971 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000972 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000973#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000974}
975
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000976/**
977 * xmlTextReaderValidatePop:
978 * @reader: the xmlTextReaderPtr used
979 *
980 * Pop the current node from validation
981 */
982static void
983xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
984 xmlNodePtr node = reader->node;
985
Daniel Veillardf54cd532004-02-25 11:52:31 +0000986#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000987 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
988 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
989 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
990 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
991 reader->ctxt->myDoc, node, node->name);
992 } else {
993 /* TODO use the BuildQName interface */
994 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000995
Daniel Veillardf4e55762003-04-15 23:32:22 +0000996 qname = xmlStrdup(node->ns->prefix);
997 qname = xmlStrcat(qname, BAD_CAST ":");
998 qname = xmlStrcat(qname, node->name);
999 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1000 reader->ctxt->myDoc, node, qname);
1001 if (qname != NULL)
1002 xmlFree(qname);
1003 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001004 }
1005#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001006#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001008 (reader->rngValidCtxt != NULL)) {
1009 int ret;
1010
1011 if (reader->rngFullNode != NULL) {
1012 if (node == reader->rngFullNode)
1013 reader->rngFullNode = NULL;
1014 return;
1015 }
1016 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1017 reader->ctxt->myDoc,
1018 node);
1019 if (ret != 1)
1020 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001021 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001022#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001023}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001024
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001025/**
1026 * xmlTextReaderValidateEntity:
1027 * @reader: the xmlTextReaderPtr used
1028 *
1029 * Handle the validation when an entity reference is encountered and
1030 * entity substitution is not activated. As a result the parser interface
1031 * must walk through the entity and do the validation calls
1032 */
1033static void
1034xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1035 xmlNodePtr oldnode = reader->node;
1036 xmlNodePtr node = reader->node;
1037 xmlParserCtxtPtr ctxt = reader->ctxt;
1038
1039 do {
1040 if (node->type == XML_ENTITY_REF_NODE) {
1041 /*
1042 * Case where the underlying tree is not availble, lookup the entity
1043 * and walk it.
1044 */
1045 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1046 (ctxt->sax->getEntity != NULL)) {
1047 node->children = (xmlNodePtr)
1048 ctxt->sax->getEntity(ctxt, node->name);
1049 }
1050
1051 if ((node->children != NULL) &&
1052 (node->children->type == XML_ENTITY_DECL) &&
1053 (node->children->children != NULL)) {
1054 xmlTextReaderEntPush(reader, node);
1055 node = node->children->children;
1056 continue;
1057 } else {
1058 /*
1059 * The error has probably be raised already.
1060 */
1061 if (node == oldnode)
1062 break;
1063 node = node->next;
1064 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001065#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001066 } else if (node->type == XML_ELEMENT_NODE) {
1067 reader->node = node;
1068 xmlTextReaderValidatePush(reader);
1069 } else if ((node->type == XML_TEXT_NODE) ||
1070 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001071 xmlTextReaderValidateCData(reader, node->content,
1072 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001073#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001074 }
1075
1076 /*
1077 * go to next node
1078 */
1079 if (node->children != NULL) {
1080 node = node->children;
1081 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001082 } else if (node->type == XML_ELEMENT_NODE) {
1083 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001084 }
1085 if (node->next != NULL) {
1086 node = node->next;
1087 continue;
1088 }
1089 do {
1090 node = node->parent;
1091 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001092 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001093 if (reader->entNr == 0) {
1094 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001095 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001096 xmlUnlinkNode(tmp);
1097 xmlTextReaderFreeNode(reader, tmp);
1098 } else
1099 break;
1100 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001101 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001102 reader->node = node;
1103 xmlTextReaderValidatePop(reader);
1104 }
1105 if ((node->type == XML_ENTITY_DECL) &&
1106 (reader->ent != NULL) && (reader->ent->children == node)) {
1107 node = xmlTextReaderEntPop(reader);
1108 }
1109 if (node == oldnode)
1110 break;
1111 if (node->next != NULL) {
1112 node = node->next;
1113 break;
1114 }
1115 } while ((node != NULL) && (node != oldnode));
1116 } while ((node != NULL) && (node != oldnode));
1117 reader->node = oldnode;
1118}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001119#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001120
1121
1122/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001123 * xmlTextReaderGetSuccessor:
1124 * @cur: the current node
1125 *
1126 * Get the successor of a node if available.
1127 *
1128 * Returns the successor node or NULL
1129 */
1130static xmlNodePtr
1131xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1132 if (cur == NULL) return(NULL) ; /* ERROR */
1133 if (cur->next != NULL) return(cur->next) ;
1134 do {
1135 cur = cur->parent;
1136 if (cur == NULL) return(NULL);
1137 if (cur->next != NULL) return(cur->next);
1138 } while (cur != NULL);
1139 return(cur);
1140}
1141
1142/**
1143 * xmlTextReaderDoExpand:
1144 * @reader: the xmlTextReaderPtr used
1145 *
1146 * Makes sure that the current node is fully read as well as all its
1147 * descendant. It means the full DOM subtree must be available at the
1148 * end of the call.
1149 *
1150 * Returns 1 if the node was expanded successfully, 0 if there is no more
1151 * nodes to read, or -1 in case of error
1152 */
1153static int
1154xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1155 int val;
1156
1157 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1158 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001159 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001160 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1161
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001162 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1163 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001164 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001165 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001166 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1167 return(1);
1168 val = xmlTextReaderPushData(reader);
1169 if (val < 0)
1170 return(-1);
1171 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1172 return(1);
1173}
1174
1175/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001176 * xmlTextReaderCollectSiblings:
1177 * @node: the first child
1178 *
1179 * Traverse depth-first through all sibling nodes and their children
1180 * nodes and concatenate their content. This is an auxiliary function
1181 * to xmlTextReaderReadString.
1182 *
1183 * Returns a string containing the content, or NULL in case of error.
1184 */
1185static xmlChar *
1186xmlTextReaderCollectSiblings(xmlNodePtr node)
1187{
1188 xmlBufferPtr buffer;
1189 xmlChar *ret;
1190
1191 buffer = xmlBufferCreate();
1192 if (buffer == NULL)
1193 return NULL;
1194
1195 for ( ; node != NULL; node = node->next) {
1196 switch (node->type) {
1197 case XML_TEXT_NODE:
1198 case XML_CDATA_SECTION_NODE:
1199 xmlBufferCat(buffer, node->content);
1200 break;
1201 case XML_ELEMENT_NODE:
1202 xmlBufferCat(buffer, xmlTextReaderCollectSiblings(node->children));
1203 default:
1204 break;
1205 }
1206 }
1207 ret = buffer->content;
1208 buffer->content = NULL;
1209 xmlBufferFree(buffer);
1210 return(ret);
1211}
1212
1213/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001214 * xmlTextReaderRead:
1215 * @reader: the xmlTextReaderPtr used
1216 *
1217 * Moves the position of the current instance to the next node in
1218 * the stream, exposing its properties.
1219 *
1220 * Returns 1 if the node was read successfully, 0 if there is no more
1221 * nodes to read, or -1 in case of error
1222 */
1223int
1224xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001225 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001226 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001227 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001228
William M. Brack1af55582004-07-22 17:18:00 +00001229
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001230 if (reader == NULL)
1231 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001232 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001233 if (reader->doc != NULL)
1234 return(xmlTextReaderReadTree(reader));
1235 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001236 return(-1);
1237 if (reader->ctxt->wellFormed != 1)
1238 return(-1);
1239
1240#ifdef DEBUG_READER
1241 fprintf(stderr, "\nREAD ");
1242 DUMP_READER
1243#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001244 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1245 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001246 /*
1247 * Initial state
1248 */
1249 do {
1250 val = xmlTextReaderPushData(reader);
1251 if (val < 0)
1252 return(-1);
1253 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001254 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1255 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001256 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001257 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001258 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001259 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001260 if (reader->node == NULL)
1261 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001262 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001264 if (reader->ctxt->myDoc != NULL) {
1265 reader->node = reader->ctxt->myDoc->children;
1266 }
1267 if (reader->node == NULL)
1268 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001269 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001270 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001271 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001272 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001273 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001274 }
1275 oldstate = reader->state;
1276 olddepth = reader->ctxt->nodeNr;
1277 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001278
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001279get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001280 if (reader->node == NULL) {
1281 if (reader->mode == XML_TEXTREADER_DONE)
1282 return(0);
1283 else
1284 return(-1);
1285 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001286
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287 /*
1288 * If we are not backtracking on ancestors or examined nodes,
1289 * that the parser didn't finished or that we arent at the end
1290 * of stream, continue processing.
1291 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001292 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001293 (reader->ctxt->nodeNr == olddepth) &&
1294 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001295 (reader->node->children == NULL) ||
1296 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001297 ((reader->node->children != NULL) &&
1298 (reader->node->children->type == XML_TEXT_NODE) &&
1299 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001300 (reader->node->type == XML_DTD_NODE) ||
1301 (reader->node->type == XML_DOCUMENT_NODE) ||
1302 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001303 ((reader->ctxt->node == NULL) ||
1304 (reader->ctxt->node == reader->node) ||
1305 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001306 (reader->ctxt->instate != XML_PARSER_EOF)) {
1307 val = xmlTextReaderPushData(reader);
1308 if (val < 0)
1309 return(-1);
1310 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001311 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001312 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001313 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001314 if ((reader->node->children != NULL) &&
1315 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001316 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001317 (reader->node->type != XML_DTD_NODE)) {
1318 reader->node = reader->node->children;
1319 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001320 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001321 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 }
1323 }
1324 if (reader->node->next != NULL) {
1325 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001326 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001327 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001328 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1329#ifdef LIBXML_XINCLUDE_ENABLED
1330 && (reader->in_xinclude <= 0)
1331#endif
1332 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001333 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001334 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001336#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001337 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001338 (reader->node->type == XML_ELEMENT_NODE))
1339 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001340#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001341 if ((reader->preserves > 0) &&
1342 (reader->node->extra & NODE_IS_SPRESERVED))
1343 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 reader->node = reader->node->next;
1345 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001346
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001347 /*
1348 * Cleanup of the old node
1349 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001350 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001351#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001352 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001353#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001354 (reader->entNr == 0) &&
1355 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001356 (reader->node->prev->type != XML_DTD_NODE) &&
1357 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001358 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001359 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001360 xmlUnlinkNode(tmp);
1361 xmlTextReaderFreeNode(reader, tmp);
1362 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 }
1364
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001365 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001366 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001367 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001368 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001369 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001370 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001371 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001372 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001373 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001374#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001375 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001376 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001377#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001378 if ((reader->preserves > 0) &&
1379 (reader->node->extra & NODE_IS_SPRESERVED))
1380 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001381 reader->node = reader->node->parent;
1382 if ((reader->node == NULL) ||
1383 (reader->node->type == XML_DOCUMENT_NODE) ||
1384#ifdef LIBXML_DOCB_ENABLED
1385 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1386#endif
1387 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001388 if (reader->mode != XML_TEXTREADER_DONE) {
1389 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1390 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001391 if (val != 0)
1392 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001393 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001394 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001395 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001396
1397 /*
1398 * Cleanup of the old node
1399 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001400 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001401#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001402 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001403#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001404 (reader->entNr == 0) &&
1405 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001406 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001407 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001408 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001409 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001410 }
1411
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001412 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001413 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001414 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001415#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001416 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001417#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001418 (reader->entNr == 0) &&
1419 (reader->node->last != NULL) &&
1420 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1421 xmlNodePtr tmp = reader->node->last;
1422 xmlUnlinkNode(tmp);
1423 xmlTextReaderFreeNode(reader, tmp);
1424 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001425 reader->depth--;
1426 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001427
1428node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001429 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001430
1431 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001432 * If we are in the middle of a piece of CDATA make sure it's finished
1433 */
1434 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001435 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001436 ((reader->node->type == XML_TEXT_NODE) ||
1437 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001438 if (xmlTextReaderExpand(reader) == NULL)
1439 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001440 }
1441
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001442#ifdef LIBXML_XINCLUDE_ENABLED
1443 /*
1444 * Handle XInclude if asked for
1445 */
1446 if ((reader->xinclude) && (reader->node != NULL) &&
1447 (reader->node->type == XML_ELEMENT_NODE) &&
1448 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001449 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1450 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001451 if (reader->xincctxt == NULL) {
1452 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardc14c3892004-08-16 12:34:50 +00001453 xmlXIncludeSetFlags(reader->xincctxt,
1454 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001455 }
1456 /*
1457 * expand that node and process it
1458 */
William M. Brack42331a92004-07-29 07:07:16 +00001459 if (xmlTextReaderExpand(reader) == NULL)
1460 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001461 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1462 }
1463 if (reader->node->type == XML_XINCLUDE_START) {
1464 reader->in_xinclude++;
1465 goto get_next_node;
1466 }
1467 if (reader->node->type == XML_XINCLUDE_END) {
1468 reader->in_xinclude--;
1469 goto get_next_node;
1470 }
1471#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001472 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001473 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001474 */
1475 if ((reader->node != NULL) &&
1476 (reader->node->type == XML_ENTITY_REF_NODE) &&
1477 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1478 /*
1479 * Case where the underlying tree is not availble, lookup the entity
1480 * and walk it.
1481 */
1482 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1483 (reader->ctxt->sax->getEntity != NULL)) {
1484 reader->node->children = (xmlNodePtr)
1485 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1486 }
1487
1488 if ((reader->node->children != NULL) &&
1489 (reader->node->children->type == XML_ENTITY_DECL) &&
1490 (reader->node->children->children != NULL)) {
1491 xmlTextReaderEntPush(reader, reader->node);
1492 reader->node = reader->node->children->children;
1493 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001494#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001495 } else if ((reader->node != NULL) &&
1496 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001497 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001498 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001499#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001500 }
1501 if ((reader->node != NULL) &&
1502 (reader->node->type == XML_ENTITY_DECL) &&
1503 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1504 reader->node = xmlTextReaderEntPop(reader);
1505 reader->depth++;
1506 goto get_next_node;
1507 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001508#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001509 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001510 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001511
1512 if ((node->type == XML_ELEMENT_NODE) &&
1513 ((reader->state != XML_TEXTREADER_END) &&
1514 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1515 xmlTextReaderValidatePush(reader);
1516 } else if ((node->type == XML_TEXT_NODE) ||
1517 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001518 xmlTextReaderValidateCData(reader, node->content,
1519 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001520 }
1521 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001522#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001523#ifdef LIBXML_PATTERN_ENABLED
1524 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1525 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1526 int i;
1527 for (i = 0;i < reader->patternNr;i++) {
1528 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1529 xmlTextReaderPreserve(reader);
1530 break;
1531 }
1532 }
1533 }
1534#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001535#ifdef LIBXML_SCHEMAS_ENABLED
1536 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1537 (reader->xsdValidErrors == 0) &&
1538 (reader->xsdValidCtxt != NULL)) {
1539 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1540 }
1541#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001542 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001543node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001544 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001545 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001546}
1547
Daniel Veillard67df8092002-12-16 22:04:11 +00001548/**
1549 * xmlTextReaderReadState:
1550 * @reader: the xmlTextReaderPtr used
1551 *
1552 * Gets the read state of the reader.
1553 *
1554 * Returns the state value, or -1 in case of error
1555 */
1556int
1557xmlTextReaderReadState(xmlTextReaderPtr reader) {
1558 if (reader == NULL)
1559 return(-1);
1560 return(reader->mode);
1561}
1562
1563/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001564 * xmlTextReaderExpand:
1565 * @reader: the xmlTextReaderPtr used
1566 *
1567 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001568 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001569 *
1570 * Returns a node pointer valid until the next xmlTextReaderRead() call
1571 * or NULL in case of error.
1572 */
1573xmlNodePtr
1574xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001575 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001576 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001577 if (reader->doc != NULL)
1578 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001579 if (reader->ctxt == NULL)
1580 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001581 if (xmlTextReaderDoExpand(reader) < 0)
1582 return(NULL);
1583 return(reader->node);
1584}
1585
1586/**
1587 * xmlTextReaderNext:
1588 * @reader: the xmlTextReaderPtr used
1589 *
1590 * Skip to the node following the current one in document order while
1591 * avoiding the subtree if any.
1592 *
1593 * Returns 1 if the node was read successfully, 0 if there is no more
1594 * nodes to read, or -1 in case of error
1595 */
1596int
1597xmlTextReaderNext(xmlTextReaderPtr reader) {
1598 int ret;
1599 xmlNodePtr cur;
1600
1601 if (reader == NULL)
1602 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001603 if (reader->doc != NULL)
1604 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001605 cur = reader->node;
1606 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1607 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001608 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001609 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001610 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001611 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001612 do {
1613 ret = xmlTextReaderRead(reader);
1614 if (ret != 1)
1615 return(ret);
1616 } while (reader->node != cur);
1617 return(xmlTextReaderRead(reader));
1618}
1619
1620/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001621 * xmlTextReaderReadInnerXml:
1622 * @reader: the xmlTextReaderPtr used
1623 *
1624 * Reads the contents of the current node, including child nodes and markup.
1625 *
1626 * Returns a string containing the XML content, or NULL if the current node
1627 * is neither an element nor attribute, or has no child nodes. The
1628 * string must be deallocated by the caller.
1629 */
1630xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001631xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1632{
1633 xmlChar *resbuf;
1634 xmlNodePtr node, cur_node;
1635 xmlBufferPtr buff, buff2;
1636 xmlDocPtr doc;
1637
1638 if (xmlTextReaderExpand(reader) == NULL) {
1639 return NULL;
1640 }
1641 doc = reader->doc;
1642 buff = xmlBufferCreate();
1643 for (cur_node = reader->node->children; cur_node != NULL;
1644 cur_node = cur_node->next) {
1645 node = xmlDocCopyNode(cur_node, doc, 1);
1646 buff2 = xmlBufferCreate();
1647 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1648 xmlFreeNode(node);
1649 xmlBufferFree(buff2);
1650 xmlBufferFree(buff);
1651 return NULL;
1652 }
1653 xmlBufferCat(buff, buff2->content);
1654 xmlFreeNode(node);
1655 xmlBufferFree(buff2);
1656 }
1657 resbuf = buff->content;
1658 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001659}
1660
1661/**
1662 * xmlTextReaderReadOuterXml:
1663 * @reader: the xmlTextReaderPtr used
1664 *
1665 * Reads the contents of the current node, including child nodes and markup.
1666 *
1667 * Returns a string containing the XML content, or NULL if the current node
1668 * is neither an element nor attribute, or has no child nodes. The
1669 * string must be deallocated by the caller.
1670 */
1671xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001672xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1673{
1674 xmlChar *resbuf;
1675 xmlNodePtr node;
1676 xmlBufferPtr buff;
1677 xmlDocPtr doc;
1678
1679 node = reader->node;
1680 doc = reader->doc;
1681 if (xmlTextReaderExpand(reader) == NULL) {
1682 return NULL;
1683 }
1684 node = xmlDocCopyNode(node, doc, 1);
1685 buff = xmlBufferCreate();
1686 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1687 xmlFreeNode(node);
1688 xmlBufferFree(buff);
1689 return NULL;
1690 }
1691
1692 resbuf = buff->content;
1693 buff->content = NULL;
1694
1695 xmlFreeNode(node);
1696 xmlBufferFree(buff);
1697 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001698}
1699
1700/**
1701 * xmlTextReaderReadString:
1702 * @reader: the xmlTextReaderPtr used
1703 *
1704 * Reads the contents of an element or a text node as a string.
1705 *
1706 * Returns a string containing the contents of the Element or Text node,
1707 * or NULL if the reader is positioned on any other type of node.
1708 * The string must be deallocated by the caller.
1709 */
1710xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001711xmlTextReaderReadString(xmlTextReaderPtr reader)
1712{
1713 xmlNodePtr node;
1714
1715 if ((reader == NULL) || (reader->node == NULL))
1716 return(NULL);
1717
1718 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1719 switch (node->type) {
1720 case XML_TEXT_NODE:
1721 if (node->content != NULL)
1722 return(xmlStrdup(node->content));
1723 break;
1724 case XML_ELEMENT_NODE:
1725 if (xmlTextReaderDoExpand(reader) != -1) {
1726 return xmlTextReaderCollectSiblings(node->children);
1727 }
1728 case XML_ATTRIBUTE_NODE:
1729 TODO
1730 break;
1731 default:
1732 break;
1733 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001734 return(NULL);
1735}
1736
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001737#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001738/**
1739 * xmlTextReaderReadBase64:
1740 * @reader: the xmlTextReaderPtr used
1741 * @array: a byte array to store the content.
1742 * @offset: the zero-based index into array where the method should
1743 * begin to write.
1744 * @len: the number of bytes to write.
1745 *
1746 * Reads and decodes the Base64 encoded contents of an element and
1747 * stores the result in a byte buffer.
1748 *
1749 * Returns the number of bytes written to array, or zero if the current
1750 * instance is not positioned on an element or -1 in case of error.
1751 */
1752int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001753xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1754 unsigned char *array ATTRIBUTE_UNUSED,
1755 int offset ATTRIBUTE_UNUSED,
1756 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001757 if ((reader == NULL) || (reader->ctxt == NULL))
1758 return(-1);
1759 if (reader->ctxt->wellFormed != 1)
1760 return(-1);
1761
1762 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1763 return(0);
1764 TODO
1765 return(0);
1766}
1767
1768/**
1769 * xmlTextReaderReadBinHex:
1770 * @reader: the xmlTextReaderPtr used
1771 * @array: a byte array to store the content.
1772 * @offset: the zero-based index into array where the method should
1773 * begin to write.
1774 * @len: the number of bytes to write.
1775 *
1776 * Reads and decodes the BinHex encoded contents of an element and
1777 * stores the result in a byte buffer.
1778 *
1779 * Returns the number of bytes written to array, or zero if the current
1780 * instance is not positioned on an element or -1 in case of error.
1781 */
1782int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001783xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1784 unsigned char *array ATTRIBUTE_UNUSED,
1785 int offset ATTRIBUTE_UNUSED,
1786 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001787 if ((reader == NULL) || (reader->ctxt == NULL))
1788 return(-1);
1789 if (reader->ctxt->wellFormed != 1)
1790 return(-1);
1791
1792 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1793 return(0);
1794 TODO
1795 return(0);
1796}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001797#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001798
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001799/************************************************************************
1800 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 * Operating on a preparsed tree *
1802 * *
1803 ************************************************************************/
1804static int
1805xmlTextReaderNextTree(xmlTextReaderPtr reader)
1806{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001807 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001808 return(-1);
1809
1810 if (reader->state == XML_TEXTREADER_END)
1811 return(0);
1812
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001813 if (reader->node == NULL) {
1814 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001815 reader->state = XML_TEXTREADER_END;
1816 return(0);
1817 }
1818
1819 reader->node = reader->doc->children;
1820 reader->state = XML_TEXTREADER_START;
1821 return(1);
1822 }
1823
1824 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1825 if (reader->node->children != 0) {
1826 reader->node = reader->node->children;
1827 reader->depth++;
1828 reader->state = XML_TEXTREADER_START;
1829 return(1);
1830 }
1831
1832 if ((reader->node->type == XML_ELEMENT_NODE) ||
1833 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1834 reader->state = XML_TEXTREADER_BACKTRACK;
1835 return(1);
1836 }
1837 }
1838
1839 if (reader->node->next != 0) {
1840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1843 }
1844
1845 if (reader->node->parent != 0) {
1846 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1847 reader->state = XML_TEXTREADER_END;
1848 return(0);
1849 }
1850
1851 reader->node = reader->node->parent;
1852 reader->depth--;
1853 reader->state = XML_TEXTREADER_BACKTRACK;
1854 return(1);
1855 }
1856
1857 reader->state = XML_TEXTREADER_END;
1858
1859 return(1);
1860}
1861
1862/**
1863 * xmlTextReaderReadTree:
1864 * @reader: the xmlTextReaderPtr used
1865 *
1866 * Moves the position of the current instance to the next node in
1867 * the stream, exposing its properties.
1868 *
1869 * Returns 1 if the node was read successfully, 0 if there is no more
1870 * nodes to read, or -1 in case of error
1871 */
1872static int
1873xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1874 if (reader->state == XML_TEXTREADER_END)
1875 return(0);
1876
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001877next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001878 if (reader->node == NULL) {
1879 if (reader->doc->children == NULL) {
1880 reader->state = XML_TEXTREADER_END;
1881 return(0);
1882 }
1883
1884 reader->node = reader->doc->children;
1885 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001886 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001887 }
1888
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001889 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1890 (reader->node->type != XML_DTD_NODE) &&
1891 (reader->node->type != XML_XINCLUDE_START) &&
1892 (reader->node->type != XML_ENTITY_REF_NODE)) {
1893 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001894 reader->node = reader->node->children;
1895 reader->depth++;
1896 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001897 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001898 }
1899
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001900 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001901 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001902 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 }
1904 }
1905
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001906 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001907 reader->node = reader->node->next;
1908 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001909 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 }
1911
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001912 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001913 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1914 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1915 reader->state = XML_TEXTREADER_END;
1916 return(0);
1917 }
1918
1919 reader->node = reader->node->parent;
1920 reader->depth--;
1921 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001922 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 }
1924
1925 reader->state = XML_TEXTREADER_END;
1926
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001927found_node:
1928 if ((reader->node->type == XML_XINCLUDE_START) ||
1929 (reader->node->type == XML_XINCLUDE_END))
1930 goto next_node;
1931
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001932 return(1);
1933}
1934
1935/**
William M. Brackb1d53162003-11-18 06:54:40 +00001936 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001937 * @reader: the xmlTextReaderPtr used
1938 *
1939 * Skip to the node following the current one in document order while
1940 * avoiding the subtree if any.
1941 * Currently implemented only for Readers built on a document
1942 *
1943 * Returns 1 if the node was read successfully, 0 if there is no more
1944 * nodes to read, or -1 in case of error
1945 */
1946int
1947xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1948 if (reader == NULL)
1949 return(-1);
1950 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00001951 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001952 return(-1);
1953 }
1954
1955 if (reader->state == XML_TEXTREADER_END)
1956 return(0);
1957
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001958 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001959 return(xmlTextReaderNextTree(reader));
1960
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001961 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001962 reader->node = reader->node->next;
1963 reader->state = XML_TEXTREADER_START;
1964 return(1);
1965 }
1966
1967 return(0);
1968}
1969
1970/************************************************************************
1971 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001972 * Constructor and destructors *
1973 * *
1974 ************************************************************************/
1975/**
1976 * xmlNewTextReader:
1977 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001978 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001979 *
1980 * Create an xmlTextReader structure fed with @input
1981 *
1982 * Returns the new xmlTextReaderPtr or NULL in case of error
1983 */
1984xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001985xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001986 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001987
1988 if (input == NULL)
1989 return(NULL);
1990 ret = xmlMalloc(sizeof(xmlTextReader));
1991 if (ret == NULL) {
1992 xmlGenericError(xmlGenericErrorContext,
1993 "xmlNewTextReader : malloc failed\n");
1994 return(NULL);
1995 }
1996 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001997 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001998 ret->entTab = NULL;
1999 ret->entMax = 0;
2000 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002001 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002002 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002003 if (ret->buffer == NULL) {
2004 xmlFree(ret);
2005 xmlGenericError(xmlGenericErrorContext,
2006 "xmlNewTextReader : malloc failed\n");
2007 return(NULL);
2008 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002009 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2010 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002011 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002012 xmlFree(ret);
2013 xmlGenericError(xmlGenericErrorContext,
2014 "xmlNewTextReader : malloc failed\n");
2015 return(NULL);
2016 }
Daniel Veillard81273902003-09-30 00:43:48 +00002017 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018 ret->startElement = ret->sax->startElement;
2019 ret->sax->startElement = xmlTextReaderStartElement;
2020 ret->endElement = ret->sax->endElement;
2021 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002022#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002023 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002024#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002025 ret->startElementNs = ret->sax->startElementNs;
2026 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2027 ret->endElementNs = ret->sax->endElementNs;
2028 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002029#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002030 } else {
2031 ret->startElementNs = NULL;
2032 ret->endElementNs = NULL;
2033 }
Daniel Veillard81273902003-09-30 00:43:48 +00002034#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002035 ret->characters = ret->sax->characters;
2036 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002037 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002038 ret->cdataBlock = ret->sax->cdataBlock;
2039 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002040
Daniel Veillard67df8092002-12-16 22:04:11 +00002041 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002042 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002043 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00002044 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002045 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002046 }
2047 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00002049 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002050 ret->base = 0;
2051 ret->cur = 4;
2052 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002053 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002054 ret->base = 0;
2055 ret->cur = 0;
2056 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002057
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002058 if (ret->ctxt == NULL) {
2059 xmlGenericError(xmlGenericErrorContext,
2060 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00002061 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002062 xmlFree(ret->sax);
2063 xmlFree(ret);
2064 return(NULL);
2065 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002066 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002067 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002068 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002069 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002070 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002071 /*
2072 * use the parser dictionnary to allocate all elements and attributes names
2073 */
2074 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002075 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002076#ifdef LIBXML_XINCLUDE_ENABLED
2077 ret->xinclude = 0;
2078#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002079#ifdef LIBXML_PATTERN_ENABLED
2080 ret->patternMax = 0;
2081 ret->patternTab = NULL;
2082#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002083 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002084}
2085
2086/**
2087 * xmlNewTextReaderFilename:
2088 * @URI: the URI of the resource to process
2089 *
2090 * Create an xmlTextReader structure fed with the resource at @URI
2091 *
2092 * Returns the new xmlTextReaderPtr or NULL in case of error
2093 */
2094xmlTextReaderPtr
2095xmlNewTextReaderFilename(const char *URI) {
2096 xmlParserInputBufferPtr input;
2097 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002098 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002099
2100 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2101 if (input == NULL)
2102 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002103 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002104 if (ret == NULL) {
2105 xmlFreeParserInputBuffer(input);
2106 return(NULL);
2107 }
2108 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002109 if (ret->ctxt->directory == NULL)
2110 directory = xmlParserGetDirectory(URI);
2111 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2112 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2113 if (directory != NULL)
2114 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115 return(ret);
2116}
2117
2118/**
2119 * xmlFreeTextReader:
2120 * @reader: the xmlTextReaderPtr
2121 *
2122 * Deallocate all the resources associated to the reader
2123 */
2124void
2125xmlFreeTextReader(xmlTextReaderPtr reader) {
2126 if (reader == NULL)
2127 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002128#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002129 if (reader->rngSchemas != NULL) {
2130 xmlRelaxNGFree(reader->rngSchemas);
2131 reader->rngSchemas = NULL;
2132 }
2133 if (reader->rngValidCtxt != NULL) {
2134 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2135 reader->rngValidCtxt = NULL;
2136 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002137 if (reader->xsdPlug != NULL) {
2138 xmlSchemaSAXUnplug(reader->xsdPlug);
2139 reader->xsdPlug = NULL;
2140 }
2141 if (reader->xsdValidCtxt != NULL) {
2142 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2143 reader->xsdValidCtxt = NULL;
2144 }
2145 if (reader->xsdSchemas != NULL) {
2146 xmlSchemaFree(reader->xsdSchemas);
2147 reader->xsdSchemas = NULL;
2148 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002149#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002150#ifdef LIBXML_XINCLUDE_ENABLED
2151 if (reader->xincctxt != NULL)
2152 xmlXIncludeFreeContext(reader->xincctxt);
2153#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002154#ifdef LIBXML_PATTERN_ENABLED
2155 if (reader->patternTab != NULL) {
2156 int i;
2157 for (i = 0;i < reader->patternNr;i++) {
2158 if (reader->patternTab[i] != NULL)
2159 xmlFreePattern(reader->patternTab[i]);
2160 }
2161 xmlFree(reader->patternTab);
2162 }
2163#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002164 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002165 if (reader->dict == reader->ctxt->dict)
2166 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002167 if (reader->ctxt->myDoc != NULL) {
2168 if (reader->preserve == 0)
2169 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2170 reader->ctxt->myDoc = NULL;
2171 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002172 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2173 (reader->ctxt->vctxt.vstateMax > 0)){
2174 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002175 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002176 reader->ctxt->vctxt.vstateMax = 0;
2177 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002178 if (reader->allocs & XML_TEXTREADER_CTXT)
2179 xmlFreeParserCtxt(reader->ctxt);
2180 }
2181 if (reader->sax != NULL)
2182 xmlFree(reader->sax);
2183 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2184 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002185 if (reader->faketext != NULL) {
2186 xmlFreeNode(reader->faketext);
2187 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002188 if (reader->buffer != NULL)
2189 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002190 if (reader->entTab != NULL)
2191 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002192 if (reader->dict != NULL)
2193 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002194 xmlFree(reader);
2195}
2196
2197/************************************************************************
2198 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002199 * Methods for XmlTextReader *
2200 * *
2201 ************************************************************************/
2202/**
2203 * xmlTextReaderClose:
2204 * @reader: the xmlTextReaderPtr used
2205 *
2206 * This method releases any resources allocated by the current instance
2207 * changes the state to Closed and close any underlying input.
2208 *
2209 * Returns 0 or -1 in case of error
2210 */
2211int
2212xmlTextReaderClose(xmlTextReaderPtr reader) {
2213 if (reader == NULL)
2214 return(-1);
2215 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002216 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002217 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2218 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002219 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002220 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002221 if (reader->preserve == 0)
2222 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002223 reader->ctxt->myDoc = NULL;
2224 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002225 }
2226 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2227 xmlFreeParserInputBuffer(reader->input);
2228 reader->allocs -= XML_TEXTREADER_INPUT;
2229 }
2230 return(0);
2231}
2232
2233/**
2234 * xmlTextReaderGetAttributeNo:
2235 * @reader: the xmlTextReaderPtr used
2236 * @no: the zero-based index of the attribute relative to the containing element
2237 *
2238 * Provides the value of the attribute with the specified index relative
2239 * to the containing element.
2240 *
2241 * Returns a string containing the value of the specified attribute, or NULL
2242 * in case of error. The string must be deallocated by the caller.
2243 */
2244xmlChar *
2245xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2246 xmlChar *ret;
2247 int i;
2248 xmlAttrPtr cur;
2249 xmlNsPtr ns;
2250
2251 if (reader == NULL)
2252 return(NULL);
2253 if (reader->node == NULL)
2254 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002255 if (reader->curnode != NULL)
2256 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002257 /* TODO: handle the xmlDecl */
2258 if (reader->node->type != XML_ELEMENT_NODE)
2259 return(NULL);
2260
2261 ns = reader->node->nsDef;
2262 for (i = 0;(i < no) && (ns != NULL);i++) {
2263 ns = ns->next;
2264 }
2265 if (ns != NULL)
2266 return(xmlStrdup(ns->href));
2267
2268 cur = reader->node->properties;
2269 if (cur == NULL)
2270 return(NULL);
2271 for (;i < no;i++) {
2272 cur = cur->next;
2273 if (cur == NULL)
2274 return(NULL);
2275 }
2276 /* TODO walk the DTD if present */
2277
2278 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2279 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2280 return(ret);
2281}
2282
2283/**
2284 * xmlTextReaderGetAttribute:
2285 * @reader: the xmlTextReaderPtr used
2286 * @name: the qualified name of the attribute.
2287 *
2288 * Provides the value of the attribute with the specified qualified name.
2289 *
2290 * Returns a string containing the value of the specified attribute, or NULL
2291 * in case of error. The string must be deallocated by the caller.
2292 */
2293xmlChar *
2294xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2295 xmlChar *prefix = NULL;
2296 xmlChar *localname;
2297 xmlNsPtr ns;
2298 xmlChar *ret = NULL;
2299
2300 if ((reader == NULL) || (name == NULL))
2301 return(NULL);
2302 if (reader->node == NULL)
2303 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002304 if (reader->curnode != NULL)
2305 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002306
2307 /* TODO: handle the xmlDecl */
2308 if (reader->node->type != XML_ELEMENT_NODE)
2309 return(NULL);
2310
2311 localname = xmlSplitQName2(name, &prefix);
2312 if (localname == NULL)
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002313 return(xmlGetNoNsProp(reader->node, name));
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002314
2315 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2316 if (ns != NULL)
2317 ret = xmlGetNsProp(reader->node, localname, ns->href);
2318
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002319 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002320 if (prefix != NULL)
2321 xmlFree(prefix);
2322 return(ret);
2323}
2324
2325
2326/**
2327 * xmlTextReaderGetAttributeNs:
2328 * @reader: the xmlTextReaderPtr used
2329 * @localName: the local name of the attribute.
2330 * @namespaceURI: the namespace URI of the attribute.
2331 *
2332 * Provides the value of the specified attribute
2333 *
2334 * Returns a string containing the value of the specified attribute, or NULL
2335 * in case of error. The string must be deallocated by the caller.
2336 */
2337xmlChar *
2338xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2339 const xmlChar *namespaceURI) {
2340 if ((reader == NULL) || (localName == NULL))
2341 return(NULL);
2342 if (reader->node == NULL)
2343 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002344 if (reader->curnode != NULL)
2345 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002346
2347 /* TODO: handle the xmlDecl */
2348 if (reader->node->type != XML_ELEMENT_NODE)
2349 return(NULL);
2350
2351 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2352}
2353
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002354/**
2355 * xmlTextReaderGetRemainder:
2356 * @reader: the xmlTextReaderPtr used
2357 *
2358 * Method to get the remainder of the buffered XML. this method stops the
2359 * parser, set its state to End Of File and return the input stream with
2360 * what is left that the parser did not use.
2361 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002362 * The implementation is not good, the parser certainly procgressed past
2363 * what's left in reader->input, and there is an allocation problem. Best
2364 * would be to rewrite it differently.
2365 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002366 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2367 * in case of error.
2368 */
2369xmlParserInputBufferPtr
2370xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2371 xmlParserInputBufferPtr ret = NULL;
2372
2373 if (reader == NULL)
2374 return(NULL);
2375 if (reader->node == NULL)
2376 return(NULL);
2377
2378 reader->node = NULL;
2379 reader->curnode = NULL;
2380 reader->mode = XML_TEXTREADER_MODE_EOF;
2381 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002382 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002383 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002384 if (reader->preserve == 0)
2385 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002386 reader->ctxt->myDoc = NULL;
2387 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002388 }
2389 if (reader->allocs & XML_TEXTREADER_INPUT) {
2390 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002391 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002392 reader->allocs -= XML_TEXTREADER_INPUT;
2393 } else {
2394 /*
2395 * Hum, one may need to duplicate the data structure because
2396 * without reference counting the input may be freed twice:
2397 * - by the layer which allocated it.
2398 * - by the layer to which would have been returned to.
2399 */
2400 TODO
2401 return(NULL);
2402 }
2403 return(ret);
2404}
2405
2406/**
2407 * xmlTextReaderLookupNamespace:
2408 * @reader: the xmlTextReaderPtr used
2409 * @prefix: the prefix whose namespace URI is to be resolved. To return
2410 * the default namespace, specify NULL
2411 *
2412 * Resolves a namespace prefix in the scope of the current element.
2413 *
2414 * Returns a string containing the namespace URI to which the prefix maps
2415 * or NULL in case of error. The string must be deallocated by the caller.
2416 */
2417xmlChar *
2418xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2419 xmlNsPtr ns;
2420
2421 if (reader == NULL)
2422 return(NULL);
2423 if (reader->node == NULL)
2424 return(NULL);
2425
2426 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2427 if (ns == NULL)
2428 return(NULL);
2429 return(xmlStrdup(ns->href));
2430}
2431
2432/**
2433 * xmlTextReaderMoveToAttributeNo:
2434 * @reader: the xmlTextReaderPtr used
2435 * @no: the zero-based index of the attribute relative to the containing
2436 * element.
2437 *
2438 * Moves the position of the current instance to the attribute with
2439 * the specified index relative to the containing element.
2440 *
2441 * Returns 1 in case of success, -1 in case of error, 0 if not found
2442 */
2443int
2444xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2445 int i;
2446 xmlAttrPtr cur;
2447 xmlNsPtr ns;
2448
2449 if (reader == NULL)
2450 return(-1);
2451 if (reader->node == NULL)
2452 return(-1);
2453 /* TODO: handle the xmlDecl */
2454 if (reader->node->type != XML_ELEMENT_NODE)
2455 return(-1);
2456
2457 reader->curnode = NULL;
2458
2459 ns = reader->node->nsDef;
2460 for (i = 0;(i < no) && (ns != NULL);i++) {
2461 ns = ns->next;
2462 }
2463 if (ns != NULL) {
2464 reader->curnode = (xmlNodePtr) ns;
2465 return(1);
2466 }
2467
2468 cur = reader->node->properties;
2469 if (cur == NULL)
2470 return(0);
2471 for (;i < no;i++) {
2472 cur = cur->next;
2473 if (cur == NULL)
2474 return(0);
2475 }
2476 /* TODO walk the DTD if present */
2477
2478 reader->curnode = (xmlNodePtr) cur;
2479 return(1);
2480}
2481
2482/**
2483 * xmlTextReaderMoveToAttribute:
2484 * @reader: the xmlTextReaderPtr used
2485 * @name: the qualified name of the attribute.
2486 *
2487 * Moves the position of the current instance to the attribute with
2488 * the specified qualified name.
2489 *
2490 * Returns 1 in case of success, -1 in case of error, 0 if not found
2491 */
2492int
2493xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2494 xmlChar *prefix = NULL;
2495 xmlChar *localname;
2496 xmlNsPtr ns;
2497 xmlAttrPtr prop;
2498
2499 if ((reader == NULL) || (name == NULL))
2500 return(-1);
2501 if (reader->node == NULL)
2502 return(-1);
2503
2504 /* TODO: handle the xmlDecl */
2505 if (reader->node->type != XML_ELEMENT_NODE)
2506 return(0);
2507
2508 localname = xmlSplitQName2(name, &prefix);
2509 if (localname == NULL) {
2510 /*
2511 * Namespace default decl
2512 */
2513 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2514 ns = reader->node->nsDef;
2515 while (ns != NULL) {
2516 if (ns->prefix == NULL) {
2517 reader->curnode = (xmlNodePtr) ns;
2518 return(1);
2519 }
2520 ns = ns->next;
2521 }
2522 return(0);
2523 }
2524
2525 prop = reader->node->properties;
2526 while (prop != NULL) {
2527 /*
2528 * One need to have
2529 * - same attribute names
2530 * - and the attribute carrying that namespace
2531 */
2532 if ((xmlStrEqual(prop->name, name)) &&
2533 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2534 reader->curnode = (xmlNodePtr) prop;
2535 return(1);
2536 }
2537 prop = prop->next;
2538 }
2539 return(0);
2540 }
2541
2542 /*
2543 * Namespace default decl
2544 */
2545 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2546 ns = reader->node->nsDef;
2547 while (ns != NULL) {
2548 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2549 reader->curnode = (xmlNodePtr) ns;
2550 goto found;
2551 }
2552 ns = ns->next;
2553 }
2554 goto not_found;
2555 }
2556 prop = reader->node->properties;
2557 while (prop != NULL) {
2558 /*
2559 * One need to have
2560 * - same attribute names
2561 * - and the attribute carrying that namespace
2562 */
2563 if ((xmlStrEqual(prop->name, localname)) &&
2564 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2565 reader->curnode = (xmlNodePtr) prop;
2566 goto found;
2567 }
2568 prop = prop->next;
2569 }
2570not_found:
2571 if (localname != NULL)
2572 xmlFree(localname);
2573 if (prefix != NULL)
2574 xmlFree(prefix);
2575 return(0);
2576
2577found:
2578 if (localname != NULL)
2579 xmlFree(localname);
2580 if (prefix != NULL)
2581 xmlFree(prefix);
2582 return(1);
2583}
2584
2585/**
2586 * xmlTextReaderMoveToAttributeNs:
2587 * @reader: the xmlTextReaderPtr used
2588 * @localName: the local name of the attribute.
2589 * @namespaceURI: the namespace URI of the attribute.
2590 *
2591 * Moves the position of the current instance to the attribute with the
2592 * specified local name and namespace URI.
2593 *
2594 * Returns 1 in case of success, -1 in case of error, 0 if not found
2595 */
2596int
2597xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2598 const xmlChar *localName, const xmlChar *namespaceURI) {
2599 xmlAttrPtr prop;
2600 xmlNodePtr node;
2601
2602 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2603 return(-1);
2604 if (reader->node == NULL)
2605 return(-1);
2606 if (reader->node->type != XML_ELEMENT_NODE)
2607 return(0);
2608 node = reader->node;
2609
2610 /*
2611 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2612 * namespace name associated to "xmlns"
2613 */
2614 prop = node->properties;
2615 while (prop != NULL) {
2616 /*
2617 * One need to have
2618 * - same attribute names
2619 * - and the attribute carrying that namespace
2620 */
2621 if (xmlStrEqual(prop->name, localName) &&
2622 ((prop->ns != NULL) &&
2623 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2624 reader->curnode = (xmlNodePtr) prop;
2625 return(1);
2626 }
2627 prop = prop->next;
2628 }
2629 return(0);
2630}
2631
2632/**
2633 * xmlTextReaderMoveToFirstAttribute:
2634 * @reader: the xmlTextReaderPtr used
2635 *
2636 * Moves the position of the current instance to the first attribute
2637 * associated with the current node.
2638 *
2639 * Returns 1 in case of success, -1 in case of error, 0 if not found
2640 */
2641int
2642xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2643 if (reader == NULL)
2644 return(-1);
2645 if (reader->node == NULL)
2646 return(-1);
2647 if (reader->node->type != XML_ELEMENT_NODE)
2648 return(0);
2649
2650 if (reader->node->nsDef != NULL) {
2651 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2652 return(1);
2653 }
2654 if (reader->node->properties != NULL) {
2655 reader->curnode = (xmlNodePtr) reader->node->properties;
2656 return(1);
2657 }
2658 return(0);
2659}
2660
2661/**
2662 * xmlTextReaderMoveToNextAttribute:
2663 * @reader: the xmlTextReaderPtr used
2664 *
2665 * Moves the position of the current instance to the next attribute
2666 * associated with the current node.
2667 *
2668 * Returns 1 in case of success, -1 in case of error, 0 if not found
2669 */
2670int
2671xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2672 if (reader == NULL)
2673 return(-1);
2674 if (reader->node == NULL)
2675 return(-1);
2676 if (reader->node->type != XML_ELEMENT_NODE)
2677 return(0);
2678 if (reader->curnode == NULL)
2679 return(xmlTextReaderMoveToFirstAttribute(reader));
2680
2681 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2682 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2683 if (ns->next != NULL) {
2684 reader->curnode = (xmlNodePtr) ns->next;
2685 return(1);
2686 }
2687 if (reader->node->properties != NULL) {
2688 reader->curnode = (xmlNodePtr) reader->node->properties;
2689 return(1);
2690 }
2691 return(0);
2692 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2693 (reader->curnode->next != NULL)) {
2694 reader->curnode = reader->curnode->next;
2695 return(1);
2696 }
2697 return(0);
2698}
2699
2700/**
2701 * xmlTextReaderMoveToElement:
2702 * @reader: the xmlTextReaderPtr used
2703 *
2704 * Moves the position of the current instance to the node that
2705 * contains the current Attribute node.
2706 *
2707 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2708 */
2709int
2710xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2711 if (reader == NULL)
2712 return(-1);
2713 if (reader->node == NULL)
2714 return(-1);
2715 if (reader->node->type != XML_ELEMENT_NODE)
2716 return(0);
2717 if (reader->curnode != NULL) {
2718 reader->curnode = NULL;
2719 return(1);
2720 }
2721 return(0);
2722}
2723
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002724/**
2725 * xmlTextReaderReadAttributeValue:
2726 * @reader: the xmlTextReaderPtr used
2727 *
2728 * Parses an attribute value into one or more Text and EntityReference nodes.
2729 *
2730 * Returns 1 in case of success, 0 if the reader was not positionned on an
2731 * ttribute node or all the attribute values have been read, or -1
2732 * in case of error.
2733 */
2734int
2735xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2736 if (reader == NULL)
2737 return(-1);
2738 if (reader->node == NULL)
2739 return(-1);
2740 if (reader->curnode == NULL)
2741 return(0);
2742 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2743 if (reader->curnode->children == NULL)
2744 return(0);
2745 reader->curnode = reader->curnode->children;
2746 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2747 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2748
2749 if (reader->faketext == NULL) {
2750 reader->faketext = xmlNewDocText(reader->node->doc,
2751 ns->href);
2752 } else {
2753 if (reader->faketext->content != NULL)
2754 xmlFree(reader->faketext->content);
2755 reader->faketext->content = xmlStrdup(ns->href);
2756 }
2757 reader->curnode = reader->faketext;
2758 } else {
2759 if (reader->curnode->next == NULL)
2760 return(0);
2761 reader->curnode = reader->curnode->next;
2762 }
2763 return(1);
2764}
2765
Daniel Veillarde2811272004-10-19 09:04:23 +00002766/**
2767 * xmlTextReaderConstEncoding:
2768 * @reader: the xmlTextReaderPtr used
2769 *
2770 * Determine the encoding of the document being read.
2771 *
2772 * Returns a string containing the encoding of the document or NULL in
2773 * case of error. The string is deallocated with the reader.
2774 */
2775const xmlChar *
2776xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2777 xmlDocPtr doc = NULL;
2778 if (reader == NULL)
2779 return(NULL);
2780 if (reader->doc != NULL)
2781 doc = reader->doc;
2782 else if (reader->ctxt != NULL)
2783 doc = reader->ctxt->myDoc;
2784 if (doc == NULL)
2785 return(NULL);
2786
2787 if (doc->encoding == NULL)
2788 return(NULL);
2789 else
2790 return(CONSTSTR(doc->encoding));
2791}
2792
2793
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002794/************************************************************************
2795 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002796 * Acces API to the current node *
2797 * *
2798 ************************************************************************/
2799/**
2800 * xmlTextReaderAttributeCount:
2801 * @reader: the xmlTextReaderPtr used
2802 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002803 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002804 *
2805 * Returns 0 i no attributes, -1 in case of error or the attribute count
2806 */
2807int
2808xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2809 int ret;
2810 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002811 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002812 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002813
2814 if (reader == NULL)
2815 return(-1);
2816 if (reader->node == NULL)
2817 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002818
2819 if (reader->curnode != NULL)
2820 node = reader->curnode;
2821 else
2822 node = reader->node;
2823
2824 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002825 return(0);
2826 if ((reader->state == XML_TEXTREADER_END) ||
2827 (reader->state == XML_TEXTREADER_BACKTRACK))
2828 return(0);
2829 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002830 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002831 while (attr != NULL) {
2832 ret++;
2833 attr = attr->next;
2834 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002835 ns = node->nsDef;
2836 while (ns != NULL) {
2837 ret++;
2838 ns = ns->next;
2839 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002840 return(ret);
2841}
2842
2843/**
2844 * xmlTextReaderNodeType:
2845 * @reader: the xmlTextReaderPtr used
2846 *
2847 * Get the node type of the current node
2848 * Reference:
2849 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2850 *
2851 * Returns the xmlNodeType of the current node or -1 in case of error
2852 */
2853int
2854xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002855 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002856
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002857 if (reader == NULL)
2858 return(-1);
2859 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002860 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002861 if (reader->curnode != NULL)
2862 node = reader->curnode;
2863 else
2864 node = reader->node;
2865 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002866 case XML_ELEMENT_NODE:
2867 if ((reader->state == XML_TEXTREADER_END) ||
2868 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002869 return(XML_READER_TYPE_END_ELEMENT);
2870 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002871 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002872 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002873 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002874 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002875 if (xmlIsBlankNode(reader->node)) {
2876 if (xmlNodeGetSpacePreserve(reader->node))
2877 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2878 else
2879 return(XML_READER_TYPE_WHITESPACE);
2880 } else {
2881 return(XML_READER_TYPE_TEXT);
2882 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002883 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002884 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002885 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002886 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002887 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002888 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002889 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002890 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002891 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002892 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002893 case XML_DOCUMENT_NODE:
2894 case XML_HTML_DOCUMENT_NODE:
2895#ifdef LIBXML_DOCB_ENABLED
2896 case XML_DOCB_DOCUMENT_NODE:
2897#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002898 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002899 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002900 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002901 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002902 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002903 case XML_DOCUMENT_TYPE_NODE:
2904 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002905 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002906
2907 case XML_ELEMENT_DECL:
2908 case XML_ATTRIBUTE_DECL:
2909 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002910 case XML_XINCLUDE_START:
2911 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002912 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002913 }
2914 return(-1);
2915}
2916
2917/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002918 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919 * @reader: the xmlTextReaderPtr used
2920 *
2921 * Check if the current node is empty
2922 *
2923 * Returns 1 if empty, 0 if not and -1 in case of error
2924 */
2925int
2926xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2927 if ((reader == NULL) || (reader->node == NULL))
2928 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002929 if (reader->node->type != XML_ELEMENT_NODE)
2930 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002931 if (reader->curnode != NULL)
2932 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002933 if (reader->node->children != NULL)
2934 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002935 if (reader->state == XML_TEXTREADER_END)
2936 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002937 if (reader->doc != NULL)
2938 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002939#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002940 if (reader->in_xinclude > 0)
2941 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002942#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002943 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002944}
2945
2946/**
2947 * xmlTextReaderLocalName:
2948 * @reader: the xmlTextReaderPtr used
2949 *
2950 * The local name of the node.
2951 *
2952 * Returns the local name or NULL if not available
2953 */
2954xmlChar *
2955xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002956 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002957 if ((reader == NULL) || (reader->node == NULL))
2958 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002959 if (reader->curnode != NULL)
2960 node = reader->curnode;
2961 else
2962 node = reader->node;
2963 if (node->type == XML_NAMESPACE_DECL) {
2964 xmlNsPtr ns = (xmlNsPtr) node;
2965 if (ns->prefix == NULL)
2966 return(xmlStrdup(BAD_CAST "xmlns"));
2967 else
2968 return(xmlStrdup(ns->prefix));
2969 }
2970 if ((node->type != XML_ELEMENT_NODE) &&
2971 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002972 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002973 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002974}
2975
2976/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002977 * xmlTextReaderConstLocalName:
2978 * @reader: the xmlTextReaderPtr used
2979 *
2980 * The local name of the node.
2981 *
2982 * Returns the local name or NULL if not available, the
2983 * string will be deallocated with the reader.
2984 */
2985const xmlChar *
2986xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2987 xmlNodePtr node;
2988 if ((reader == NULL) || (reader->node == NULL))
2989 return(NULL);
2990 if (reader->curnode != NULL)
2991 node = reader->curnode;
2992 else
2993 node = reader->node;
2994 if (node->type == XML_NAMESPACE_DECL) {
2995 xmlNsPtr ns = (xmlNsPtr) node;
2996 if (ns->prefix == NULL)
2997 return(CONSTSTR(BAD_CAST "xmlns"));
2998 else
2999 return(ns->prefix);
3000 }
3001 if ((node->type != XML_ELEMENT_NODE) &&
3002 (node->type != XML_ATTRIBUTE_NODE))
3003 return(xmlTextReaderConstName(reader));
3004 return(node->name);
3005}
3006
3007/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003008 * xmlTextReaderName:
3009 * @reader: the xmlTextReaderPtr used
3010 *
3011 * The qualified name of the node, equal to Prefix :LocalName.
3012 *
3013 * Returns the local name or NULL if not available
3014 */
3015xmlChar *
3016xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003017 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003018 xmlChar *ret;
3019
3020 if ((reader == NULL) || (reader->node == NULL))
3021 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003022 if (reader->curnode != NULL)
3023 node = reader->curnode;
3024 else
3025 node = reader->node;
3026 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003027 case XML_ELEMENT_NODE:
3028 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003029 if ((node->ns == NULL) ||
3030 (node->ns->prefix == NULL))
3031 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003032
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003033 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003034 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003035 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003036 return(ret);
3037 case XML_TEXT_NODE:
3038 return(xmlStrdup(BAD_CAST "#text"));
3039 case XML_CDATA_SECTION_NODE:
3040 return(xmlStrdup(BAD_CAST "#cdata-section"));
3041 case XML_ENTITY_NODE:
3042 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003043 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003044 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003045 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003046 case XML_COMMENT_NODE:
3047 return(xmlStrdup(BAD_CAST "#comment"));
3048 case XML_DOCUMENT_NODE:
3049 case XML_HTML_DOCUMENT_NODE:
3050#ifdef LIBXML_DOCB_ENABLED
3051 case XML_DOCB_DOCUMENT_NODE:
3052#endif
3053 return(xmlStrdup(BAD_CAST "#document"));
3054 case XML_DOCUMENT_FRAG_NODE:
3055 return(xmlStrdup(BAD_CAST "#document-fragment"));
3056 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003057 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003058 case XML_DOCUMENT_TYPE_NODE:
3059 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003060 return(xmlStrdup(node->name));
3061 case XML_NAMESPACE_DECL: {
3062 xmlNsPtr ns = (xmlNsPtr) node;
3063
3064 ret = xmlStrdup(BAD_CAST "xmlns");
3065 if (ns->prefix == NULL)
3066 return(ret);
3067 ret = xmlStrcat(ret, BAD_CAST ":");
3068 ret = xmlStrcat(ret, ns->prefix);
3069 return(ret);
3070 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003071
3072 case XML_ELEMENT_DECL:
3073 case XML_ATTRIBUTE_DECL:
3074 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003075 case XML_XINCLUDE_START:
3076 case XML_XINCLUDE_END:
3077 return(NULL);
3078 }
3079 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003080}
3081
3082/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003083 * xmlTextReaderConstName:
3084 * @reader: the xmlTextReaderPtr used
3085 *
3086 * The qualified name of the node, equal to Prefix :LocalName.
3087 *
3088 * Returns the local name or NULL if not available, the string is
3089 * deallocated with the reader.
3090 */
3091const xmlChar *
3092xmlTextReaderConstName(xmlTextReaderPtr reader) {
3093 xmlNodePtr node;
3094
3095 if ((reader == NULL) || (reader->node == NULL))
3096 return(NULL);
3097 if (reader->curnode != NULL)
3098 node = reader->curnode;
3099 else
3100 node = reader->node;
3101 switch (node->type) {
3102 case XML_ELEMENT_NODE:
3103 case XML_ATTRIBUTE_NODE:
3104 if ((node->ns == NULL) ||
3105 (node->ns->prefix == NULL))
3106 return(node->name);
3107 return(CONSTQSTR(node->ns->prefix, node->name));
3108 case XML_TEXT_NODE:
3109 return(CONSTSTR(BAD_CAST "#text"));
3110 case XML_CDATA_SECTION_NODE:
3111 return(CONSTSTR(BAD_CAST "#cdata-section"));
3112 case XML_ENTITY_NODE:
3113 case XML_ENTITY_REF_NODE:
3114 return(CONSTSTR(node->name));
3115 case XML_PI_NODE:
3116 return(CONSTSTR(node->name));
3117 case XML_COMMENT_NODE:
3118 return(CONSTSTR(BAD_CAST "#comment"));
3119 case XML_DOCUMENT_NODE:
3120 case XML_HTML_DOCUMENT_NODE:
3121#ifdef LIBXML_DOCB_ENABLED
3122 case XML_DOCB_DOCUMENT_NODE:
3123#endif
3124 return(CONSTSTR(BAD_CAST "#document"));
3125 case XML_DOCUMENT_FRAG_NODE:
3126 return(CONSTSTR(BAD_CAST "#document-fragment"));
3127 case XML_NOTATION_NODE:
3128 return(CONSTSTR(node->name));
3129 case XML_DOCUMENT_TYPE_NODE:
3130 case XML_DTD_NODE:
3131 return(CONSTSTR(node->name));
3132 case XML_NAMESPACE_DECL: {
3133 xmlNsPtr ns = (xmlNsPtr) node;
3134
3135 if (ns->prefix == NULL)
3136 return(CONSTSTR(BAD_CAST "xmlns"));
3137 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3138 }
3139
3140 case XML_ELEMENT_DECL:
3141 case XML_ATTRIBUTE_DECL:
3142 case XML_ENTITY_DECL:
3143 case XML_XINCLUDE_START:
3144 case XML_XINCLUDE_END:
3145 return(NULL);
3146 }
3147 return(NULL);
3148}
3149
3150/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003151 * xmlTextReaderPrefix:
3152 * @reader: the xmlTextReaderPtr used
3153 *
3154 * A shorthand reference to the namespace associated with the node.
3155 *
3156 * Returns the prefix or NULL if not available
3157 */
3158xmlChar *
3159xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003160 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003161 if ((reader == NULL) || (reader->node == NULL))
3162 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003163 if (reader->curnode != NULL)
3164 node = reader->curnode;
3165 else
3166 node = reader->node;
3167 if (node->type == XML_NAMESPACE_DECL) {
3168 xmlNsPtr ns = (xmlNsPtr) node;
3169 if (ns->prefix == NULL)
3170 return(NULL);
3171 return(xmlStrdup(BAD_CAST "xmlns"));
3172 }
3173 if ((node->type != XML_ELEMENT_NODE) &&
3174 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003175 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003176 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003177 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003178 return(NULL);
3179}
3180
3181/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003182 * xmlTextReaderConstPrefix:
3183 * @reader: the xmlTextReaderPtr used
3184 *
3185 * A shorthand reference to the namespace associated with the node.
3186 *
3187 * Returns the prefix or NULL if not available, the string is deallocated
3188 * with the reader.
3189 */
3190const xmlChar *
3191xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3192 xmlNodePtr node;
3193 if ((reader == NULL) || (reader->node == NULL))
3194 return(NULL);
3195 if (reader->curnode != NULL)
3196 node = reader->curnode;
3197 else
3198 node = reader->node;
3199 if (node->type == XML_NAMESPACE_DECL) {
3200 xmlNsPtr ns = (xmlNsPtr) node;
3201 if (ns->prefix == NULL)
3202 return(NULL);
3203 return(CONSTSTR(BAD_CAST "xmlns"));
3204 }
3205 if ((node->type != XML_ELEMENT_NODE) &&
3206 (node->type != XML_ATTRIBUTE_NODE))
3207 return(NULL);
3208 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3209 return(CONSTSTR(node->ns->prefix));
3210 return(NULL);
3211}
3212
3213/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003214 * xmlTextReaderNamespaceUri:
3215 * @reader: the xmlTextReaderPtr used
3216 *
3217 * The URI defining the namespace associated with the node.
3218 *
3219 * Returns the namespace URI or NULL if not available
3220 */
3221xmlChar *
3222xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003223 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003224 if ((reader == NULL) || (reader->node == NULL))
3225 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003226 if (reader->curnode != NULL)
3227 node = reader->curnode;
3228 else
3229 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003230 if (node->type == XML_NAMESPACE_DECL)
3231 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003232 if ((node->type != XML_ELEMENT_NODE) &&
3233 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003234 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003235 if (node->ns != NULL)
3236 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003237 return(NULL);
3238}
3239
3240/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003241 * xmlTextReaderConstNamespaceUri:
3242 * @reader: the xmlTextReaderPtr used
3243 *
3244 * The URI defining the namespace associated with the node.
3245 *
3246 * Returns the namespace URI or NULL if not available, the string
3247 * will be deallocated with the reader
3248 */
3249const xmlChar *
3250xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3251 xmlNodePtr node;
3252 if ((reader == NULL) || (reader->node == NULL))
3253 return(NULL);
3254 if (reader->curnode != NULL)
3255 node = reader->curnode;
3256 else
3257 node = reader->node;
3258 if (node->type == XML_NAMESPACE_DECL)
3259 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3260 if ((node->type != XML_ELEMENT_NODE) &&
3261 (node->type != XML_ATTRIBUTE_NODE))
3262 return(NULL);
3263 if (node->ns != NULL)
3264 return(CONSTSTR(node->ns->href));
3265 return(NULL);
3266}
3267
3268/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003269 * xmlTextReaderBaseUri:
3270 * @reader: the xmlTextReaderPtr used
3271 *
3272 * The base URI of the node.
3273 *
3274 * Returns the base URI or NULL if not available
3275 */
3276xmlChar *
3277xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3278 if ((reader == NULL) || (reader->node == NULL))
3279 return(NULL);
3280 return(xmlNodeGetBase(NULL, reader->node));
3281}
3282
3283/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003284 * xmlTextReaderConstBaseUri:
3285 * @reader: the xmlTextReaderPtr used
3286 *
3287 * The base URI of the node.
3288 *
3289 * Returns the base URI or NULL if not available, the string
3290 * will be deallocated with the reader
3291 */
3292const xmlChar *
3293xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3294 xmlChar *tmp;
3295 const xmlChar *ret;
3296
3297 if ((reader == NULL) || (reader->node == NULL))
3298 return(NULL);
3299 tmp = xmlNodeGetBase(NULL, reader->node);
3300 if (tmp == NULL)
3301 return(NULL);
3302 ret = CONSTSTR(tmp);
3303 xmlFree(tmp);
3304 return(ret);
3305}
3306
3307/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003308 * xmlTextReaderDepth:
3309 * @reader: the xmlTextReaderPtr used
3310 *
3311 * The depth of the node in the tree.
3312 *
3313 * Returns the depth or -1 in case of error
3314 */
3315int
3316xmlTextReaderDepth(xmlTextReaderPtr reader) {
3317 if (reader == NULL)
3318 return(-1);
3319 if (reader->node == NULL)
3320 return(0);
3321
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003322 if (reader->curnode != NULL) {
3323 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3324 (reader->curnode->type == XML_NAMESPACE_DECL))
3325 return(reader->depth + 1);
3326 return(reader->depth + 2);
3327 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003328 return(reader->depth);
3329}
3330
3331/**
3332 * xmlTextReaderHasAttributes:
3333 * @reader: the xmlTextReaderPtr used
3334 *
3335 * Whether the node has attributes.
3336 *
3337 * Returns 1 if true, 0 if false, and -1 in case or error
3338 */
3339int
3340xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003341 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003342 if (reader == NULL)
3343 return(-1);
3344 if (reader->node == NULL)
3345 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003346 if (reader->curnode != NULL)
3347 node = reader->curnode;
3348 else
3349 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003350
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003351 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003352 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003353 return(1);
3354 /* TODO: handle the xmlDecl */
3355 return(0);
3356}
3357
3358/**
3359 * xmlTextReaderHasValue:
3360 * @reader: the xmlTextReaderPtr used
3361 *
3362 * Whether the node can have a text value.
3363 *
3364 * Returns 1 if true, 0 if false, and -1 in case or error
3365 */
3366int
3367xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003368 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003369 if (reader == NULL)
3370 return(-1);
3371 if (reader->node == NULL)
3372 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003373 if (reader->curnode != NULL)
3374 node = reader->curnode;
3375 else
3376 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003377
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003378 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003379 case XML_ATTRIBUTE_NODE:
3380 case XML_TEXT_NODE:
3381 case XML_CDATA_SECTION_NODE:
3382 case XML_PI_NODE:
3383 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003384 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003385 return(1);
3386 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003387 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003388 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003389 return(0);
3390}
3391
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003392/**
3393 * xmlTextReaderValue:
3394 * @reader: the xmlTextReaderPtr used
3395 *
3396 * Provides the text value of the node if present
3397 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003398 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003399 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003400 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003401xmlChar *
3402xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003403 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003404 if (reader == NULL)
3405 return(NULL);
3406 if (reader->node == NULL)
3407 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003408 if (reader->curnode != NULL)
3409 node = reader->curnode;
3410 else
3411 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003412
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003413 switch (node->type) {
3414 case XML_NAMESPACE_DECL:
3415 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003416 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003417 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003418
3419 if (attr->parent != NULL)
3420 return (xmlNodeListGetString
3421 (attr->parent->doc, attr->children, 1));
3422 else
3423 return (xmlNodeListGetString(NULL, attr->children, 1));
3424 break;
3425 }
3426 case XML_TEXT_NODE:
3427 case XML_CDATA_SECTION_NODE:
3428 case XML_PI_NODE:
3429 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003430 if (node->content != NULL)
3431 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003432 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003433 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003434 }
3435 return(NULL);
3436}
3437
3438/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003439 * xmlTextReaderConstValue:
3440 * @reader: the xmlTextReaderPtr used
3441 *
3442 * Provides the text value of the node if present
3443 *
3444 * Returns the string or NULL if not available. The result will be
3445 * deallocated on the next Read() operation.
3446 */
3447const xmlChar *
3448xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3449 xmlNodePtr node;
3450 if (reader == NULL)
3451 return(NULL);
3452 if (reader->node == NULL)
3453 return(NULL);
3454 if (reader->curnode != NULL)
3455 node = reader->curnode;
3456 else
3457 node = reader->node;
3458
3459 switch (node->type) {
3460 case XML_NAMESPACE_DECL:
3461 return(((xmlNsPtr) node)->href);
3462 case XML_ATTRIBUTE_NODE:{
3463 xmlAttrPtr attr = (xmlAttrPtr) node;
3464
3465 if ((attr->children != NULL) &&
3466 (attr->children->type == XML_TEXT_NODE) &&
3467 (attr->children->next == NULL))
3468 return(attr->children->content);
3469 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003470 if (reader->buffer == NULL)
3471 reader->buffer = xmlBufferCreateSize(100);
3472 if (reader->buffer == NULL) {
3473 xmlGenericError(xmlGenericErrorContext,
3474 "xmlTextReaderSetup : malloc failed\n");
3475 return (NULL);
3476 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003477 reader->buffer->use = 0;
3478 xmlNodeBufGetContent(reader->buffer, node);
3479 return(reader->buffer->content);
3480 }
3481 break;
3482 }
3483 case XML_TEXT_NODE:
3484 case XML_CDATA_SECTION_NODE:
3485 case XML_PI_NODE:
3486 case XML_COMMENT_NODE:
3487 return(node->content);
3488 default:
3489 break;
3490 }
3491 return(NULL);
3492}
3493
3494/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003495 * xmlTextReaderIsDefault:
3496 * @reader: the xmlTextReaderPtr used
3497 *
3498 * Whether an Attribute node was generated from the default value
3499 * defined in the DTD or schema.
3500 *
3501 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3502 */
3503int
3504xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3505 if (reader == NULL)
3506 return(-1);
3507 return(0);
3508}
3509
3510/**
3511 * xmlTextReaderQuoteChar:
3512 * @reader: the xmlTextReaderPtr used
3513 *
3514 * The quotation mark character used to enclose the value of an attribute.
3515 *
3516 * Returns " or ' and -1 in case of error
3517 */
3518int
3519xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3520 if (reader == NULL)
3521 return(-1);
3522 /* TODO maybe lookup the attribute value for " first */
3523 return((int) '"');
3524}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003525
3526/**
3527 * xmlTextReaderXmlLang:
3528 * @reader: the xmlTextReaderPtr used
3529 *
3530 * The xml:lang scope within which the node resides.
3531 *
3532 * Returns the xml:lang value or NULL if none exists.
3533 */
3534xmlChar *
3535xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3536 if (reader == NULL)
3537 return(NULL);
3538 if (reader->node == NULL)
3539 return(NULL);
3540 return(xmlNodeGetLang(reader->node));
3541}
3542
Daniel Veillard67df8092002-12-16 22:04:11 +00003543/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003544 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003545 * @reader: the xmlTextReaderPtr used
3546 *
3547 * The xml:lang scope within which the node resides.
3548 *
3549 * Returns the xml:lang value or NULL if none exists.
3550 */
3551const xmlChar *
3552xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3553 xmlChar *tmp;
3554 const xmlChar *ret;
3555
3556 if (reader == NULL)
3557 return(NULL);
3558 if (reader->node == NULL)
3559 return(NULL);
3560 tmp = xmlNodeGetLang(reader->node);
3561 if (tmp == NULL)
3562 return(NULL);
3563 ret = CONSTSTR(tmp);
3564 xmlFree(tmp);
3565 return(ret);
3566}
3567
3568/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003569 * xmlTextReaderConstString:
3570 * @reader: the xmlTextReaderPtr used
3571 * @str: the string to intern.
3572 *
3573 * Get an interned string from the reader, allows for example to
3574 * speedup string name comparisons
3575 *
3576 * Returns an interned copy of the string or NULL in case of error. The
3577 * string will be deallocated with the reader.
3578 */
3579const xmlChar *
3580xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3581 if (reader == NULL)
3582 return(NULL);
3583 return(CONSTSTR(str));
3584}
3585
3586/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003587 * xmlTextReaderNormalization:
3588 * @reader: the xmlTextReaderPtr used
3589 *
3590 * The value indicating whether to normalize white space and attribute values.
3591 * Since attribute value and end of line normalizations are a MUST in the XML
3592 * specification only the value true is accepted. The broken bahaviour of
3593 * accepting out of range character entities like &#0; is of course not
3594 * supported either.
3595 *
3596 * Returns 1 or -1 in case of error.
3597 */
3598int
3599xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3600 if (reader == NULL)
3601 return(-1);
3602 return(1);
3603}
3604
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003605/************************************************************************
3606 * *
3607 * Extensions to the base APIs *
3608 * *
3609 ************************************************************************/
3610
3611/**
3612 * xmlTextReaderSetParserProp:
3613 * @reader: the xmlTextReaderPtr used
3614 * @prop: the xmlParserProperties to set
3615 * @value: usually 0 or 1 to (de)activate it
3616 *
3617 * Change the parser processing behaviour by changing some of its internal
3618 * properties. Note that some properties can only be changed before any
3619 * read has been done.
3620 *
3621 * Returns 0 if the call was successful, or -1 in case of error
3622 */
3623int
3624xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3625 xmlParserProperties p = (xmlParserProperties) prop;
3626 xmlParserCtxtPtr ctxt;
3627
3628 if ((reader == NULL) || (reader->ctxt == NULL))
3629 return(-1);
3630 ctxt = reader->ctxt;
3631
3632 switch (p) {
3633 case XML_PARSER_LOADDTD:
3634 if (value != 0) {
3635 if (ctxt->loadsubset == 0) {
3636 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3637 return(-1);
3638 ctxt->loadsubset = XML_DETECT_IDS;
3639 }
3640 } else {
3641 ctxt->loadsubset = 0;
3642 }
3643 return(0);
3644 case XML_PARSER_DEFAULTATTRS:
3645 if (value != 0) {
3646 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3647 } else {
3648 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3649 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3650 }
3651 return(0);
3652 case XML_PARSER_VALIDATE:
3653 if (value != 0) {
3654 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003655 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003656 } else {
3657 ctxt->validate = 0;
3658 }
3659 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003660 case XML_PARSER_SUBST_ENTITIES:
3661 if (value != 0) {
3662 ctxt->replaceEntities = 1;
3663 } else {
3664 ctxt->replaceEntities = 0;
3665 }
3666 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003667 }
3668 return(-1);
3669}
3670
3671/**
3672 * xmlTextReaderGetParserProp:
3673 * @reader: the xmlTextReaderPtr used
3674 * @prop: the xmlParserProperties to get
3675 *
3676 * Read the parser internal property.
3677 *
3678 * Returns the value, usually 0 or 1, or -1 in case of error.
3679 */
3680int
3681xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3682 xmlParserProperties p = (xmlParserProperties) prop;
3683 xmlParserCtxtPtr ctxt;
3684
3685 if ((reader == NULL) || (reader->ctxt == NULL))
3686 return(-1);
3687 ctxt = reader->ctxt;
3688
3689 switch (p) {
3690 case XML_PARSER_LOADDTD:
3691 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3692 return(1);
3693 return(0);
3694 case XML_PARSER_DEFAULTATTRS:
3695 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3696 return(1);
3697 return(0);
3698 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003699 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003700 case XML_PARSER_SUBST_ENTITIES:
3701 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003702 }
3703 return(-1);
3704}
3705
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003706
Daniel Veillarde18fc182002-12-28 22:56:33 +00003707/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003708 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003709 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003710 *
3711 * Provide the line number of the current parsing point.
3712 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003713 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003714 */
3715int
3716xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3717{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003718 if ((reader == NULL) || (reader->ctxt == NULL) ||
3719 (reader->ctxt->input == NULL)) {
3720 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003721 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003722 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003723}
3724
3725/**
3726 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003727 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003728 *
3729 * Provide the column number of the current parsing point.
3730 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003731 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003732 */
3733int
3734xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3735{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003736 if ((reader == NULL) || (reader->ctxt == NULL) ||
3737 (reader->ctxt->input == NULL)) {
3738 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003739 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003740 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003741}
3742
3743/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003744 * xmlTextReaderCurrentNode:
3745 * @reader: the xmlTextReaderPtr used
3746 *
3747 * Hacking interface allowing to get the xmlNodePtr correponding to the
3748 * current node being accessed by the xmlTextReader. This is dangerous
3749 * because the underlying node may be destroyed on the next Reads.
3750 *
3751 * Returns the xmlNodePtr or NULL in case of error.
3752 */
3753xmlNodePtr
3754xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3755 if (reader == NULL)
3756 return(NULL);
3757
3758 if (reader->curnode != NULL)
3759 return(reader->curnode);
3760 return(reader->node);
3761}
3762
3763/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003764 * xmlTextReaderPreserve:
3765 * @reader: the xmlTextReaderPtr used
3766 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003767 * This tells the XML Reader to preserve the current node.
3768 * The caller must also use xmlTextReaderCurrentDoc() to
3769 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003770 *
3771 * Returns the xmlNodePtr or NULL in case of error.
3772 */
3773xmlNodePtr
3774xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3775 xmlNodePtr cur, parent;
3776
3777 if (reader == NULL)
3778 return(NULL);
3779
3780 if (reader->curnode != NULL)
3781 cur = reader->curnode;
3782 else
3783 cur = reader->node;
3784 if (cur == NULL)
3785 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003786
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003787 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003788 cur->extra |= NODE_IS_PRESERVED;
3789 cur->extra |= NODE_IS_SPRESERVED;
3790 }
3791 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003792
3793 parent = cur->parent;;
3794 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003795 if (parent->type == XML_ELEMENT_NODE)
3796 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003797 parent = parent->parent;
3798 }
3799 return(cur);
3800}
3801
Daniel Veillard1e906612003-12-05 14:57:46 +00003802#ifdef LIBXML_PATTERN_ENABLED
3803/**
3804 * xmlTextReaderPreservePattern:
3805 * @reader: the xmlTextReaderPtr used
3806 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003807 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003808 *
3809 * This tells the XML Reader to preserve all nodes matched by the
3810 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3811 * keep an handle on the resulting document once parsing has finished
3812 *
3813 * Returns a positive number in case of success and -1 in case of error
3814 */
3815int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003816xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3817 const xmlChar **namespaces)
3818{
Daniel Veillard1e906612003-12-05 14:57:46 +00003819 xmlPatternPtr comp;
3820
3821 if ((reader == NULL) || (pattern == NULL))
3822 return(-1);
3823
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003824 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003825 if (comp == NULL)
3826 return(-1);
3827
3828 if (reader->patternMax <= 0) {
3829 reader->patternMax = 4;
3830 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3831 sizeof(reader->patternTab[0]));
3832 if (reader->patternTab == NULL) {
3833 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3834 return (-1);
3835 }
3836 }
3837 if (reader->patternNr >= reader->patternMax) {
3838 xmlPatternPtr *tmp;
3839 reader->patternMax *= 2;
3840 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3841 reader->patternMax *
3842 sizeof(reader->patternTab[0]));
3843 if (tmp == NULL) {
3844 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3845 reader->patternMax /= 2;
3846 return (-1);
3847 }
3848 reader->patternTab = tmp;
3849 }
3850 reader->patternTab[reader->patternNr] = comp;
3851 return(reader->patternNr++);
3852}
3853#endif
3854
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003855/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003856 * xmlTextReaderCurrentDoc:
3857 * @reader: the xmlTextReaderPtr used
3858 *
3859 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003860 * current document being accessed by the xmlTextReader.
3861 * NOTE: as a result of this call, the reader will not destroy the
3862 * associated XML document and calling xmlFreeDoc() on the result
3863 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003864 *
3865 * Returns the xmlDocPtr or NULL in case of error.
3866 */
3867xmlDocPtr
3868xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003869 if (reader == NULL)
3870 return(NULL);
3871 if (reader->doc != NULL)
3872 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003873 if ((reader == NULL) || (reader->ctxt == NULL) ||
3874 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003875 return(NULL);
3876
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003877 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003878 return(reader->ctxt->myDoc);
3879}
3880
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003881#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003882
3883static char *
3884xmlTextReaderBuildMessage(const char *msg, va_list ap);
3885
Daniel Veillardffa3c742005-07-21 13:24:09 +00003886static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003887xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
3888
Daniel Veillardffa3c742005-07-21 13:24:09 +00003889static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003890xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
3891
Daniel Veillardffa3c742005-07-21 13:24:09 +00003892static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003893{
3894 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3895 char * str;
3896 va_list ap;
3897
3898 va_start(ap,msg);
3899 str = xmlTextReaderBuildMessage(msg,ap);
3900 if (!reader->errorFunc) {
3901 xmlTextReaderValidityError(ctx, "%s", str);
3902 } else {
3903 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */);
3904 }
3905 if (str != NULL)
3906 xmlFree(str);
3907 va_end(ap);
3908}
3909
Daniel Veillardffa3c742005-07-21 13:24:09 +00003910static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003911{
3912 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
3913 char * str;
3914 va_list ap;
3915
3916 va_start(ap,msg);
3917 str = xmlTextReaderBuildMessage(msg,ap);
3918 if (!reader->errorFunc) {
3919 xmlTextReaderValidityWarning(ctx, "%s", str);
3920 } else {
3921 reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */);
3922 }
3923 if (str != NULL)
3924 xmlFree(str);
3925 va_end(ap);
3926}
3927
3928static void
3929xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
3930
3931static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error)
3932{
3933 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
3934
3935 if (reader->sErrorFunc) {
3936 reader->sErrorFunc(reader->errorFuncArg, error);
3937 } else {
3938 xmlTextReaderStructuredError(reader, error);
3939 }
3940}
3941
Daniel Veillardf4e55762003-04-15 23:32:22 +00003942/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003943 * xmlTextReaderRelaxNGSetSchema:
3944 * @reader: the xmlTextReaderPtr used
3945 * @schema: a precompiled RelaxNG schema
3946 *
3947 * Use RelaxNG to validate the document as it is processed.
3948 * Activation is only possible before the first Read().
3949 * if @schema is NULL, then RelaxNG validation is desactivated.
3950 @ The @schema should not be freed until the reader is deallocated
3951 * or its use has been deactivated.
3952 *
3953 * Returns 0 in case the RelaxNG validation could be (des)activated and
3954 * -1 in case of error.
3955 */
3956int
3957xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00003958 if (reader == NULL)
3959 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003960 if (schema == NULL) {
3961 if (reader->rngSchemas != NULL) {
3962 xmlRelaxNGFree(reader->rngSchemas);
3963 reader->rngSchemas = NULL;
3964 }
3965 if (reader->rngValidCtxt != NULL) {
3966 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3967 reader->rngValidCtxt = NULL;
3968 }
3969 return(0);
3970 }
3971 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3972 return(-1);
3973 if (reader->rngSchemas != NULL) {
3974 xmlRelaxNGFree(reader->rngSchemas);
3975 reader->rngSchemas = NULL;
3976 }
3977 if (reader->rngValidCtxt != NULL) {
3978 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3979 reader->rngValidCtxt = NULL;
3980 }
3981 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3982 if (reader->rngValidCtxt == NULL)
3983 return(-1);
3984 if (reader->errorFunc != NULL) {
3985 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00003986 xmlTextReaderValidityErrorRelay,
3987 xmlTextReaderValidityWarningRelay,
3988 reader);
3989 }
3990 if (reader->sErrorFunc != NULL) {
3991 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
3992 xmlTextReaderValidityStructuredRelay,
3993 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00003994 }
3995 reader->rngValidErrors = 0;
3996 reader->rngFullNode = NULL;
3997 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3998 return(0);
3999}
4000
4001/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004002 * xmlTextReaderSetSchema:
4003 * @reader: the xmlTextReaderPtr used
4004 * @schema: a precompiled Schema schema
4005 *
4006 * Use XSD Schema to validate the document as it is processed.
4007 * Activation is only possible before the first Read().
4008 * if @schema is NULL, then Schema validation is desactivated.
4009 @ The @schema should not be freed until the reader is deallocated
4010 * or its use has been deactivated.
4011 *
4012 * Returns 0 in case the Schema validation could be (des)activated and
4013 * -1 in case of error.
4014 */
4015int
4016xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4017 if (reader == NULL)
4018 return(-1);
4019 if (schema == NULL) {
4020 if (reader->xsdPlug != NULL) {
4021 xmlSchemaSAXUnplug(reader->xsdPlug);
4022 reader->xsdPlug = NULL;
4023 }
4024 if (reader->xsdValidCtxt != NULL) {
4025 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4026 reader->xsdValidCtxt = NULL;
4027 }
4028 if (reader->xsdSchemas != NULL) {
4029 xmlSchemaFree(reader->xsdSchemas);
4030 reader->xsdSchemas = NULL;
4031 }
4032 return(0);
4033 }
4034 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4035 return(-1);
4036 if (reader->xsdPlug != NULL) {
4037 xmlSchemaSAXUnplug(reader->xsdPlug);
4038 reader->xsdPlug = NULL;
4039 }
4040 if (reader->xsdValidCtxt != NULL) {
4041 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4042 reader->xsdValidCtxt = NULL;
4043 }
4044 if (reader->xsdSchemas != NULL) {
4045 xmlSchemaFree(reader->xsdSchemas);
4046 reader->xsdSchemas = NULL;
4047 }
4048 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4049 if (reader->xsdValidCtxt == NULL) {
4050 xmlSchemaFree(reader->xsdSchemas);
4051 reader->xsdSchemas = NULL;
4052 return(-1);
4053 }
4054 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4055 &(reader->ctxt->sax),
4056 &(reader->ctxt->userData));
4057 if (reader->xsdPlug == NULL) {
4058 xmlSchemaFree(reader->xsdSchemas);
4059 reader->xsdSchemas = NULL;
4060 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4061 reader->xsdValidCtxt = NULL;
4062 return(-1);
4063 }
4064 if (reader->errorFunc != NULL) {
4065 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004066 xmlTextReaderValidityErrorRelay,
4067 xmlTextReaderValidityWarningRelay,
4068 reader);
4069 }
4070 if (reader->sErrorFunc != NULL) {
4071 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4072 xmlTextReaderValidityStructuredRelay,
4073 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004074 }
4075 reader->xsdValidErrors = 0;
4076 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4077 return(0);
4078}
4079
4080/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00004081 * xmlTextReaderRelaxNGValidate:
4082 * @reader: the xmlTextReaderPtr used
4083 * @rng: the path to a RelaxNG schema or NULL
4084 *
4085 * Use RelaxNG to validate the document as it is processed.
4086 * Activation is only possible before the first Read().
4087 * if @rng is NULL, then RelaxNG validation is desactivated.
4088 *
4089 * Returns 0 in case the RelaxNG validation could be (des)activated and
4090 * -1 in case of error.
4091 */
4092int
4093xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
4094 xmlRelaxNGParserCtxtPtr ctxt;
4095
4096 if (reader == NULL)
4097 return(-1);
4098
4099 if (rng == NULL) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004100 if (reader->rngValidCtxt != NULL) {
4101 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4102 reader->rngValidCtxt = NULL;
4103 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004104 if (reader->rngSchemas != NULL) {
4105 xmlRelaxNGFree(reader->rngSchemas);
4106 reader->rngSchemas = NULL;
4107 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004108 return(0);
4109 }
4110 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4111 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004112 if (reader->rngSchemas != NULL) {
4113 xmlRelaxNGFree(reader->rngSchemas);
4114 reader->rngSchemas = NULL;
4115 }
4116 if (reader->rngValidCtxt != NULL) {
4117 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4118 reader->rngValidCtxt = NULL;
4119 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004120 ctxt = xmlRelaxNGNewParserCtxt(rng);
4121 if (reader->errorFunc != NULL) {
4122 xmlRelaxNGSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004123 xmlTextReaderValidityErrorRelay,
4124 xmlTextReaderValidityWarningRelay,
4125 reader);
4126 }
4127 if (reader->sErrorFunc != NULL) {
4128 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4129 xmlTextReaderValidityStructuredRelay,
4130 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004131 }
4132 reader->rngSchemas = xmlRelaxNGParse(ctxt);
4133 xmlRelaxNGFreeParserCtxt(ctxt);
4134 if (reader->rngSchemas == NULL)
4135 return(-1);
4136 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004137 if (reader->rngValidCtxt == NULL) {
4138 xmlRelaxNGFree(reader->rngSchemas);
4139 reader->rngSchemas = NULL;
Daniel Veillardf4e55762003-04-15 23:32:22 +00004140 return(-1);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004141 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00004142 if (reader->errorFunc != NULL) {
4143 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004144 xmlTextReaderValidityErrorRelay,
4145 xmlTextReaderValidityWarningRelay,
4146 reader);
4147 }
4148 if (reader->sErrorFunc != NULL) {
4149 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4150 xmlTextReaderValidityStructuredRelay,
4151 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004152 }
4153 reader->rngValidErrors = 0;
4154 reader->rngFullNode = NULL;
4155 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4156 return(0);
4157}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004158
4159/**
4160 * xmlTextReaderSchemaValidate:
4161 * @reader: the xmlTextReaderPtr used
4162 * @xsd: the path to a W3C XSD schema or NULL
4163 *
4164 * Use W3C XSD schema to validate the document as it is processed.
4165 * Activation is only possible before the first Read().
4166 * if @xsd is NULL, then RelaxNG validation is desactivated.
4167 *
4168 * Returns 0 in case the schemas validation could be (des)activated and
4169 * -1 in case of error.
4170 */
4171int
4172xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) {
4173 xmlSchemaParserCtxtPtr ctxt;
4174
4175 if (reader == NULL)
4176 return(-1);
4177
4178 if (xsd == NULL) {
4179 if (reader->xsdPlug != NULL) {
4180 xmlSchemaSAXUnplug(reader->xsdPlug);
4181 reader->xsdPlug = NULL;
4182 }
4183 if (reader->xsdSchemas != NULL) {
4184 xmlSchemaFree(reader->xsdSchemas);
4185 reader->xsdSchemas = NULL;
4186 }
4187 if (reader->xsdValidCtxt != NULL) {
4188 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4189 reader->xsdValidCtxt = NULL;
4190 }
4191 return(0);
4192 }
4193 if ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4194 (reader->ctxt == NULL))
4195 return(-1);
4196 if (reader->xsdPlug != NULL) {
4197 xmlSchemaSAXUnplug(reader->xsdPlug);
4198 reader->xsdPlug = NULL;
4199 }
4200 if (reader->xsdValidCtxt != NULL) {
4201 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4202 reader->xsdValidCtxt = NULL;
4203 }
4204 if (reader->xsdSchemas != NULL) {
4205 xmlSchemaFree(reader->xsdSchemas);
4206 reader->xsdSchemas = NULL;
4207 }
4208 ctxt = xmlSchemaNewParserCtxt(xsd);
4209 if (reader->errorFunc != NULL) {
4210 xmlSchemaSetParserErrors(ctxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004211 xmlTextReaderValidityErrorRelay,
4212 xmlTextReaderValidityWarningRelay,
4213 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004214 }
4215 reader->xsdSchemas = xmlSchemaParse(ctxt);
4216 xmlSchemaFreeParserCtxt(ctxt);
4217 if (reader->xsdSchemas == NULL)
4218 return(-1);
4219 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4220 if (reader->xsdValidCtxt == NULL) {
4221 xmlSchemaFree(reader->xsdSchemas);
4222 reader->xsdSchemas = NULL;
4223 return(-1);
4224 }
4225 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4226 &(reader->ctxt->sax),
4227 &(reader->ctxt->userData));
4228 if (reader->xsdPlug == NULL) {
4229 xmlSchemaFree(reader->xsdSchemas);
4230 reader->xsdSchemas = NULL;
4231 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4232 reader->xsdValidCtxt = NULL;
4233 return(-1);
4234 }
4235 if (reader->errorFunc != NULL) {
4236 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004237 xmlTextReaderValidityErrorRelay,
4238 xmlTextReaderValidityWarningRelay,
4239 reader);
4240 }
4241 if (reader->sErrorFunc != NULL) {
4242 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4243 xmlTextReaderValidityStructuredRelay,
4244 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004245 }
4246 reader->xsdValidErrors = 0;
4247 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4248 return(0);
4249}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004250#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004251
Daniel Veillarde2811272004-10-19 09:04:23 +00004252/**
4253 * xmlTextReaderIsNamespaceDecl:
4254 * @reader: the xmlTextReaderPtr used
4255 *
4256 * Determine whether the current node is a namespace declaration
4257 * rather than a regular attribute.
4258 *
4259 * Returns 1 if the current node is a namespace declaration, 0 if it
4260 * is a regular attribute or other type of node, or -1 in case of
4261 * error.
4262 */
4263int
4264xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4265 xmlNodePtr node;
4266 if (reader == NULL)
4267 return(-1);
4268 if (reader->node == NULL)
4269 return(-1);
4270 if (reader->curnode != NULL)
4271 node = reader->curnode;
4272 else
4273 node = reader->node;
4274
4275 if (XML_NAMESPACE_DECL == node->type)
4276 return(1);
4277 else
4278 return(0);
4279}
4280
4281/**
4282 * xmlTextReaderConstXmlVersion:
4283 * @reader: the xmlTextReaderPtr used
4284 *
4285 * Determine the XML version of the document being read.
4286 *
4287 * Returns a string containing the XML version of the document or NULL
4288 * in case of error. The string is deallocated with the reader.
4289 */
4290const xmlChar *
4291xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4292 xmlDocPtr doc = NULL;
4293 if (reader == NULL)
4294 return(NULL);
4295 if (reader->doc != NULL)
4296 doc = reader->doc;
4297 else if (reader->ctxt != NULL)
4298 doc = reader->ctxt->myDoc;
4299 if (doc == NULL)
4300 return(NULL);
4301
4302 if (doc->version == NULL)
4303 return(NULL);
4304 else
4305 return(CONSTSTR(doc->version));
4306}
4307
4308/**
4309 * xmlTextReaderStandalone:
4310 * @reader: the xmlTextReaderPtr used
4311 *
4312 * Determine the standalone status of the document being read.
4313 *
4314 * Returns 1 if the document was declared to be standalone, 0 if it
4315 * was declared to be not standalone, or -1 if the document did not
4316 * specify its standalone status or in case of error.
4317 */
4318int
4319xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4320 xmlDocPtr doc = NULL;
4321 if (reader == NULL)
4322 return(-1);
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(-1);
4329
4330 return(doc->standalone);
4331}
4332
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004333/************************************************************************
4334 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004335 * Error Handling Extensions *
4336 * *
4337 ************************************************************************/
4338
4339/* helper to build a xmlMalloc'ed string from a format and va_list */
4340static char *
4341xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4342 int size;
4343 int chars;
4344 char *larger;
4345 char *str;
4346
Daniel Veillard3c908dc2003-04-19 00:07:51 +00004347 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00004348 if (str == NULL) {
4349 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4350 return NULL;
4351 }
4352
4353 size = 150;
4354
4355 while (1) {
4356 chars = vsnprintf(str, size, msg, ap);
4357 if ((chars > -1) && (chars < size))
4358 break;
4359 if (chars > -1)
4360 size += chars + 1;
4361 else
4362 size += 100;
4363 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4364 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4365 xmlFree(str);
4366 return NULL;
4367 }
4368 str = larger;
4369 }
4370
4371 return str;
4372}
4373
Daniel Veillard417be3a2003-01-20 21:26:34 +00004374/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004375 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004376 * @locator: the xmlTextReaderLocatorPtr used
4377 *
4378 * Obtain the line number for the given locator.
4379 *
4380 * Returns the line number or -1 in case of error.
4381 */
4382int
4383xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4384 /* we know that locator is a xmlParserCtxtPtr */
4385 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4386 int ret = -1;
4387
Daniel Veillardce682bc2004-11-05 17:22:25 +00004388 if (locator == NULL)
4389 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004390 if (ctx->node != NULL) {
4391 ret = xmlGetLineNo(ctx->node);
4392 }
4393 else {
4394 /* inspired from error.c */
4395 xmlParserInputPtr input;
4396 input = ctx->input;
4397 if ((input->filename == NULL) && (ctx->inputNr > 1))
4398 input = ctx->inputTab[ctx->inputNr - 2];
4399 if (input != NULL) {
4400 ret = input->line;
4401 }
4402 else {
4403 ret = -1;
4404 }
4405 }
4406
4407 return ret;
4408}
4409
4410/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004411 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004412 * @locator: the xmlTextReaderLocatorPtr used
4413 *
4414 * Obtain the base URI for the given locator.
4415 *
4416 * Returns the base URI or NULL in case of error.
4417 */
4418xmlChar *
4419xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4420 /* we know that locator is a xmlParserCtxtPtr */
4421 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4422 xmlChar *ret = NULL;
4423
Daniel Veillardce682bc2004-11-05 17:22:25 +00004424 if (locator == NULL)
4425 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004426 if (ctx->node != NULL) {
4427 ret = xmlNodeGetBase(NULL,ctx->node);
4428 }
4429 else {
4430 /* inspired from error.c */
4431 xmlParserInputPtr input;
4432 input = ctx->input;
4433 if ((input->filename == NULL) && (ctx->inputNr > 1))
4434 input = ctx->inputTab[ctx->inputNr - 2];
4435 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004436 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004437 }
4438 else {
4439 ret = NULL;
4440 }
4441 }
4442
4443 return ret;
4444}
4445
Daniel Veillard26f70262003-01-16 22:45:08 +00004446static void
William M. Brack899e64a2003-09-26 18:03:42 +00004447xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004448 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
4449 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
4450
William M. Bracka3215c72004-07-31 16:24:01 +00004451 if (str != NULL) {
4452 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00004453 reader->errorFunc(reader->errorFuncArg,
4454 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004455 severity,
4456 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00004457 xmlFree(str);
4458 }
4459}
4460
4461static void
William M. Brack93d004f2004-02-03 00:14:10 +00004462xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
4463 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4464 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4465
4466 if (error && reader->sErrorFunc) {
4467 reader->sErrorFunc(reader->errorFuncArg,
4468 (xmlErrorPtr) error);
4469 }
4470}
4471
Daniel Veillardffa3c742005-07-21 13:24:09 +00004472static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004473xmlTextReaderError(void *ctxt, const char *msg, ...) {
4474 va_list ap;
4475
4476 va_start(ap,msg);
4477 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004478 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00004479 xmlTextReaderBuildMessage(msg,ap));
4480 va_end(ap);
4481
4482}
4483
Daniel Veillardffa3c742005-07-21 13:24:09 +00004484static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004485xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
4486 va_list ap;
4487
4488 va_start(ap,msg);
4489 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004490 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00004491 xmlTextReaderBuildMessage(msg,ap));
4492 va_end(ap);
4493}
4494
Daniel Veillardffa3c742005-07-21 13:24:09 +00004495static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004496xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
4497 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004498 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004499
Daniel Veillard417be3a2003-01-20 21:26:34 +00004500 if ((len > 1) && (msg[len - 2] != ':')) {
4501 /*
4502 * some callbacks only report locator information:
4503 * skip them (mimicking behaviour in error.c)
4504 */
4505 va_start(ap,msg);
4506 xmlTextReaderGenericError(ctxt,
4507 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4508 xmlTextReaderBuildMessage(msg,ap));
4509 va_end(ap);
4510 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004511}
4512
Daniel Veillardffa3c742005-07-21 13:24:09 +00004513static void XMLCDECL
Daniel Veillard26f70262003-01-16 22:45:08 +00004514xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
4515 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00004516 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004517
Daniel Veillard417be3a2003-01-20 21:26:34 +00004518 if ((len != 0) && (msg[len - 1] != ':')) {
4519 /*
4520 * some callbacks only report locator information:
4521 * skip them (mimicking behaviour in error.c)
4522 */
4523 va_start(ap,msg);
4524 xmlTextReaderGenericError(ctxt,
4525 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4526 xmlTextReaderBuildMessage(msg,ap));
4527 va_end(ap);
4528 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004529}
4530
4531/**
4532 * xmlTextReaderSetErrorHandler:
4533 * @reader: the xmlTextReaderPtr used
4534 * @f: the callback function to call on error and warnings
4535 * @arg: a user argument to pass to the callback function
4536 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004537 * Register a callback function that will be called on error and warnings.
4538 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004539 * If @f is NULL, the default error and warning handlers are restored.
4540 */
4541void
4542xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4543 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004544 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004545 if (f != NULL) {
4546 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004547 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004548 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4549 reader->ctxt->sax->warning = xmlTextReaderWarning;
4550 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4551 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004552 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004553 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004554#ifdef LIBXML_SCHEMAS_ENABLED
4555 if (reader->rngValidCtxt) {
4556 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4557 xmlTextReaderValidityErrorRelay,
4558 xmlTextReaderValidityWarningRelay,
4559 reader);
4560 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4561 }
4562 if (reader->xsdValidCtxt) {
4563 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4564 xmlTextReaderValidityErrorRelay,
4565 xmlTextReaderValidityWarningRelay,
4566 reader);
4567 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4568 }
4569#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004570 }
4571 else {
4572 /* restore defaults */
4573 reader->ctxt->sax->error = xmlParserError;
4574 reader->ctxt->vctxt.error = xmlParserValidityError;
4575 reader->ctxt->sax->warning = xmlParserWarning;
4576 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4577 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004578 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004579 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004580#ifdef LIBXML_SCHEMAS_ENABLED
4581 if (reader->rngValidCtxt) {
4582 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4583 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4584 }
4585 if (reader->xsdValidCtxt) {
4586 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4587 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4588 }
4589#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004590 }
4591}
4592
Daniel Veillard417be3a2003-01-20 21:26:34 +00004593/**
William M. Brack93d004f2004-02-03 00:14:10 +00004594* xmlTextReaderSetStructuredErrorHandler:
4595 * @reader: the xmlTextReaderPtr used
4596 * @f: the callback function to call on error and warnings
4597 * @arg: a user argument to pass to the callback function
4598 *
4599 * Register a callback function that will be called on error and warnings.
4600 *
4601 * If @f is NULL, the default error and warning handlers are restored.
4602 */
4603void
4604xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4605 xmlStructuredErrorFunc f,
4606 void *arg) {
4607 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004608 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004609 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4610 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4611 reader->ctxt->sax->warning = xmlTextReaderWarning;
4612 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4613 reader->sErrorFunc = f;
4614 reader->errorFunc = NULL;
4615 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004616#ifdef LIBXML_SCHEMAS_ENABLED
4617 if (reader->rngValidCtxt) {
4618 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4619 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4620 xmlTextReaderValidityStructuredRelay,
4621 reader);
4622 }
4623 if (reader->xsdValidCtxt) {
4624 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4625 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4626 xmlTextReaderValidityStructuredRelay,
4627 reader);
4628 }
4629#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004630 }
4631 else {
4632 /* restore defaults */
4633 reader->ctxt->sax->error = xmlParserError;
4634 reader->ctxt->sax->serror = NULL;
4635 reader->ctxt->vctxt.error = xmlParserValidityError;
4636 reader->ctxt->sax->warning = xmlParserWarning;
4637 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4638 reader->errorFunc = NULL;
4639 reader->sErrorFunc = NULL;
4640 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004641#ifdef LIBXML_SCHEMAS_ENABLED
4642 if (reader->rngValidCtxt) {
4643 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader);
4644 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader);
4645 }
4646 if (reader->xsdValidCtxt) {
4647 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader);
4648 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader);
4649 }
4650#endif
William M. Brack93d004f2004-02-03 00:14:10 +00004651 }
4652}
4653
4654/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004655 * xmlTextReaderIsValid:
4656 * @reader: the xmlTextReaderPtr used
4657 *
4658 * Retrieve the validity status from the parser context
4659 *
4660 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4661 */
4662int
4663xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004664 if (reader == NULL) return(-1);
4665#ifdef LIBXML_SCHEMAS_ENABLED
4666 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4667 return(reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004668 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
4669 return(reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004670#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004671 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004672 return(reader->ctxt->valid);
4673 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004674}
4675
4676/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004677 * xmlTextReaderGetErrorHandler:
4678 * @reader: the xmlTextReaderPtr used
4679 * @f: the callback function or NULL is no callback has been registered
4680 * @arg: a user argument
4681 *
4682 * Retrieve the error callback function and user argument.
4683 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004684void
4685xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4686 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004687 void **arg) {
Daniel Veillardd5cc0f72004-11-06 19:24:28 +00004688 if (f != NULL) *f = reader->errorFunc;
4689 if (arg != NULL) *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00004690}
4691
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004692
4693/************************************************************************
4694 * *
4695 * New set (2.6.0) of simpler and more flexible APIs *
4696 * *
4697 ************************************************************************/
4698
4699/**
4700 * xmlTextReaderSetup:
4701 * @reader: an XML reader
4702 * @URL: the base URL to use for the document
4703 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004704 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004705 * @reuse: keep the context for reuse
4706 *
4707 * Setup an XML reader with new options
4708 *
4709 * Returns 0 in case of success and -1 in case of error.
4710 */
4711static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004712xmlTextReaderSetup(xmlTextReaderPtr reader,
4713 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004714 const char *encoding, int options)
4715{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004716 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004717 return (-1);
4718
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004719 reader->doc = NULL;
4720 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004721 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004722 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004723 if ((input != NULL) && (reader->input != NULL) &&
4724 (reader->allocs & XML_TEXTREADER_INPUT)) {
4725 xmlFreeParserInputBuffer(reader->input);
4726 reader->input = NULL;
4727 reader->allocs -= XML_TEXTREADER_INPUT;
4728 }
4729 if (input != NULL) {
4730 reader->input = input;
4731 reader->allocs |= XML_TEXTREADER_INPUT;
4732 }
4733 if (reader->buffer == NULL)
4734 reader->buffer = xmlBufferCreateSize(100);
4735 if (reader->buffer == NULL) {
4736 xmlGenericError(xmlGenericErrorContext,
4737 "xmlTextReaderSetup : malloc failed\n");
4738 return (-1);
4739 }
4740 if (reader->sax == NULL)
4741 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4742 if (reader->sax == NULL) {
4743 xmlGenericError(xmlGenericErrorContext,
4744 "xmlTextReaderSetup : malloc failed\n");
4745 return (-1);
4746 }
4747 xmlSAXVersion(reader->sax, 2);
4748 reader->startElement = reader->sax->startElement;
4749 reader->sax->startElement = xmlTextReaderStartElement;
4750 reader->endElement = reader->sax->endElement;
4751 reader->sax->endElement = xmlTextReaderEndElement;
4752#ifdef LIBXML_SAX1_ENABLED
4753 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4754#endif /* LIBXML_SAX1_ENABLED */
4755 reader->startElementNs = reader->sax->startElementNs;
4756 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4757 reader->endElementNs = reader->sax->endElementNs;
4758 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4759#ifdef LIBXML_SAX1_ENABLED
4760 } else {
4761 reader->startElementNs = NULL;
4762 reader->endElementNs = NULL;
4763 }
4764#endif /* LIBXML_SAX1_ENABLED */
4765 reader->characters = reader->sax->characters;
4766 reader->sax->characters = xmlTextReaderCharacters;
4767 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4768 reader->cdataBlock = reader->sax->cdataBlock;
4769 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4770
4771 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4772 reader->node = NULL;
4773 reader->curnode = NULL;
4774 if (input != NULL) {
4775 if (reader->input->buffer->use < 4) {
4776 xmlParserInputBufferRead(input, 4);
4777 }
4778 if (reader->ctxt == NULL) {
4779 if (reader->input->buffer->use >= 4) {
4780 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4781 (const char *) reader->input->buffer->content, 4, URL);
4782 reader->base = 0;
4783 reader->cur = 4;
4784 } else {
4785 reader->ctxt =
4786 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4787 reader->base = 0;
4788 reader->cur = 0;
4789 }
4790 } else {
4791 xmlParserInputPtr inputStream;
4792 xmlParserInputBufferPtr buf;
4793 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4794
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004795 xmlCtxtReset(reader->ctxt);
4796 buf = xmlAllocParserInputBuffer(enc);
4797 if (buf == NULL) return(-1);
4798 inputStream = xmlNewInputStream(reader->ctxt);
4799 if (inputStream == NULL) {
4800 xmlFreeParserInputBuffer(buf);
4801 return(-1);
4802 }
4803
4804 if (URL == NULL)
4805 inputStream->filename = NULL;
4806 else
4807 inputStream->filename = (char *)
4808 xmlCanonicPath((const xmlChar *) URL);
4809 inputStream->buf = buf;
4810 inputStream->base = inputStream->buf->buffer->content;
4811 inputStream->cur = inputStream->buf->buffer->content;
4812 inputStream->end =
4813 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4814
4815 inputPush(reader->ctxt, inputStream);
4816 reader->cur = 0;
4817 }
4818 if (reader->ctxt == NULL) {
4819 xmlGenericError(xmlGenericErrorContext,
4820 "xmlTextReaderSetup : malloc failed\n");
4821 return (-1);
4822 }
4823 }
4824 if (reader->dict != NULL) {
4825 if (reader->ctxt->dict != NULL) {
4826 if (reader->dict != reader->ctxt->dict) {
4827 xmlDictFree(reader->dict);
4828 reader->dict = reader->ctxt->dict;
4829 }
4830 } else {
4831 reader->ctxt->dict = reader->dict;
4832 }
4833 } else {
4834 if (reader->ctxt->dict == NULL)
4835 reader->ctxt->dict = xmlDictCreate();
4836 reader->dict = reader->ctxt->dict;
4837 }
4838 reader->ctxt->_private = reader;
4839 reader->ctxt->linenumbers = 1;
4840 reader->ctxt->dictNames = 1;
4841 /*
4842 * use the parser dictionnary to allocate all elements and attributes names
4843 */
4844 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004845 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004846
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004847#ifdef LIBXML_XINCLUDE_ENABLED
4848 if (reader->xincctxt != NULL) {
4849 xmlXIncludeFreeContext(reader->xincctxt);
4850 reader->xincctxt = NULL;
4851 }
4852 if (options & XML_PARSE_XINCLUDE) {
4853 reader->xinclude = 1;
4854 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4855 options -= XML_PARSE_XINCLUDE;
4856 } else
4857 reader->xinclude = 0;
4858 reader->in_xinclude = 0;
4859#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004860#ifdef LIBXML_PATTERN_ENABLED
4861 if (reader->patternTab == NULL) {
4862 reader->patternNr = 0;
4863 reader->patternMax = 0;
4864 }
4865 while (reader->patternNr > 0) {
4866 reader->patternNr--;
4867 if (reader->patternTab[reader->patternNr] != NULL) {
4868 xmlFreePattern(reader->patternTab[reader->patternNr]);
4869 reader->patternTab[reader->patternNr] = NULL;
4870 }
4871 }
4872#endif
4873
Daniel Veillardc36965d2003-12-02 10:28:48 +00004874 if (options & XML_PARSE_DTDVALID)
4875 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4876
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004877 xmlCtxtUseOptions(reader->ctxt, options);
4878 if (encoding != NULL) {
4879 xmlCharEncodingHandlerPtr hdlr;
4880
4881 hdlr = xmlFindCharEncodingHandler(encoding);
4882 if (hdlr != NULL)
4883 xmlSwitchToEncoding(reader->ctxt, hdlr);
4884 }
4885 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4886 (reader->ctxt->input->filename == NULL))
4887 reader->ctxt->input->filename = (char *)
4888 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004889
4890 reader->doc = NULL;
4891
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004892 return (0);
4893}
4894
4895/**
Daniel Veillard5e094142005-02-18 19:36:12 +00004896 * xmlTextReaderByteConsumed:
4897 * @reader: an XML reader
4898 *
4899 * This function provides the current index of the parser used
4900 * by the reader, relative to the start of the current entity.
4901 * This function actually just wraps a call to xmlBytesConsumed()
4902 * for the parser context associated with the reader.
4903 * See xmlBytesConsumed() for more information.
4904 *
4905 * Returns the index in bytes from the beginning of the entity or -1
4906 * in case the index could not be computed.
4907 */
4908long
4909xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
4910 if ((reader == NULL) || (reader->ctxt == NULL))
4911 return(-1);
4912 return(xmlByteConsumed(reader->ctxt));
4913}
4914
4915
4916/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004917 * xmlReaderWalker:
4918 * @doc: a preparsed document
4919 *
4920 * Create an xmltextReader for a preparsed document.
4921 *
4922 * Returns the new reader or NULL in case of error.
4923 */
4924xmlTextReaderPtr
4925xmlReaderWalker(xmlDocPtr doc)
4926{
4927 xmlTextReaderPtr ret;
4928
4929 if (doc == NULL)
4930 return(NULL);
4931
4932 ret = xmlMalloc(sizeof(xmlTextReader));
4933 if (ret == NULL) {
4934 xmlGenericError(xmlGenericErrorContext,
4935 "xmlNewTextReader : malloc failed\n");
4936 return(NULL);
4937 }
4938 memset(ret, 0, sizeof(xmlTextReader));
4939 ret->entNr = 0;
4940 ret->input = NULL;
4941 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4942 ret->node = NULL;
4943 ret->curnode = NULL;
4944 ret->base = 0;
4945 ret->cur = 0;
4946 ret->allocs = XML_TEXTREADER_CTXT;
4947 ret->doc = doc;
4948 ret->state = XML_TEXTREADER_START;
4949 ret->dict = xmlDictCreate();
4950 return(ret);
4951}
4952
4953/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004954 * xmlReaderForDoc:
4955 * @cur: a pointer to a zero terminated string
4956 * @URL: the base URL to use for the document
4957 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004958 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004959 *
4960 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004961 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004962 *
4963 * Returns the new reader or NULL in case of error.
4964 */
4965xmlTextReaderPtr
4966xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4967 int options)
4968{
4969 int len;
4970
4971 if (cur == NULL)
4972 return (NULL);
4973 len = xmlStrlen(cur);
4974
4975 return (xmlReaderForMemory
4976 ((const char *) cur, len, URL, encoding, options));
4977}
4978
4979/**
4980 * xmlReaderForFile:
4981 * @filename: a file or URL
4982 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004983 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004984 *
4985 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004986 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004987 *
4988 * Returns the new reader or NULL in case of error.
4989 */
4990xmlTextReaderPtr
4991xmlReaderForFile(const char *filename, const char *encoding, int options)
4992{
4993 xmlTextReaderPtr reader;
4994
4995 reader = xmlNewTextReaderFilename(filename);
4996 if (reader == NULL)
4997 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004998 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004999 return (reader);
5000}
5001
5002/**
5003 * xmlReaderForMemory:
5004 * @buffer: a pointer to a char array
5005 * @size: the size of the array
5006 * @URL: the base URL to use for the document
5007 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005008 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005009 *
5010 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005011 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005012 *
5013 * Returns the new reader or NULL in case of error.
5014 */
5015xmlTextReaderPtr
5016xmlReaderForMemory(const char *buffer, int size, const char *URL,
5017 const char *encoding, int options)
5018{
5019 xmlTextReaderPtr reader;
5020 xmlParserInputBufferPtr buf;
5021
Daniel Veillard21924522004-02-19 16:37:07 +00005022 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005023 XML_CHAR_ENCODING_NONE);
5024 if (buf == NULL) {
5025 return (NULL);
5026 }
5027 reader = xmlNewTextReader(buf, URL);
5028 if (reader == NULL) {
5029 xmlFreeParserInputBuffer(buf);
5030 return (NULL);
5031 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005032 reader->allocs |= XML_TEXTREADER_INPUT;
5033 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005034 return (reader);
5035}
5036
5037/**
5038 * xmlReaderForFd:
5039 * @fd: an open file descriptor
5040 * @URL: the base URL to use for the document
5041 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005042 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005043 *
5044 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005045 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005046 * NOTE that the file descriptor will not be closed when the
5047 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005048 *
5049 * Returns the new reader or NULL in case of error.
5050 */
5051xmlTextReaderPtr
5052xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5053{
5054 xmlTextReaderPtr reader;
5055 xmlParserInputBufferPtr input;
5056
5057 if (fd < 0)
5058 return (NULL);
5059
5060 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5061 if (input == NULL)
5062 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005063 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005064 reader = xmlNewTextReader(input, URL);
5065 if (reader == NULL) {
5066 xmlFreeParserInputBuffer(input);
5067 return (NULL);
5068 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005069 reader->allocs |= XML_TEXTREADER_INPUT;
5070 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005071 return (reader);
5072}
5073
5074/**
5075 * xmlReaderForIO:
5076 * @ioread: an I/O read function
5077 * @ioclose: an I/O close function
5078 * @ioctx: an I/O handler
5079 * @URL: the base URL to use for the document
5080 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005081 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005082 *
5083 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005084 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005085 *
5086 * Returns the new reader or NULL in case of error.
5087 */
5088xmlTextReaderPtr
5089xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5090 void *ioctx, const char *URL, const char *encoding,
5091 int options)
5092{
5093 xmlTextReaderPtr reader;
5094 xmlParserInputBufferPtr input;
5095
5096 if (ioread == NULL)
5097 return (NULL);
5098
5099 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5100 XML_CHAR_ENCODING_NONE);
5101 if (input == NULL)
5102 return (NULL);
5103 reader = xmlNewTextReader(input, URL);
5104 if (reader == NULL) {
5105 xmlFreeParserInputBuffer(input);
5106 return (NULL);
5107 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005108 reader->allocs |= XML_TEXTREADER_INPUT;
5109 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005110 return (reader);
5111}
5112
5113/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005114 * xmlReaderNewWalker:
5115 * @reader: an XML reader
5116 * @doc: a preparsed document
5117 *
5118 * Setup an xmltextReader to parse a preparsed XML document.
5119 * This reuses the existing @reader xmlTextReader.
5120 *
5121 * Returns 0 in case of success and -1 in case of error
5122 */
5123int
5124xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5125{
5126 if (doc == NULL)
5127 return (-1);
5128 if (reader == NULL)
5129 return (-1);
5130
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005131 if (reader->input != NULL) {
5132 xmlFreeParserInputBuffer(reader->input);
5133 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005134 if (reader->ctxt != NULL) {
5135 xmlCtxtReset(reader->ctxt);
5136 }
5137
5138 reader->entNr = 0;
5139 reader->input = NULL;
5140 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5141 reader->node = NULL;
5142 reader->curnode = NULL;
5143 reader->base = 0;
5144 reader->cur = 0;
5145 reader->allocs = XML_TEXTREADER_CTXT;
5146 reader->doc = doc;
5147 reader->state = XML_TEXTREADER_START;
5148 if (reader->dict == NULL) {
5149 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5150 reader->dict = reader->ctxt->dict;
5151 else
5152 reader->dict = xmlDictCreate();
5153 }
5154 return(0);
5155}
5156
5157/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005158 * xmlReaderNewDoc:
5159 * @reader: an XML reader
5160 * @cur: a pointer to a zero terminated string
5161 * @URL: the base URL to use for the document
5162 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005163 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005164 *
5165 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005166 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005167 * This reuses the existing @reader xmlTextReader.
5168 *
5169 * Returns 0 in case of success and -1 in case of error
5170 */
5171int
5172xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5173 const char *URL, const char *encoding, int options)
5174{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005175
5176 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005177
5178 if (cur == NULL)
5179 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005180 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005181 return (-1);
5182
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005183 len = xmlStrlen(cur);
5184 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5185 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005186}
5187
5188/**
5189 * xmlReaderNewFile:
5190 * @reader: an XML reader
5191 * @filename: a file or URL
5192 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005193 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005194 *
5195 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005196 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005197 * This reuses the existing @reader xmlTextReader.
5198 *
5199 * Returns 0 in case of success and -1 in case of error
5200 */
5201int
5202xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5203 const char *encoding, int options)
5204{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005205 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005206
5207 if (filename == NULL)
5208 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005209 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005210 return (-1);
5211
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005212 input =
5213 xmlParserInputBufferCreateFilename(filename,
5214 XML_CHAR_ENCODING_NONE);
5215 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005216 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005217 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005218}
5219
5220/**
5221 * xmlReaderNewMemory:
5222 * @reader: an XML reader
5223 * @buffer: a pointer to a char array
5224 * @size: the size of the array
5225 * @URL: the base URL to use for the document
5226 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005227 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005228 *
5229 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005230 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005231 * This reuses the existing @reader xmlTextReader.
5232 *
5233 * Returns 0 in case of success and -1 in case of error
5234 */
5235int
5236xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5237 const char *URL, const char *encoding, int options)
5238{
5239 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005240
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005241 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005242 return (-1);
5243 if (buffer == NULL)
5244 return (-1);
5245
Daniel Veillard21924522004-02-19 16:37:07 +00005246 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005247 XML_CHAR_ENCODING_NONE);
5248 if (input == NULL) {
5249 return (-1);
5250 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005251 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005252}
5253
5254/**
5255 * xmlReaderNewFd:
5256 * @reader: an XML reader
5257 * @fd: an open file descriptor
5258 * @URL: the base URL to use for the document
5259 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005260 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005261 *
5262 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005263 * NOTE that the file descriptor will not be closed when the
5264 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005265 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005266 * This reuses the existing @reader xmlTextReader.
5267 *
5268 * Returns 0 in case of success and -1 in case of error
5269 */
5270int
5271xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5272 const char *URL, const char *encoding, int options)
5273{
5274 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005275
5276 if (fd < 0)
5277 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005278 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005279 return (-1);
5280
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005281 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5282 if (input == NULL)
5283 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005284 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005285 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005286}
5287
5288/**
5289 * xmlReaderNewIO:
5290 * @reader: an XML reader
5291 * @ioread: an I/O read function
5292 * @ioclose: an I/O close function
5293 * @ioctx: an I/O handler
5294 * @URL: the base URL to use for the document
5295 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005296 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005297 *
5298 * Setup an xmltextReader to parse an XML document from I/O functions
5299 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005300 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005301 * This reuses the existing @reader xmlTextReader.
5302 *
5303 * Returns 0 in case of success and -1 in case of error
5304 */
5305int
5306xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5307 xmlInputCloseCallback ioclose, void *ioctx,
5308 const char *URL, const char *encoding, int options)
5309{
5310 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005311
5312 if (ioread == NULL)
5313 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005314 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005315 return (-1);
5316
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005317 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5318 XML_CHAR_ENCODING_NONE);
5319 if (input == NULL)
5320 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005321 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005322}
Daniel Veillard26f70262003-01-16 22:45:08 +00005323/************************************************************************
5324 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005325 * Utilities *
5326 * *
5327 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005328#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005329/**
5330 * xmlBase64Decode:
5331 * @in: the input buffer
5332 * @inlen: the size of the input (in), the size read from it (out)
5333 * @to: the output buffer
5334 * @tolen: the size of the output (in), the size written to (out)
5335 *
5336 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005337 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005338 *
5339 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5340 * 2 if there wasn't enough space on the output or -1 in case of error.
5341 */
5342static int
5343xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5344 unsigned char *to, unsigned long *tolen) {
5345 unsigned long incur; /* current index in in[] */
5346 unsigned long inblk; /* last block index in in[] */
5347 unsigned long outcur; /* current index in out[] */
5348 unsigned long inmax; /* size of in[] */
5349 unsigned long outmax; /* size of out[] */
5350 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00005351 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005352 int nbintmp; /* number of byte in intmp[] */
5353 int is_ignore; /* cur should be ignored */
5354 int is_end = 0; /* the end of the base64 was found */
5355 int retval = 1;
5356 int i;
5357
5358 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5359 return(-1);
5360
5361 incur = 0;
5362 inblk = 0;
5363 outcur = 0;
5364 inmax = *inlen;
5365 outmax = *tolen;
5366 nbintmp = 0;
5367
5368 while (1) {
5369 if (incur >= inmax)
5370 break;
5371 cur = in[incur++];
5372 is_ignore = 0;
5373 if ((cur >= 'A') && (cur <= 'Z'))
5374 cur = cur - 'A';
5375 else if ((cur >= 'a') && (cur <= 'z'))
5376 cur = cur - 'a' + 26;
5377 else if ((cur >= '0') && (cur <= '9'))
5378 cur = cur - '0' + 52;
5379 else if (cur == '+')
5380 cur = 62;
5381 else if (cur == '/')
5382 cur = 63;
5383 else if (cur == '.')
5384 cur = 0;
5385 else if (cur == '=') /*no op , end of the base64 stream */
5386 is_end = 1;
5387 else {
5388 is_ignore = 1;
5389 if (nbintmp == 0)
5390 inblk = incur;
5391 }
5392
5393 if (!is_ignore) {
5394 int nbouttmp = 3;
5395 int is_break = 0;
5396
5397 if (is_end) {
5398 if (nbintmp == 0)
5399 break;
5400 if ((nbintmp == 1) || (nbintmp == 2))
5401 nbouttmp = 1;
5402 else
5403 nbouttmp = 2;
5404 nbintmp = 3;
5405 is_break = 1;
5406 }
5407 intmp[nbintmp++] = cur;
5408 /*
5409 * if intmp is full, push the 4byte sequence as a 3 byte
5410 * sequence out
5411 */
5412 if (nbintmp == 4) {
5413 nbintmp = 0;
5414 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5415 outtmp[1] =
5416 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5417 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5418 if (outcur + 3 >= outmax) {
5419 retval = 2;
5420 break;
5421 }
5422
5423 for (i = 0; i < nbouttmp; i++)
5424 to[outcur++] = outtmp[i];
5425 inblk = incur;
5426 }
5427
5428 if (is_break) {
5429 retval = 0;
5430 break;
5431 }
5432 }
5433 }
5434
5435 *tolen = outcur;
5436 *inlen = inblk;
5437 return (retval);
5438}
5439
5440/*
5441 * Test routine for the xmlBase64Decode function
5442 */
5443#if 0
5444int main(int argc, char **argv) {
5445 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
5446 char output[100];
5447 char output2[100];
5448 char output3[100];
5449 unsigned long inlen = strlen(input);
5450 unsigned long outlen = 100;
5451 int ret;
5452 unsigned long cons, tmp, tmp2, prod;
5453
5454 /*
5455 * Direct
5456 */
5457 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5458
5459 output[outlen] = 0;
5460 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
5461
5462 /*
5463 * output chunking
5464 */
5465 cons = 0;
5466 prod = 0;
5467 while (cons < inlen) {
5468 tmp = 5;
5469 tmp2 = inlen - cons;
5470
5471 printf("%ld %ld\n", cons, prod);
5472 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5473 cons += tmp2;
5474 prod += tmp;
5475 printf("%ld %ld\n", cons, prod);
5476 }
5477 output2[outlen] = 0;
5478 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
5479
5480 /*
5481 * input chunking
5482 */
5483 cons = 0;
5484 prod = 0;
5485 while (cons < inlen) {
5486 tmp = 100 - prod;
5487 tmp2 = inlen - cons;
5488 if (tmp2 > 5)
5489 tmp2 = 5;
5490
5491 printf("%ld %ld\n", cons, prod);
5492 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5493 cons += tmp2;
5494 prod += tmp;
5495 printf("%ld %ld\n", cons, prod);
5496 }
5497 output3[outlen] = 0;
5498 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
5499 return(0);
5500
5501}
5502#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005503#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005504#define bottom_xmlreader
5505#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005506#endif /* LIBXML_READER_ENABLED */