blob: c6fc007c7247d23b83af89c259d16a71bea39c81 [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 * - setting(s) for NoBlanks
17 * - performances and tuning ...
18 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000019#define IN_LIBXML
20#include "libxml.h"
21
Daniel Veillard81273902003-09-30 00:43:48 +000022#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000024#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025
26#ifdef HAVE_CTYPE_H
27#include <ctype.h>
28#endif
29#ifdef HAVE_STDLIB_H
30#include <stdlib.h>
31#endif
32
33#include <libxml/xmlmemory.h>
34#include <libxml/xmlIO.h>
35#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000036#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000037#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000038#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000039#ifdef LIBXML_XINCLUDE_ENABLED
40#include <libxml/xinclude.h>
41#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000042#ifdef LIBXML_PATTERN_ENABLED
43#include <libxml/pattern.h>
44#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000045
46/* #define DEBUG_CALLBACKS */
47/* #define DEBUG_READER */
48
49/**
50 * TODO:
51 *
52 * macro to flag unimplemented blocks
53 */
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
59#ifdef DEBUG_READER
60#define DUMP_READER xmlTextReaderDebug(reader);
61#else
62#define DUMP_READER
63#endif
64
Daniel Veillarda880b122003-04-21 21:36:41 +000065#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000066/************************************************************************
67 * *
68 * The parser: maps the Text Reader API on top of the existing *
69 * parsing routines building a tree *
70 * *
71 ************************************************************************/
72
73#define XML_TEXTREADER_INPUT 1
74#define XML_TEXTREADER_CTXT 2
75
76typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +000077 XML_TEXTREADER_NONE = -1,
78 XML_TEXTREADER_START= 0,
79 XML_TEXTREADER_ELEMENT= 1,
80 XML_TEXTREADER_END= 2,
81 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000082 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000083 XML_TEXTREADER_DONE= 5,
84 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000085} xmlTextReaderState;
86
Daniel Veillardf4e55762003-04-15 23:32:22 +000087typedef enum {
88 XML_TEXTREADER_NOT_VALIDATE = 0,
89 XML_TEXTREADER_VALIDATE_DTD = 1,
90 XML_TEXTREADER_VALIDATE_RNG = 2
91} xmlTextReaderValidate;
92
Daniel Veillarde1ca5032002-12-09 14:13:43 +000093struct _xmlTextReader {
94 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +000095 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +000096 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000097 int allocs; /* what structure were deallocated */
98 xmlTextReaderState state;
99 xmlParserCtxtPtr ctxt; /* the parser context */
100 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
101 xmlParserInputBufferPtr input; /* the input */
102 startElementSAXFunc startElement;/* initial SAX callbacks */
103 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000104 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000105 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000106 charactersSAXFunc characters;
107 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000108 unsigned int base; /* base of the segment in the input */
109 unsigned int cur; /* current position in the input */
110 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000111 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000112 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000113 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000114 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000115 xmlBufferPtr buffer; /* used to return const xmlChar * */
116 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000117
118 /* entity stack when traversing entities content */
119 xmlNodePtr ent; /* Current Entity Ref Node */
120 int entNr; /* Depth of the entities stack */
121 int entMax; /* Max depth of the entities stack */
122 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000123
124 /* error handling */
125 xmlTextReaderErrorFunc errorFunc; /* callback function */
126 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000127
128#ifdef LIBXML_SCHEMAS_ENABLED
129 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000130 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
131 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
132 int rngValidErrors;/* The number of errors detected */
133 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
134#endif
135#ifdef LIBXML_XINCLUDE_ENABLED
136 /* Handling of XInclude processing */
137 int xinclude; /* is xinclude asked for */
138 const xmlChar * xinclude_name; /* the xinclude name from dict */
139 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
140 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000141#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000142#ifdef LIBXML_PATTERN_ENABLED
143 int patternNr; /* number of preserve patterns */
144 int patternMax; /* max preserve patterns */
145 xmlPatternPtr *patternTab; /* array of preserve patterns */
146#endif
147 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000148 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000149 /* Structured error handling */
150 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000151};
152
Daniel Veillarde8039df2003-10-27 11:25:13 +0000153#define NODE_IS_EMPTY 0x1
154#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000155#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000156
Daniel Veillarde72c5082003-09-19 12:44:05 +0000157/**
158 * CONSTSTR:
159 *
160 * Macro used to return an interned string
161 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000162#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
163#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
164
165static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
166static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000167
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000168/************************************************************************
169 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000170 * Our own version of the freeing routines as we recycle nodes *
171 * *
172 ************************************************************************/
173/**
174 * DICT_FREE:
175 * @str: a string
176 *
177 * Free a string if it is not owned by the "dict" dictionnary in the
178 * current scope
179 */
180#define DICT_FREE(str) \
181 if ((str) && ((!dict) || \
182 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
183 xmlFree((char *)(str));
184
185static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
186static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
187
188/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000189 * xmlFreeID:
190 * @not: A id
191 *
192 * Deallocate the memory used by an id definition
193 */
194static void
195xmlFreeID(xmlIDPtr id) {
196 xmlDictPtr dict = NULL;
197
198 if (id == NULL) return;
199
200 if (id->doc != NULL)
201 dict = id->doc->dict;
202
203 if (id->value != NULL)
204 DICT_FREE(id->value)
205 xmlFree(id);
206}
207
208/**
209 * xmlTextReaderRemoveID:
210 * @doc: the document
211 * @attr: the attribute
212 *
213 * Remove the given attribute from the ID table maintained internally.
214 *
215 * Returns -1 if the lookup failed and 0 otherwise
216 */
217static int
218xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
219 xmlIDTablePtr table;
220 xmlIDPtr id;
221 xmlChar *ID;
222
223 if (doc == NULL) return(-1);
224 if (attr == NULL) return(-1);
225 table = (xmlIDTablePtr) doc->ids;
226 if (table == NULL)
227 return(-1);
228
229 if (attr == NULL)
230 return(-1);
231 ID = xmlNodeListGetString(doc, attr->children, 1);
232 if (ID == NULL)
233 return(-1);
234 id = xmlHashLookup(table, ID);
235 xmlFree(ID);
236 if (id == NULL || id->attr != attr) {
237 return(-1);
238 }
239 id->name = attr->name;
240 id->attr = NULL;
241 return(0);
242}
243
244/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000245 * xmlTextReaderFreeProp:
246 * @reader: the xmlTextReaderPtr used
247 * @cur: the node
248 *
249 * Free a node.
250 */
251static void
252xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
253 xmlDictPtr dict;
254
255 dict = reader->ctxt->dict;
256 if (cur == NULL) return;
257
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000258 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
259 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
260
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000261 /* Check for ID removal -> leading to invalid references ! */
262 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
263 ((cur->parent->doc->intSubset != NULL) ||
264 (cur->parent->doc->extSubset != NULL))) {
265 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000266 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000267 }
268 if (cur->children != NULL)
269 xmlTextReaderFreeNodeList(reader, cur->children);
270
271 DICT_FREE(cur->name);
272 if ((reader != NULL) && (reader->ctxt != NULL) &&
273 (reader->ctxt->freeAttrsNr < 100)) {
274 cur->next = reader->ctxt->freeAttrs;
275 reader->ctxt->freeAttrs = cur;
276 reader->ctxt->freeAttrsNr++;
277 } else {
278 xmlFree(cur);
279 }
280}
281
282/**
283 * xmlTextReaderFreePropList:
284 * @reader: the xmlTextReaderPtr used
285 * @cur: the first property in the list
286 *
287 * Free a property and all its siblings, all the children are freed too.
288 */
289static void
290xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
291 xmlAttrPtr next;
292 if (cur == NULL) return;
293 while (cur != NULL) {
294 next = cur->next;
295 xmlTextReaderFreeProp(reader, cur);
296 cur = next;
297 }
298}
299
300/**
301 * xmlTextReaderFreeNodeList:
302 * @reader: the xmlTextReaderPtr used
303 * @cur: the first node in the list
304 *
305 * Free a node and all its siblings, this is a recursive behaviour, all
306 * the children are freed too.
307 */
308static void
309xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
310 xmlNodePtr next;
311 xmlDictPtr dict;
312
313 dict = reader->ctxt->dict;
314 if (cur == NULL) return;
315 if (cur->type == XML_NAMESPACE_DECL) {
316 xmlFreeNsList((xmlNsPtr) cur);
317 return;
318 }
319 if ((cur->type == XML_DOCUMENT_NODE) ||
320 (cur->type == XML_HTML_DOCUMENT_NODE)) {
321 xmlFreeDoc((xmlDocPtr) cur);
322 return;
323 }
324 while (cur != NULL) {
325 next = cur->next;
326 /* unroll to speed up freeing the document */
327 if (cur->type != XML_DTD_NODE) {
328
329 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000330 (cur->type != XML_ENTITY_REF_NODE)) {
331 if (cur->children->parent == cur)
332 xmlTextReaderFreeNodeList(reader, cur->children);
333 cur->children = NULL;
334 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000335
336 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
337 xmlDeregisterNodeDefaultValue(cur);
338
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000339 if (((cur->type == XML_ELEMENT_NODE) ||
340 (cur->type == XML_XINCLUDE_START) ||
341 (cur->type == XML_XINCLUDE_END)) &&
342 (cur->properties != NULL))
343 xmlTextReaderFreePropList(reader, cur->properties);
344 if ((cur->type != XML_ELEMENT_NODE) &&
345 (cur->type != XML_XINCLUDE_START) &&
346 (cur->type != XML_XINCLUDE_END) &&
347 (cur->type != XML_ENTITY_REF_NODE)) {
348 DICT_FREE(cur->content);
349 }
350 if (((cur->type == XML_ELEMENT_NODE) ||
351 (cur->type == XML_XINCLUDE_START) ||
352 (cur->type == XML_XINCLUDE_END)) &&
353 (cur->nsDef != NULL))
354 xmlFreeNsList(cur->nsDef);
355
356 /*
357 * we don't free element names here they are interned now
358 */
359 if ((cur->type != XML_TEXT_NODE) &&
360 (cur->type != XML_COMMENT_NODE))
361 DICT_FREE(cur->name);
362 if (((cur->type == XML_ELEMENT_NODE) ||
363 (cur->type == XML_TEXT_NODE)) &&
364 (reader != NULL) && (reader->ctxt != NULL) &&
365 (reader->ctxt->freeElemsNr < 100)) {
366 cur->next = reader->ctxt->freeElems;
367 reader->ctxt->freeElems = cur;
368 reader->ctxt->freeElemsNr++;
369 } else {
370 xmlFree(cur);
371 }
372 }
373 cur = next;
374 }
375}
376
377/**
378 * xmlTextReaderFreeNode:
379 * @reader: the xmlTextReaderPtr used
380 * @cur: the node
381 *
382 * Free a node, this is a recursive behaviour, all the children are freed too.
383 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
384 */
385static void
386xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
387 xmlDictPtr dict;
388
389 dict = reader->ctxt->dict;
390 if (cur->type == XML_DTD_NODE) {
391 xmlFreeDtd((xmlDtdPtr) cur);
392 return;
393 }
394 if (cur->type == XML_NAMESPACE_DECL) {
395 xmlFreeNs((xmlNsPtr) cur);
396 return;
397 }
398 if (cur->type == XML_ATTRIBUTE_NODE) {
399 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
400 return;
401 }
402
403 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000404 (cur->type != XML_ENTITY_REF_NODE)) {
405 if (cur->children->parent == cur)
406 xmlTextReaderFreeNodeList(reader, cur->children);
407 cur->children = NULL;
408 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000409
410 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
411 xmlDeregisterNodeDefaultValue(cur);
412
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000413 if (((cur->type == XML_ELEMENT_NODE) ||
414 (cur->type == XML_XINCLUDE_START) ||
415 (cur->type == XML_XINCLUDE_END)) &&
416 (cur->properties != NULL))
417 xmlTextReaderFreePropList(reader, cur->properties);
418 if ((cur->type != XML_ELEMENT_NODE) &&
419 (cur->type != XML_XINCLUDE_START) &&
420 (cur->type != XML_XINCLUDE_END) &&
421 (cur->type != XML_ENTITY_REF_NODE)) {
422 DICT_FREE(cur->content);
423 }
424 if (((cur->type == XML_ELEMENT_NODE) ||
425 (cur->type == XML_XINCLUDE_START) ||
426 (cur->type == XML_XINCLUDE_END)) &&
427 (cur->nsDef != NULL))
428 xmlFreeNsList(cur->nsDef);
429
430 /*
431 * we don't free names here they are interned now
432 */
433 if ((cur->type != XML_TEXT_NODE) &&
434 (cur->type != XML_COMMENT_NODE))
435 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000436
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000437 if (((cur->type == XML_ELEMENT_NODE) ||
438 (cur->type == XML_TEXT_NODE)) &&
439 (reader != NULL) && (reader->ctxt != NULL) &&
440 (reader->ctxt->freeElemsNr < 100)) {
441 cur->next = reader->ctxt->freeElems;
442 reader->ctxt->freeElems = cur;
443 reader->ctxt->freeElemsNr++;
444 } else {
445 xmlFree(cur);
446 }
447}
448
449/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000450 * xmlTextReaderFreeIDTable:
451 * @table: An id table
452 *
453 * Deallocate the memory used by an ID hash table.
454 */
William M. Brack60f394e2003-11-16 06:25:42 +0000455static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000456xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
457 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
458}
459
460/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000461 * xmlTextReaderFreeDoc:
462 * @reader: the xmlTextReaderPtr used
463 * @cur: pointer to the document
464 *
465 * Free up all the structures used by a document, tree included.
466 */
467static void
468xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
469 xmlDtdPtr extSubset, intSubset;
470
471 if (cur == NULL) return;
472
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000473 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
474 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
475
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000476 /*
477 * Do this before freeing the children list to avoid ID lookups
478 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000479 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000480 cur->ids = NULL;
481 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
482 cur->refs = NULL;
483 extSubset = cur->extSubset;
484 intSubset = cur->intSubset;
485 if (intSubset == extSubset)
486 extSubset = NULL;
487 if (extSubset != NULL) {
488 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
489 cur->extSubset = NULL;
490 xmlFreeDtd(extSubset);
491 }
492 if (intSubset != NULL) {
493 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
494 cur->intSubset = NULL;
495 xmlFreeDtd(intSubset);
496 }
497
498 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
499
500 if (cur->version != NULL) xmlFree((char *) cur->version);
501 if (cur->name != NULL) xmlFree((char *) cur->name);
502 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
503 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
504 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000505 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000506
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000507 xmlFree(cur);
508}
509
510/************************************************************************
511 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000512 * The reader core parser *
513 * *
514 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000515#ifdef DEBUG_READER
516static void
517xmlTextReaderDebug(xmlTextReaderPtr reader) {
518 if ((reader == NULL) || (reader->ctxt == NULL)) {
519 fprintf(stderr, "xmlTextReader NULL\n");
520 return;
521 }
522 fprintf(stderr, "xmlTextReader: state %d depth %d ",
523 reader->state, reader->depth);
524 if (reader->node == NULL) {
525 fprintf(stderr, "node = NULL\n");
526 } else {
527 fprintf(stderr, "node %s\n", reader->node->name);
528 }
529 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
530 reader->base, reader->cur, reader->ctxt->nodeNr);
531 if (reader->input->buffer == NULL) {
532 fprintf(stderr, "buffer is NULL\n");
533 } else {
534#ifdef LIBXML_DEBUG_ENABLED
535 xmlDebugDumpString(stderr,
536 &reader->input->buffer->content[reader->cur]);
537#endif
538 fprintf(stderr, "\n");
539 }
540}
541#endif
542
543/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000544 * xmlTextReaderEntPush:
545 * @reader: the xmlTextReaderPtr used
546 * @value: the entity reference node
547 *
548 * Pushes a new entity reference node on top of the entities stack
549 *
550 * Returns 0 in case of error, the index in the stack otherwise
551 */
552static int
553xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
554{
555 if (reader->entMax <= 0) {
556 reader->entMax = 10;
557 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
558 sizeof(reader->entTab[0]));
559 if (reader->entTab == NULL) {
560 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
561 return (0);
562 }
563 }
564 if (reader->entNr >= reader->entMax) {
565 reader->entMax *= 2;
566 reader->entTab =
567 (xmlNodePtr *) xmlRealloc(reader->entTab,
568 reader->entMax *
569 sizeof(reader->entTab[0]));
570 if (reader->entTab == NULL) {
571 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
572 return (0);
573 }
574 }
575 reader->entTab[reader->entNr] = value;
576 reader->ent = value;
577 return (reader->entNr++);
578}
579
580/**
581 * xmlTextReaderEntPop:
582 * @reader: the xmlTextReaderPtr used
583 *
584 * Pops the top element entity from the entities stack
585 *
586 * Returns the entity just removed
587 */
588static xmlNodePtr
589xmlTextReaderEntPop(xmlTextReaderPtr reader)
590{
591 xmlNodePtr ret;
592
593 if (reader->entNr <= 0)
594 return (0);
595 reader->entNr--;
596 if (reader->entNr > 0)
597 reader->ent = reader->entTab[reader->entNr - 1];
598 else
599 reader->ent = NULL;
600 ret = reader->entTab[reader->entNr];
601 reader->entTab[reader->entNr] = 0;
602 return (ret);
603}
604
605/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000606 * xmlTextReaderStartElement:
607 * @ctx: the user data (XML parser context)
608 * @fullname: The element name, including namespace prefix
609 * @atts: An array of name/value attributes pairs, NULL terminated
610 *
611 * called when an opening tag has been processed.
612 */
613static void
614xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
615 const xmlChar **atts) {
616 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
617 xmlTextReaderPtr reader = ctxt->_private;
618
619#ifdef DEBUG_CALLBACKS
620 printf("xmlTextReaderStartElement(%s)\n", fullname);
621#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000622 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000623 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000624 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
625 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
626 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000627 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000628 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000629 if (reader != NULL)
630 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000631}
632
633/**
634 * xmlTextReaderEndElement:
635 * @ctx: the user data (XML parser context)
636 * @fullname: The element name, including namespace prefix
637 *
638 * called when an ending tag has been processed.
639 */
640static void
641xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
642 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
643 xmlTextReaderPtr reader = ctxt->_private;
644
645#ifdef DEBUG_CALLBACKS
646 printf("xmlTextReaderEndElement(%s)\n", fullname);
647#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000648 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000649 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000650 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000651}
652
653/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000654 * xmlTextReaderStartElementNs:
655 * @ctx: the user data (XML parser context)
656 * @localname: the local name of the element
657 * @prefix: the element namespace prefix if available
658 * @URI: the element namespace name if available
659 * @nb_namespaces: number of namespace definitions on that node
660 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
661 * @nb_attributes: the number of attributes on that node
662 * nb_defaulted: the number of defaulted attributes.
663 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
664 * attribute values.
665 *
666 * called when an opening tag has been processed.
667 */
668static void
669xmlTextReaderStartElementNs(void *ctx,
670 const xmlChar *localname,
671 const xmlChar *prefix,
672 const xmlChar *URI,
673 int nb_namespaces,
674 const xmlChar **namespaces,
675 int nb_attributes,
676 int nb_defaulted,
677 const xmlChar **attributes)
678{
679 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
680 xmlTextReaderPtr reader = ctxt->_private;
681
682#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000683 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000684#endif
685 if ((reader != NULL) && (reader->startElementNs != NULL)) {
686 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
687 namespaces, nb_attributes, nb_defaulted,
688 attributes);
689 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
690 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
691 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000692 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000693 }
694 if (reader != NULL)
695 reader->state = XML_TEXTREADER_ELEMENT;
696}
697
698/**
699 * xmlTextReaderEndElementNs:
700 * @ctx: the user data (XML parser context)
701 * @localname: the local name of the element
702 * @prefix: the element namespace prefix if available
703 * @URI: the element namespace name if available
704 *
705 * called when an ending tag has been processed.
706 */
707static void
708xmlTextReaderEndElementNs(void *ctx,
709 const xmlChar * localname,
710 const xmlChar * prefix,
711 const xmlChar * URI)
712{
713 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
714 xmlTextReaderPtr reader = ctxt->_private;
715
716#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000717 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000718#endif
719 if ((reader != NULL) && (reader->endElementNs != NULL)) {
720 reader->endElementNs(ctx, localname, prefix, URI);
721 }
722}
723
724
725/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000726 * xmlTextReaderCharacters:
727 * @ctx: the user data (XML parser context)
728 * @ch: a xmlChar string
729 * @len: the number of xmlChar
730 *
731 * receiving some chars from the parser.
732 */
733static void
734xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
735{
736 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
737 xmlTextReaderPtr reader = ctxt->_private;
738
739#ifdef DEBUG_CALLBACKS
740 printf("xmlTextReaderCharacters()\n");
741#endif
742 if ((reader != NULL) && (reader->characters != NULL)) {
743 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000744 }
745}
746
747/**
748 * xmlTextReaderCDataBlock:
749 * @ctx: the user data (XML parser context)
750 * @value: The pcdata content
751 * @len: the block length
752 *
753 * called when a pcdata block has been parsed
754 */
755static void
756xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
757{
758 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
759 xmlTextReaderPtr reader = ctxt->_private;
760
761#ifdef DEBUG_CALLBACKS
762 printf("xmlTextReaderCDataBlock()\n");
763#endif
764 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
765 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000766 }
767}
768
769/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000770 * xmlTextReaderPushData:
771 * @reader: the xmlTextReaderPtr used
772 *
773 * Push data down the progressive parser until a significant callback
774 * got raised.
775 *
776 * Returns -1 in case of failure, 0 otherwise
777 */
778static int
779xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000780 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000781 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000782 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000783
784 if ((reader->input == NULL) || (reader->input->buffer == NULL))
785 return(-1);
786
Daniel Veillardea7751d2002-12-20 00:16:24 +0000787 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000788 reader->state = XML_TEXTREADER_NONE;
789 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000790
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000791 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000792 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000793 /*
794 * Refill the buffer unless we are at the end of the stream
795 */
796 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
797 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000798 if ((val == 0) &&
799 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
800 if (inbuf->use == reader->cur) {
801 reader->mode = XML_TEXTREADER_MODE_EOF;
802 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000803 }
804 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000805 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000806 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000807 if ((oldstate != XML_TEXTREADER_START) ||
808 (reader->ctxt->myDoc != NULL))
809 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000810 } else if (val == 0) {
811 /* mark the end of the stream and process the remains */
812 reader->mode = XML_TEXTREADER_MODE_EOF;
813 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000814 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000815
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000816 } else
817 break;
818 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000819 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000820 * parse by block of CHUNK_SIZE bytes, various tests show that
821 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000822 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000823 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000824 val = xmlParseChunk(reader->ctxt,
825 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000826 CHUNK_SIZE, 0);
827 reader->cur += CHUNK_SIZE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000828 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000829 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000830 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000831 s = inbuf->use - reader->cur;
832 val = xmlParseChunk(reader->ctxt,
833 (const char *) &inbuf->content[reader->cur],
834 s, 0);
835 reader->cur += s;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000836 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000837 return(-1);
838 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 }
840 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000841
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000842 /*
843 * Discard the consumed input when needed and possible
844 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000845 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000846 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
847 if ((reader->cur >= 4096) &&
848 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
849 val = xmlBufferShrink(inbuf, reader->cur);
850 if (val >= 0) {
851 reader->cur -= val;
852 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000853 }
854 }
855 }
856
857 /*
858 * At the end of the stream signal that the work is done to the Push
859 * parser.
860 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000861 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000862 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000863 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000864 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000865 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000866 s, 1);
867 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000868 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000869 if ((val != 0) && (reader->ctxt->wellFormed == 0))
870 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000871 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000872 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000873 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000874 return(0);
875}
876
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000877#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000878/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000879 * xmlTextReaderValidatePush:
880 * @reader: the xmlTextReaderPtr used
881 *
882 * Push the current node for validation
883 */
884static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000885xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000886 xmlNodePtr node = reader->node;
887
Daniel Veillardf54cd532004-02-25 11:52:31 +0000888#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000889 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
890 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
891 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
892 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
893 reader->ctxt->myDoc, node, node->name);
894 } else {
895 /* TODO use the BuildQName interface */
896 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000897
Daniel Veillardf4e55762003-04-15 23:32:22 +0000898 qname = xmlStrdup(node->ns->prefix);
899 qname = xmlStrcat(qname, BAD_CAST ":");
900 qname = xmlStrcat(qname, node->name);
901 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
902 reader->ctxt->myDoc, node, qname);
903 if (qname != NULL)
904 xmlFree(qname);
905 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000906 }
907#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000908#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000909 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000910 (reader->rngValidCtxt != NULL)) {
911 int ret;
912
913 if (reader->rngFullNode != NULL) return;
914 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
915 reader->ctxt->myDoc,
916 node);
917 if (ret == 0) {
918 /*
919 * this element requires a full tree
920 */
921 node = xmlTextReaderExpand(reader);
922 if (node == NULL) {
923printf("Expand failed !\n");
924 ret = -1;
925 } else {
926 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
927 reader->ctxt->myDoc,
928 node);
929 reader->rngFullNode = node;
930 }
931 }
932 if (ret != 1)
933 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000934 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000935#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000936}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000937
938/**
939 * xmlTextReaderValidateCData:
940 * @reader: the xmlTextReaderPtr used
941 * @data: pointer to the CData
942 * @len: lenght of the CData block in bytes.
943 *
944 * Push some CData for validation
945 */
946static void
947xmlTextReaderValidateCData(xmlTextReaderPtr reader,
948 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000949#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000950 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
951 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
952 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
953 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000954 }
955#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000956#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000957 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000958 (reader->rngValidCtxt != NULL)) {
959 int ret;
960
961 if (reader->rngFullNode != NULL) return;
962 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
963 if (ret != 1)
964 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000966#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000967}
968
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000969/**
970 * xmlTextReaderValidatePop:
971 * @reader: the xmlTextReaderPtr used
972 *
973 * Pop the current node from validation
974 */
975static void
976xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
977 xmlNodePtr node = reader->node;
978
Daniel Veillardf54cd532004-02-25 11:52:31 +0000979#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000980 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
981 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
982 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
983 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
984 reader->ctxt->myDoc, node, node->name);
985 } else {
986 /* TODO use the BuildQName interface */
987 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000988
Daniel Veillardf4e55762003-04-15 23:32:22 +0000989 qname = xmlStrdup(node->ns->prefix);
990 qname = xmlStrcat(qname, BAD_CAST ":");
991 qname = xmlStrcat(qname, node->name);
992 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
993 reader->ctxt->myDoc, node, qname);
994 if (qname != NULL)
995 xmlFree(qname);
996 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000997 }
998#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000999#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001000 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001001 (reader->rngValidCtxt != NULL)) {
1002 int ret;
1003
1004 if (reader->rngFullNode != NULL) {
1005 if (node == reader->rngFullNode)
1006 reader->rngFullNode = NULL;
1007 return;
1008 }
1009 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1010 reader->ctxt->myDoc,
1011 node);
1012 if (ret != 1)
1013 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001014 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001015#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001016}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001017
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001018/**
1019 * xmlTextReaderValidateEntity:
1020 * @reader: the xmlTextReaderPtr used
1021 *
1022 * Handle the validation when an entity reference is encountered and
1023 * entity substitution is not activated. As a result the parser interface
1024 * must walk through the entity and do the validation calls
1025 */
1026static void
1027xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1028 xmlNodePtr oldnode = reader->node;
1029 xmlNodePtr node = reader->node;
1030 xmlParserCtxtPtr ctxt = reader->ctxt;
1031
1032 do {
1033 if (node->type == XML_ENTITY_REF_NODE) {
1034 /*
1035 * Case where the underlying tree is not availble, lookup the entity
1036 * and walk it.
1037 */
1038 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1039 (ctxt->sax->getEntity != NULL)) {
1040 node->children = (xmlNodePtr)
1041 ctxt->sax->getEntity(ctxt, node->name);
1042 }
1043
1044 if ((node->children != NULL) &&
1045 (node->children->type == XML_ENTITY_DECL) &&
1046 (node->children->children != NULL)) {
1047 xmlTextReaderEntPush(reader, node);
1048 node = node->children->children;
1049 continue;
1050 } else {
1051 /*
1052 * The error has probably be raised already.
1053 */
1054 if (node == oldnode)
1055 break;
1056 node = node->next;
1057 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001058#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001059 } else if (node->type == XML_ELEMENT_NODE) {
1060 reader->node = node;
1061 xmlTextReaderValidatePush(reader);
1062 } else if ((node->type == XML_TEXT_NODE) ||
1063 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001064 xmlTextReaderValidateCData(reader, node->content,
1065 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001066#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001067 }
1068
1069 /*
1070 * go to next node
1071 */
1072 if (node->children != NULL) {
1073 node = node->children;
1074 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001075 } else if (node->type == XML_ELEMENT_NODE) {
1076 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001077 }
1078 if (node->next != NULL) {
1079 node = node->next;
1080 continue;
1081 }
1082 do {
1083 node = node->parent;
1084 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001085 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001086 if (reader->entNr == 0) {
1087 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001088 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001089 xmlUnlinkNode(tmp);
1090 xmlTextReaderFreeNode(reader, tmp);
1091 } else
1092 break;
1093 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001094 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001095 reader->node = node;
1096 xmlTextReaderValidatePop(reader);
1097 }
1098 if ((node->type == XML_ENTITY_DECL) &&
1099 (reader->ent != NULL) && (reader->ent->children == node)) {
1100 node = xmlTextReaderEntPop(reader);
1101 }
1102 if (node == oldnode)
1103 break;
1104 if (node->next != NULL) {
1105 node = node->next;
1106 break;
1107 }
1108 } while ((node != NULL) && (node != oldnode));
1109 } while ((node != NULL) && (node != oldnode));
1110 reader->node = oldnode;
1111}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001112#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001113
1114
1115/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001116 * xmlTextReaderGetSuccessor:
1117 * @cur: the current node
1118 *
1119 * Get the successor of a node if available.
1120 *
1121 * Returns the successor node or NULL
1122 */
1123static xmlNodePtr
1124xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1125 if (cur == NULL) return(NULL) ; /* ERROR */
1126 if (cur->next != NULL) return(cur->next) ;
1127 do {
1128 cur = cur->parent;
1129 if (cur == NULL) return(NULL);
1130 if (cur->next != NULL) return(cur->next);
1131 } while (cur != NULL);
1132 return(cur);
1133}
1134
1135/**
1136 * xmlTextReaderDoExpand:
1137 * @reader: the xmlTextReaderPtr used
1138 *
1139 * Makes sure that the current node is fully read as well as all its
1140 * descendant. It means the full DOM subtree must be available at the
1141 * end of the call.
1142 *
1143 * Returns 1 if the node was expanded successfully, 0 if there is no more
1144 * nodes to read, or -1 in case of error
1145 */
1146static int
1147xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1148 int val;
1149
1150 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1151 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001152 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001153 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1154
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001155 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1156 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001157 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001158 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001159 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1160 return(1);
1161 val = xmlTextReaderPushData(reader);
1162 if (val < 0)
1163 return(-1);
1164 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1165 return(1);
1166}
1167
1168/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001169 * xmlTextReaderRead:
1170 * @reader: the xmlTextReaderPtr used
1171 *
1172 * Moves the position of the current instance to the next node in
1173 * the stream, exposing its properties.
1174 *
1175 * Returns 1 if the node was read successfully, 0 if there is no more
1176 * nodes to read, or -1 in case of error
1177 */
1178int
1179xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001180 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001181 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001182 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001183
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001184
1185 if (reader == NULL)
1186 return(-1);
1187 if (reader->doc != NULL)
1188 return(xmlTextReaderReadTree(reader));
1189 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001190 return(-1);
1191 if (reader->ctxt->wellFormed != 1)
1192 return(-1);
1193
1194#ifdef DEBUG_READER
1195 fprintf(stderr, "\nREAD ");
1196 DUMP_READER
1197#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001198 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001199 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1200 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001201 /*
1202 * Initial state
1203 */
1204 do {
1205 val = xmlTextReaderPushData(reader);
1206 if (val < 0)
1207 return(-1);
1208 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001209 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1210 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001212 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001213 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001214 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001215 if (reader->node == NULL)
1216 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001217 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001218 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001219 if (reader->ctxt->myDoc != NULL) {
1220 reader->node = reader->ctxt->myDoc->children;
1221 }
1222 if (reader->node == NULL)
1223 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001224 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001225 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001226 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001227 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001228 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001229 }
1230 oldstate = reader->state;
1231 olddepth = reader->ctxt->nodeNr;
1232 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001233
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001234get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001235 if (reader->node == NULL) {
1236 if (reader->mode == XML_TEXTREADER_DONE)
1237 return(0);
1238 else
1239 return(-1);
1240 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001241
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001242 /*
1243 * If we are not backtracking on ancestors or examined nodes,
1244 * that the parser didn't finished or that we arent at the end
1245 * of stream, continue processing.
1246 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001247 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001248 (reader->ctxt->nodeNr == olddepth) &&
1249 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001250 (reader->node->children == NULL) ||
1251 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001252 ((reader->node->children != NULL) &&
1253 (reader->node->children->type == XML_TEXT_NODE) &&
1254 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001255 (reader->node->type == XML_DTD_NODE) ||
1256 (reader->node->type == XML_DOCUMENT_NODE) ||
1257 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001258 ((reader->ctxt->node == NULL) ||
1259 (reader->ctxt->node == reader->node) ||
1260 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001261 (reader->ctxt->instate != XML_PARSER_EOF)) {
1262 val = xmlTextReaderPushData(reader);
1263 if (val < 0)
1264 return(-1);
1265 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001266 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001267 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001269 if ((reader->node->children != NULL) &&
1270 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001271 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 (reader->node->type != XML_DTD_NODE)) {
1273 reader->node = reader->node->children;
1274 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001275 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001276 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001277 }
1278 }
1279 if (reader->node->next != NULL) {
1280 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001281 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001282 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001283 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1284#ifdef LIBXML_XINCLUDE_ENABLED
1285 && (reader->in_xinclude <= 0)
1286#endif
1287 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001288 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001289 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001290 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001291#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001292 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001293 (reader->node->type == XML_ELEMENT_NODE))
1294 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001295#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001296 if ((reader->preserves > 0) &&
1297 (reader->node->extra & NODE_IS_SPRESERVED))
1298 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001299 reader->node = reader->node->next;
1300 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001301
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001302 /*
1303 * Cleanup of the old node
1304 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001305 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001306#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001307 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001308#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001309 (reader->entNr == 0) &&
1310 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001311 (reader->node->prev->type != XML_DTD_NODE) &&
1312 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001313 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001314 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001315 xmlUnlinkNode(tmp);
1316 xmlTextReaderFreeNode(reader, tmp);
1317 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001318 }
1319
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001320 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001321 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001322 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001323 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001324 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001325 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001326 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001327 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001328 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001329#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001330 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001331 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001332#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001333 if ((reader->preserves > 0) &&
1334 (reader->node->extra & NODE_IS_SPRESERVED))
1335 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001336 reader->node = reader->node->parent;
1337 if ((reader->node == NULL) ||
1338 (reader->node->type == XML_DOCUMENT_NODE) ||
1339#ifdef LIBXML_DOCB_ENABLED
1340 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1341#endif
1342 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001343 if (reader->mode != XML_TEXTREADER_DONE) {
1344 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1345 reader->mode = XML_TEXTREADER_DONE;
1346 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001347 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001348 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001349
1350 /*
1351 * Cleanup of the old node
1352 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001353 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001354#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001355 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001356#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001357 (reader->entNr == 0) &&
1358 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001359 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001360 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001361 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001362 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 }
1364
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001365 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001366 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001367 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001368#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001369 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001370#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001371 (reader->entNr == 0) &&
1372 (reader->node->last != NULL) &&
1373 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1374 xmlNodePtr tmp = reader->node->last;
1375 xmlUnlinkNode(tmp);
1376 xmlTextReaderFreeNode(reader, tmp);
1377 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001378 reader->depth--;
1379 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001380
1381node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001382 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001383
1384 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001385 * If we are in the middle of a piece of CDATA make sure it's finished
1386 */
1387 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001388 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001389 ((reader->node->type == XML_TEXT_NODE) ||
1390 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1391 xmlTextReaderExpand(reader);
1392 }
1393
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001394#ifdef LIBXML_XINCLUDE_ENABLED
1395 /*
1396 * Handle XInclude if asked for
1397 */
1398 if ((reader->xinclude) && (reader->node != NULL) &&
1399 (reader->node->type == XML_ELEMENT_NODE) &&
1400 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001401 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1402 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001403 if (reader->xincctxt == NULL) {
1404 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001405 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001406 }
1407 /*
1408 * expand that node and process it
1409 */
1410 xmlTextReaderExpand(reader);
1411 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1412 }
1413 if (reader->node->type == XML_XINCLUDE_START) {
1414 reader->in_xinclude++;
1415 goto get_next_node;
1416 }
1417 if (reader->node->type == XML_XINCLUDE_END) {
1418 reader->in_xinclude--;
1419 goto get_next_node;
1420 }
1421#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001422 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001423 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001424 */
1425 if ((reader->node != NULL) &&
1426 (reader->node->type == XML_ENTITY_REF_NODE) &&
1427 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1428 /*
1429 * Case where the underlying tree is not availble, lookup the entity
1430 * and walk it.
1431 */
1432 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1433 (reader->ctxt->sax->getEntity != NULL)) {
1434 reader->node->children = (xmlNodePtr)
1435 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1436 }
1437
1438 if ((reader->node->children != NULL) &&
1439 (reader->node->children->type == XML_ENTITY_DECL) &&
1440 (reader->node->children->children != NULL)) {
1441 xmlTextReaderEntPush(reader, reader->node);
1442 reader->node = reader->node->children->children;
1443 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001444#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001445 } else if ((reader->node != NULL) &&
1446 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001447 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001448 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001449#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001450 }
1451 if ((reader->node != NULL) &&
1452 (reader->node->type == XML_ENTITY_DECL) &&
1453 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1454 reader->node = xmlTextReaderEntPop(reader);
1455 reader->depth++;
1456 goto get_next_node;
1457 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001458#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001459 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001460 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001461
1462 if ((node->type == XML_ELEMENT_NODE) &&
1463 ((reader->state != XML_TEXTREADER_END) &&
1464 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1465 xmlTextReaderValidatePush(reader);
1466 } else if ((node->type == XML_TEXT_NODE) ||
1467 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001468 xmlTextReaderValidateCData(reader, node->content,
1469 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001470 }
1471 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001472#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001473#ifdef LIBXML_PATTERN_ENABLED
1474 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1475 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1476 int i;
1477 for (i = 0;i < reader->patternNr;i++) {
1478 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1479 xmlTextReaderPreserve(reader);
1480 break;
1481 }
1482 }
1483 }
1484#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001486node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001487 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001488 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001489}
1490
Daniel Veillard67df8092002-12-16 22:04:11 +00001491/**
1492 * xmlTextReaderReadState:
1493 * @reader: the xmlTextReaderPtr used
1494 *
1495 * Gets the read state of the reader.
1496 *
1497 * Returns the state value, or -1 in case of error
1498 */
1499int
1500xmlTextReaderReadState(xmlTextReaderPtr reader) {
1501 if (reader == NULL)
1502 return(-1);
1503 return(reader->mode);
1504}
1505
1506/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001507 * xmlTextReaderExpand:
1508 * @reader: the xmlTextReaderPtr used
1509 *
1510 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001511 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001512 *
1513 * Returns a node pointer valid until the next xmlTextReaderRead() call
1514 * or NULL in case of error.
1515 */
1516xmlNodePtr
1517xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001518 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001519 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001520 if (reader->doc != NULL)
1521 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001522 if (reader->ctxt == NULL)
1523 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001524 if (xmlTextReaderDoExpand(reader) < 0)
1525 return(NULL);
1526 return(reader->node);
1527}
1528
1529/**
1530 * xmlTextReaderNext:
1531 * @reader: the xmlTextReaderPtr used
1532 *
1533 * Skip to the node following the current one in document order while
1534 * avoiding the subtree if any.
1535 *
1536 * Returns 1 if the node was read successfully, 0 if there is no more
1537 * nodes to read, or -1 in case of error
1538 */
1539int
1540xmlTextReaderNext(xmlTextReaderPtr reader) {
1541 int ret;
1542 xmlNodePtr cur;
1543
1544 if (reader == NULL)
1545 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001546 if (reader->doc != NULL)
1547 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001548 cur = reader->node;
1549 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1550 return(xmlTextReaderRead(reader));
1551 if (reader->state == XML_TEXTREADER_END)
1552 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001553 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001554 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001555 do {
1556 ret = xmlTextReaderRead(reader);
1557 if (ret != 1)
1558 return(ret);
1559 } while (reader->node != cur);
1560 return(xmlTextReaderRead(reader));
1561}
1562
1563/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001564 * xmlTextReaderReadInnerXml:
1565 * @reader: the xmlTextReaderPtr used
1566 *
1567 * Reads the contents of the current node, including child nodes and markup.
1568 *
1569 * Returns a string containing the XML content, or NULL if the current node
1570 * is neither an element nor attribute, or has no child nodes. The
1571 * string must be deallocated by the caller.
1572 */
1573xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001574xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001575 TODO
1576 return(NULL);
1577}
1578
1579/**
1580 * xmlTextReaderReadOuterXml:
1581 * @reader: the xmlTextReaderPtr used
1582 *
1583 * Reads the contents of the current node, including child nodes and markup.
1584 *
1585 * Returns a string containing the XML content, or NULL if the current node
1586 * is neither an element nor attribute, or has no child nodes. The
1587 * string must be deallocated by the caller.
1588 */
1589xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001590xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001591 TODO
1592 return(NULL);
1593}
1594
1595/**
1596 * xmlTextReaderReadString:
1597 * @reader: the xmlTextReaderPtr used
1598 *
1599 * Reads the contents of an element or a text node as a string.
1600 *
1601 * Returns a string containing the contents of the Element or Text node,
1602 * or NULL if the reader is positioned on any other type of node.
1603 * The string must be deallocated by the caller.
1604 */
1605xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001606xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001607 TODO
1608 return(NULL);
1609}
1610
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001611#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001612/**
1613 * xmlTextReaderReadBase64:
1614 * @reader: the xmlTextReaderPtr used
1615 * @array: a byte array to store the content.
1616 * @offset: the zero-based index into array where the method should
1617 * begin to write.
1618 * @len: the number of bytes to write.
1619 *
1620 * Reads and decodes the Base64 encoded contents of an element and
1621 * stores the result in a byte buffer.
1622 *
1623 * Returns the number of bytes written to array, or zero if the current
1624 * instance is not positioned on an element or -1 in case of error.
1625 */
1626int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001627xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1628 unsigned char *array ATTRIBUTE_UNUSED,
1629 int offset ATTRIBUTE_UNUSED,
1630 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001631 if ((reader == NULL) || (reader->ctxt == NULL))
1632 return(-1);
1633 if (reader->ctxt->wellFormed != 1)
1634 return(-1);
1635
1636 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1637 return(0);
1638 TODO
1639 return(0);
1640}
1641
1642/**
1643 * xmlTextReaderReadBinHex:
1644 * @reader: the xmlTextReaderPtr used
1645 * @array: a byte array to store the content.
1646 * @offset: the zero-based index into array where the method should
1647 * begin to write.
1648 * @len: the number of bytes to write.
1649 *
1650 * Reads and decodes the BinHex encoded contents of an element and
1651 * stores the result in a byte buffer.
1652 *
1653 * Returns the number of bytes written to array, or zero if the current
1654 * instance is not positioned on an element or -1 in case of error.
1655 */
1656int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001657xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1658 unsigned char *array ATTRIBUTE_UNUSED,
1659 int offset ATTRIBUTE_UNUSED,
1660 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001661 if ((reader == NULL) || (reader->ctxt == NULL))
1662 return(-1);
1663 if (reader->ctxt->wellFormed != 1)
1664 return(-1);
1665
1666 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1667 return(0);
1668 TODO
1669 return(0);
1670}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001671#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001672
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001673/************************************************************************
1674 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001675 * Operating on a preparsed tree *
1676 * *
1677 ************************************************************************/
1678static int
1679xmlTextReaderNextTree(xmlTextReaderPtr reader)
1680{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001681 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001682 return(-1);
1683
1684 if (reader->state == XML_TEXTREADER_END)
1685 return(0);
1686
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001687 if (reader->node == NULL) {
1688 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001689 reader->state = XML_TEXTREADER_END;
1690 return(0);
1691 }
1692
1693 reader->node = reader->doc->children;
1694 reader->state = XML_TEXTREADER_START;
1695 return(1);
1696 }
1697
1698 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1699 if (reader->node->children != 0) {
1700 reader->node = reader->node->children;
1701 reader->depth++;
1702 reader->state = XML_TEXTREADER_START;
1703 return(1);
1704 }
1705
1706 if ((reader->node->type == XML_ELEMENT_NODE) ||
1707 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1708 reader->state = XML_TEXTREADER_BACKTRACK;
1709 return(1);
1710 }
1711 }
1712
1713 if (reader->node->next != 0) {
1714 reader->node = reader->node->next;
1715 reader->state = XML_TEXTREADER_START;
1716 return(1);
1717 }
1718
1719 if (reader->node->parent != 0) {
1720 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1721 reader->state = XML_TEXTREADER_END;
1722 return(0);
1723 }
1724
1725 reader->node = reader->node->parent;
1726 reader->depth--;
1727 reader->state = XML_TEXTREADER_BACKTRACK;
1728 return(1);
1729 }
1730
1731 reader->state = XML_TEXTREADER_END;
1732
1733 return(1);
1734}
1735
1736/**
1737 * xmlTextReaderReadTree:
1738 * @reader: the xmlTextReaderPtr used
1739 *
1740 * Moves the position of the current instance to the next node in
1741 * the stream, exposing its properties.
1742 *
1743 * Returns 1 if the node was read successfully, 0 if there is no more
1744 * nodes to read, or -1 in case of error
1745 */
1746static int
1747xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1748 if (reader->state == XML_TEXTREADER_END)
1749 return(0);
1750
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001751next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001752 if (reader->node == NULL) {
1753 if (reader->doc->children == NULL) {
1754 reader->state = XML_TEXTREADER_END;
1755 return(0);
1756 }
1757
1758 reader->node = reader->doc->children;
1759 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001760 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001761 }
1762
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001763 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1764 (reader->node->type != XML_DTD_NODE) &&
1765 (reader->node->type != XML_XINCLUDE_START) &&
1766 (reader->node->type != XML_ENTITY_REF_NODE)) {
1767 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001768 reader->node = reader->node->children;
1769 reader->depth++;
1770 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001771 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001772 }
1773
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001774 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001775 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001776 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001777 }
1778 }
1779
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001780 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001781 reader->node = reader->node->next;
1782 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001783 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001784 }
1785
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001786 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001787 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1788 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1789 reader->state = XML_TEXTREADER_END;
1790 return(0);
1791 }
1792
1793 reader->node = reader->node->parent;
1794 reader->depth--;
1795 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001796 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001797 }
1798
1799 reader->state = XML_TEXTREADER_END;
1800
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001801found_node:
1802 if ((reader->node->type == XML_XINCLUDE_START) ||
1803 (reader->node->type == XML_XINCLUDE_END))
1804 goto next_node;
1805
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001806 return(1);
1807}
1808
1809/**
William M. Brackb1d53162003-11-18 06:54:40 +00001810 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001811 * @reader: the xmlTextReaderPtr used
1812 *
1813 * Skip to the node following the current one in document order while
1814 * avoiding the subtree if any.
1815 * Currently implemented only for Readers built on a document
1816 *
1817 * Returns 1 if the node was read successfully, 0 if there is no more
1818 * nodes to read, or -1 in case of error
1819 */
1820int
1821xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1822 if (reader == NULL)
1823 return(-1);
1824 if (reader->doc == NULL) {
1825 TODO
1826 return(-1);
1827 }
1828
1829 if (reader->state == XML_TEXTREADER_END)
1830 return(0);
1831
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001832 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001833 return(xmlTextReaderNextTree(reader));
1834
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001835 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001836 reader->node = reader->node->next;
1837 reader->state = XML_TEXTREADER_START;
1838 return(1);
1839 }
1840
1841 return(0);
1842}
1843
1844/************************************************************************
1845 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001846 * Constructor and destructors *
1847 * *
1848 ************************************************************************/
1849/**
1850 * xmlNewTextReader:
1851 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001852 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001853 *
1854 * Create an xmlTextReader structure fed with @input
1855 *
1856 * Returns the new xmlTextReaderPtr or NULL in case of error
1857 */
1858xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001859xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001860 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001861
1862 if (input == NULL)
1863 return(NULL);
1864 ret = xmlMalloc(sizeof(xmlTextReader));
1865 if (ret == NULL) {
1866 xmlGenericError(xmlGenericErrorContext,
1867 "xmlNewTextReader : malloc failed\n");
1868 return(NULL);
1869 }
1870 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001871 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001872 ret->entTab = NULL;
1873 ret->entMax = 0;
1874 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001875 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001876 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001877 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1878 if (ret->sax == NULL) {
1879 xmlFree(ret);
1880 xmlGenericError(xmlGenericErrorContext,
1881 "xmlNewTextReader : malloc failed\n");
1882 return(NULL);
1883 }
Daniel Veillard81273902003-09-30 00:43:48 +00001884 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001885 ret->startElement = ret->sax->startElement;
1886 ret->sax->startElement = xmlTextReaderStartElement;
1887 ret->endElement = ret->sax->endElement;
1888 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001889#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001890 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001891#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001892 ret->startElementNs = ret->sax->startElementNs;
1893 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1894 ret->endElementNs = ret->sax->endElementNs;
1895 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001896#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001897 } else {
1898 ret->startElementNs = NULL;
1899 ret->endElementNs = NULL;
1900 }
Daniel Veillard81273902003-09-30 00:43:48 +00001901#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001902 ret->characters = ret->sax->characters;
1903 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001904 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001905 ret->cdataBlock = ret->sax->cdataBlock;
1906 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001907
Daniel Veillard67df8092002-12-16 22:04:11 +00001908 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001909 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001910 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001911 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001912 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001913 }
1914 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001915 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001916 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001917 ret->base = 0;
1918 ret->cur = 4;
1919 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001920 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001921 ret->base = 0;
1922 ret->cur = 0;
1923 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001924
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001925 if (ret->ctxt == NULL) {
1926 xmlGenericError(xmlGenericErrorContext,
1927 "xmlNewTextReader : malloc failed\n");
1928 xmlFree(ret->sax);
1929 xmlFree(ret);
1930 return(NULL);
1931 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001932 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001933 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001934 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001935 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001936 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001937 /*
1938 * use the parser dictionnary to allocate all elements and attributes names
1939 */
1940 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001941 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001942#ifdef LIBXML_XINCLUDE_ENABLED
1943 ret->xinclude = 0;
1944#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001945#ifdef LIBXML_PATTERN_ENABLED
1946 ret->patternMax = 0;
1947 ret->patternTab = NULL;
1948#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001949 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001950}
1951
1952/**
1953 * xmlNewTextReaderFilename:
1954 * @URI: the URI of the resource to process
1955 *
1956 * Create an xmlTextReader structure fed with the resource at @URI
1957 *
1958 * Returns the new xmlTextReaderPtr or NULL in case of error
1959 */
1960xmlTextReaderPtr
1961xmlNewTextReaderFilename(const char *URI) {
1962 xmlParserInputBufferPtr input;
1963 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001964 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001965
1966 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1967 if (input == NULL)
1968 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001969 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001970 if (ret == NULL) {
1971 xmlFreeParserInputBuffer(input);
1972 return(NULL);
1973 }
1974 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001975 if (ret->ctxt->directory == NULL)
1976 directory = xmlParserGetDirectory(URI);
1977 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1978 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1979 if (directory != NULL)
1980 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001981 return(ret);
1982}
1983
1984/**
1985 * xmlFreeTextReader:
1986 * @reader: the xmlTextReaderPtr
1987 *
1988 * Deallocate all the resources associated to the reader
1989 */
1990void
1991xmlFreeTextReader(xmlTextReaderPtr reader) {
1992 if (reader == NULL)
1993 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001994#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001995 if (reader->rngSchemas != NULL) {
1996 xmlRelaxNGFree(reader->rngSchemas);
1997 reader->rngSchemas = NULL;
1998 }
1999 if (reader->rngValidCtxt != NULL) {
2000 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2001 reader->rngValidCtxt = NULL;
2002 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002003#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002004#ifdef LIBXML_XINCLUDE_ENABLED
2005 if (reader->xincctxt != NULL)
2006 xmlXIncludeFreeContext(reader->xincctxt);
2007#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002008#ifdef LIBXML_PATTERN_ENABLED
2009 if (reader->patternTab != NULL) {
2010 int i;
2011 for (i = 0;i < reader->patternNr;i++) {
2012 if (reader->patternTab[i] != NULL)
2013 xmlFreePattern(reader->patternTab[i]);
2014 }
2015 xmlFree(reader->patternTab);
2016 }
2017#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002018 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002019 if (reader->dict == reader->ctxt->dict)
2020 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002021 if (reader->ctxt->myDoc != NULL) {
2022 if (reader->preserve == 0)
2023 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2024 reader->ctxt->myDoc = NULL;
2025 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002026 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2027 (reader->ctxt->vctxt.vstateMax > 0)){
2028 xmlFree(reader->ctxt->vctxt.vstateTab);
2029 reader->ctxt->vctxt.vstateTab = 0;
2030 reader->ctxt->vctxt.vstateMax = 0;
2031 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002032 if (reader->allocs & XML_TEXTREADER_CTXT)
2033 xmlFreeParserCtxt(reader->ctxt);
2034 }
2035 if (reader->sax != NULL)
2036 xmlFree(reader->sax);
2037 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2038 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002039 if (reader->faketext != NULL) {
2040 xmlFreeNode(reader->faketext);
2041 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002042 if (reader->buffer != NULL)
2043 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002044 if (reader->entTab != NULL)
2045 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002046 if (reader->dict != NULL)
2047 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048 xmlFree(reader);
2049}
2050
2051/************************************************************************
2052 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002053 * Methods for XmlTextReader *
2054 * *
2055 ************************************************************************/
2056/**
2057 * xmlTextReaderClose:
2058 * @reader: the xmlTextReaderPtr used
2059 *
2060 * This method releases any resources allocated by the current instance
2061 * changes the state to Closed and close any underlying input.
2062 *
2063 * Returns 0 or -1 in case of error
2064 */
2065int
2066xmlTextReaderClose(xmlTextReaderPtr reader) {
2067 if (reader == NULL)
2068 return(-1);
2069 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002070 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002071 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2072 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002073 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002074 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002075 if (reader->preserve == 0)
2076 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002077 reader->ctxt->myDoc = NULL;
2078 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002079 }
2080 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2081 xmlFreeParserInputBuffer(reader->input);
2082 reader->allocs -= XML_TEXTREADER_INPUT;
2083 }
2084 return(0);
2085}
2086
2087/**
2088 * xmlTextReaderGetAttributeNo:
2089 * @reader: the xmlTextReaderPtr used
2090 * @no: the zero-based index of the attribute relative to the containing element
2091 *
2092 * Provides the value of the attribute with the specified index relative
2093 * to the containing element.
2094 *
2095 * Returns a string containing the value of the specified attribute, or NULL
2096 * in case of error. The string must be deallocated by the caller.
2097 */
2098xmlChar *
2099xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2100 xmlChar *ret;
2101 int i;
2102 xmlAttrPtr cur;
2103 xmlNsPtr ns;
2104
2105 if (reader == NULL)
2106 return(NULL);
2107 if (reader->node == NULL)
2108 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002109 if (reader->curnode != NULL)
2110 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002111 /* TODO: handle the xmlDecl */
2112 if (reader->node->type != XML_ELEMENT_NODE)
2113 return(NULL);
2114
2115 ns = reader->node->nsDef;
2116 for (i = 0;(i < no) && (ns != NULL);i++) {
2117 ns = ns->next;
2118 }
2119 if (ns != NULL)
2120 return(xmlStrdup(ns->href));
2121
2122 cur = reader->node->properties;
2123 if (cur == NULL)
2124 return(NULL);
2125 for (;i < no;i++) {
2126 cur = cur->next;
2127 if (cur == NULL)
2128 return(NULL);
2129 }
2130 /* TODO walk the DTD if present */
2131
2132 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2133 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2134 return(ret);
2135}
2136
2137/**
2138 * xmlTextReaderGetAttribute:
2139 * @reader: the xmlTextReaderPtr used
2140 * @name: the qualified name of the attribute.
2141 *
2142 * Provides the value of the attribute with the specified qualified name.
2143 *
2144 * Returns a string containing the value of the specified attribute, or NULL
2145 * in case of error. The string must be deallocated by the caller.
2146 */
2147xmlChar *
2148xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2149 xmlChar *prefix = NULL;
2150 xmlChar *localname;
2151 xmlNsPtr ns;
2152 xmlChar *ret = NULL;
2153
2154 if ((reader == NULL) || (name == NULL))
2155 return(NULL);
2156 if (reader->node == NULL)
2157 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002158 if (reader->curnode != NULL)
2159 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002160
2161 /* TODO: handle the xmlDecl */
2162 if (reader->node->type != XML_ELEMENT_NODE)
2163 return(NULL);
2164
2165 localname = xmlSplitQName2(name, &prefix);
2166 if (localname == NULL)
2167 return(xmlGetProp(reader->node, name));
2168
2169 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2170 if (ns != NULL)
2171 ret = xmlGetNsProp(reader->node, localname, ns->href);
2172
2173 if (localname != NULL)
2174 xmlFree(localname);
2175 if (prefix != NULL)
2176 xmlFree(prefix);
2177 return(ret);
2178}
2179
2180
2181/**
2182 * xmlTextReaderGetAttributeNs:
2183 * @reader: the xmlTextReaderPtr used
2184 * @localName: the local name of the attribute.
2185 * @namespaceURI: the namespace URI of the attribute.
2186 *
2187 * Provides the value of the specified attribute
2188 *
2189 * Returns a string containing the value of the specified attribute, or NULL
2190 * in case of error. The string must be deallocated by the caller.
2191 */
2192xmlChar *
2193xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2194 const xmlChar *namespaceURI) {
2195 if ((reader == NULL) || (localName == NULL))
2196 return(NULL);
2197 if (reader->node == NULL)
2198 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002199 if (reader->curnode != NULL)
2200 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002201
2202 /* TODO: handle the xmlDecl */
2203 if (reader->node->type != XML_ELEMENT_NODE)
2204 return(NULL);
2205
2206 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2207}
2208
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002209/**
2210 * xmlTextReaderGetRemainder:
2211 * @reader: the xmlTextReaderPtr used
2212 *
2213 * Method to get the remainder of the buffered XML. this method stops the
2214 * parser, set its state to End Of File and return the input stream with
2215 * what is left that the parser did not use.
2216 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002217 * The implementation is not good, the parser certainly procgressed past
2218 * what's left in reader->input, and there is an allocation problem. Best
2219 * would be to rewrite it differently.
2220 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002221 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2222 * in case of error.
2223 */
2224xmlParserInputBufferPtr
2225xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2226 xmlParserInputBufferPtr ret = NULL;
2227
2228 if (reader == NULL)
2229 return(NULL);
2230 if (reader->node == NULL)
2231 return(NULL);
2232
2233 reader->node = NULL;
2234 reader->curnode = NULL;
2235 reader->mode = XML_TEXTREADER_MODE_EOF;
2236 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002237 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002238 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002239 if (reader->preserve == 0)
2240 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002241 reader->ctxt->myDoc = NULL;
2242 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002243 }
2244 if (reader->allocs & XML_TEXTREADER_INPUT) {
2245 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002246 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002247 reader->allocs -= XML_TEXTREADER_INPUT;
2248 } else {
2249 /*
2250 * Hum, one may need to duplicate the data structure because
2251 * without reference counting the input may be freed twice:
2252 * - by the layer which allocated it.
2253 * - by the layer to which would have been returned to.
2254 */
2255 TODO
2256 return(NULL);
2257 }
2258 return(ret);
2259}
2260
2261/**
2262 * xmlTextReaderLookupNamespace:
2263 * @reader: the xmlTextReaderPtr used
2264 * @prefix: the prefix whose namespace URI is to be resolved. To return
2265 * the default namespace, specify NULL
2266 *
2267 * Resolves a namespace prefix in the scope of the current element.
2268 *
2269 * Returns a string containing the namespace URI to which the prefix maps
2270 * or NULL in case of error. The string must be deallocated by the caller.
2271 */
2272xmlChar *
2273xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2274 xmlNsPtr ns;
2275
2276 if (reader == NULL)
2277 return(NULL);
2278 if (reader->node == NULL)
2279 return(NULL);
2280
2281 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2282 if (ns == NULL)
2283 return(NULL);
2284 return(xmlStrdup(ns->href));
2285}
2286
2287/**
2288 * xmlTextReaderMoveToAttributeNo:
2289 * @reader: the xmlTextReaderPtr used
2290 * @no: the zero-based index of the attribute relative to the containing
2291 * element.
2292 *
2293 * Moves the position of the current instance to the attribute with
2294 * the specified index relative to the containing element.
2295 *
2296 * Returns 1 in case of success, -1 in case of error, 0 if not found
2297 */
2298int
2299xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2300 int i;
2301 xmlAttrPtr cur;
2302 xmlNsPtr ns;
2303
2304 if (reader == NULL)
2305 return(-1);
2306 if (reader->node == NULL)
2307 return(-1);
2308 /* TODO: handle the xmlDecl */
2309 if (reader->node->type != XML_ELEMENT_NODE)
2310 return(-1);
2311
2312 reader->curnode = NULL;
2313
2314 ns = reader->node->nsDef;
2315 for (i = 0;(i < no) && (ns != NULL);i++) {
2316 ns = ns->next;
2317 }
2318 if (ns != NULL) {
2319 reader->curnode = (xmlNodePtr) ns;
2320 return(1);
2321 }
2322
2323 cur = reader->node->properties;
2324 if (cur == NULL)
2325 return(0);
2326 for (;i < no;i++) {
2327 cur = cur->next;
2328 if (cur == NULL)
2329 return(0);
2330 }
2331 /* TODO walk the DTD if present */
2332
2333 reader->curnode = (xmlNodePtr) cur;
2334 return(1);
2335}
2336
2337/**
2338 * xmlTextReaderMoveToAttribute:
2339 * @reader: the xmlTextReaderPtr used
2340 * @name: the qualified name of the attribute.
2341 *
2342 * Moves the position of the current instance to the attribute with
2343 * the specified qualified name.
2344 *
2345 * Returns 1 in case of success, -1 in case of error, 0 if not found
2346 */
2347int
2348xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2349 xmlChar *prefix = NULL;
2350 xmlChar *localname;
2351 xmlNsPtr ns;
2352 xmlAttrPtr prop;
2353
2354 if ((reader == NULL) || (name == NULL))
2355 return(-1);
2356 if (reader->node == NULL)
2357 return(-1);
2358
2359 /* TODO: handle the xmlDecl */
2360 if (reader->node->type != XML_ELEMENT_NODE)
2361 return(0);
2362
2363 localname = xmlSplitQName2(name, &prefix);
2364 if (localname == NULL) {
2365 /*
2366 * Namespace default decl
2367 */
2368 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2369 ns = reader->node->nsDef;
2370 while (ns != NULL) {
2371 if (ns->prefix == NULL) {
2372 reader->curnode = (xmlNodePtr) ns;
2373 return(1);
2374 }
2375 ns = ns->next;
2376 }
2377 return(0);
2378 }
2379
2380 prop = reader->node->properties;
2381 while (prop != NULL) {
2382 /*
2383 * One need to have
2384 * - same attribute names
2385 * - and the attribute carrying that namespace
2386 */
2387 if ((xmlStrEqual(prop->name, name)) &&
2388 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2389 reader->curnode = (xmlNodePtr) prop;
2390 return(1);
2391 }
2392 prop = prop->next;
2393 }
2394 return(0);
2395 }
2396
2397 /*
2398 * Namespace default decl
2399 */
2400 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2401 ns = reader->node->nsDef;
2402 while (ns != NULL) {
2403 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2404 reader->curnode = (xmlNodePtr) ns;
2405 goto found;
2406 }
2407 ns = ns->next;
2408 }
2409 goto not_found;
2410 }
2411 prop = reader->node->properties;
2412 while (prop != NULL) {
2413 /*
2414 * One need to have
2415 * - same attribute names
2416 * - and the attribute carrying that namespace
2417 */
2418 if ((xmlStrEqual(prop->name, localname)) &&
2419 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2420 reader->curnode = (xmlNodePtr) prop;
2421 goto found;
2422 }
2423 prop = prop->next;
2424 }
2425not_found:
2426 if (localname != NULL)
2427 xmlFree(localname);
2428 if (prefix != NULL)
2429 xmlFree(prefix);
2430 return(0);
2431
2432found:
2433 if (localname != NULL)
2434 xmlFree(localname);
2435 if (prefix != NULL)
2436 xmlFree(prefix);
2437 return(1);
2438}
2439
2440/**
2441 * xmlTextReaderMoveToAttributeNs:
2442 * @reader: the xmlTextReaderPtr used
2443 * @localName: the local name of the attribute.
2444 * @namespaceURI: the namespace URI of the attribute.
2445 *
2446 * Moves the position of the current instance to the attribute with the
2447 * specified local name and namespace URI.
2448 *
2449 * Returns 1 in case of success, -1 in case of error, 0 if not found
2450 */
2451int
2452xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2453 const xmlChar *localName, const xmlChar *namespaceURI) {
2454 xmlAttrPtr prop;
2455 xmlNodePtr node;
2456
2457 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2458 return(-1);
2459 if (reader->node == NULL)
2460 return(-1);
2461 if (reader->node->type != XML_ELEMENT_NODE)
2462 return(0);
2463 node = reader->node;
2464
2465 /*
2466 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2467 * namespace name associated to "xmlns"
2468 */
2469 prop = node->properties;
2470 while (prop != NULL) {
2471 /*
2472 * One need to have
2473 * - same attribute names
2474 * - and the attribute carrying that namespace
2475 */
2476 if (xmlStrEqual(prop->name, localName) &&
2477 ((prop->ns != NULL) &&
2478 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2479 reader->curnode = (xmlNodePtr) prop;
2480 return(1);
2481 }
2482 prop = prop->next;
2483 }
2484 return(0);
2485}
2486
2487/**
2488 * xmlTextReaderMoveToFirstAttribute:
2489 * @reader: the xmlTextReaderPtr used
2490 *
2491 * Moves the position of the current instance to the first attribute
2492 * associated with the current node.
2493 *
2494 * Returns 1 in case of success, -1 in case of error, 0 if not found
2495 */
2496int
2497xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2498 if (reader == NULL)
2499 return(-1);
2500 if (reader->node == NULL)
2501 return(-1);
2502 if (reader->node->type != XML_ELEMENT_NODE)
2503 return(0);
2504
2505 if (reader->node->nsDef != NULL) {
2506 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2507 return(1);
2508 }
2509 if (reader->node->properties != NULL) {
2510 reader->curnode = (xmlNodePtr) reader->node->properties;
2511 return(1);
2512 }
2513 return(0);
2514}
2515
2516/**
2517 * xmlTextReaderMoveToNextAttribute:
2518 * @reader: the xmlTextReaderPtr used
2519 *
2520 * Moves the position of the current instance to the next attribute
2521 * associated with the current node.
2522 *
2523 * Returns 1 in case of success, -1 in case of error, 0 if not found
2524 */
2525int
2526xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2527 if (reader == NULL)
2528 return(-1);
2529 if (reader->node == NULL)
2530 return(-1);
2531 if (reader->node->type != XML_ELEMENT_NODE)
2532 return(0);
2533 if (reader->curnode == NULL)
2534 return(xmlTextReaderMoveToFirstAttribute(reader));
2535
2536 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2537 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2538 if (ns->next != NULL) {
2539 reader->curnode = (xmlNodePtr) ns->next;
2540 return(1);
2541 }
2542 if (reader->node->properties != NULL) {
2543 reader->curnode = (xmlNodePtr) reader->node->properties;
2544 return(1);
2545 }
2546 return(0);
2547 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2548 (reader->curnode->next != NULL)) {
2549 reader->curnode = reader->curnode->next;
2550 return(1);
2551 }
2552 return(0);
2553}
2554
2555/**
2556 * xmlTextReaderMoveToElement:
2557 * @reader: the xmlTextReaderPtr used
2558 *
2559 * Moves the position of the current instance to the node that
2560 * contains the current Attribute node.
2561 *
2562 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2563 */
2564int
2565xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2566 if (reader == NULL)
2567 return(-1);
2568 if (reader->node == NULL)
2569 return(-1);
2570 if (reader->node->type != XML_ELEMENT_NODE)
2571 return(0);
2572 if (reader->curnode != NULL) {
2573 reader->curnode = NULL;
2574 return(1);
2575 }
2576 return(0);
2577}
2578
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002579/**
2580 * xmlTextReaderReadAttributeValue:
2581 * @reader: the xmlTextReaderPtr used
2582 *
2583 * Parses an attribute value into one or more Text and EntityReference nodes.
2584 *
2585 * Returns 1 in case of success, 0 if the reader was not positionned on an
2586 * ttribute node or all the attribute values have been read, or -1
2587 * in case of error.
2588 */
2589int
2590xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2591 if (reader == NULL)
2592 return(-1);
2593 if (reader->node == NULL)
2594 return(-1);
2595 if (reader->curnode == NULL)
2596 return(0);
2597 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2598 if (reader->curnode->children == NULL)
2599 return(0);
2600 reader->curnode = reader->curnode->children;
2601 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2602 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2603
2604 if (reader->faketext == NULL) {
2605 reader->faketext = xmlNewDocText(reader->node->doc,
2606 ns->href);
2607 } else {
2608 if (reader->faketext->content != NULL)
2609 xmlFree(reader->faketext->content);
2610 reader->faketext->content = xmlStrdup(ns->href);
2611 }
2612 reader->curnode = reader->faketext;
2613 } else {
2614 if (reader->curnode->next == NULL)
2615 return(0);
2616 reader->curnode = reader->curnode->next;
2617 }
2618 return(1);
2619}
2620
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002621/************************************************************************
2622 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002623 * Acces API to the current node *
2624 * *
2625 ************************************************************************/
2626/**
2627 * xmlTextReaderAttributeCount:
2628 * @reader: the xmlTextReaderPtr used
2629 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002630 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002631 *
2632 * Returns 0 i no attributes, -1 in case of error or the attribute count
2633 */
2634int
2635xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2636 int ret;
2637 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002638 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002639 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002640
2641 if (reader == NULL)
2642 return(-1);
2643 if (reader->node == NULL)
2644 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002645
2646 if (reader->curnode != NULL)
2647 node = reader->curnode;
2648 else
2649 node = reader->node;
2650
2651 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002652 return(0);
2653 if ((reader->state == XML_TEXTREADER_END) ||
2654 (reader->state == XML_TEXTREADER_BACKTRACK))
2655 return(0);
2656 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002657 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002658 while (attr != NULL) {
2659 ret++;
2660 attr = attr->next;
2661 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002662 ns = node->nsDef;
2663 while (ns != NULL) {
2664 ret++;
2665 ns = ns->next;
2666 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002667 return(ret);
2668}
2669
2670/**
2671 * xmlTextReaderNodeType:
2672 * @reader: the xmlTextReaderPtr used
2673 *
2674 * Get the node type of the current node
2675 * Reference:
2676 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2677 *
2678 * Returns the xmlNodeType of the current node or -1 in case of error
2679 */
2680int
2681xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002682 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002683
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002684 if (reader == NULL)
2685 return(-1);
2686 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002687 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002688 if (reader->curnode != NULL)
2689 node = reader->curnode;
2690 else
2691 node = reader->node;
2692 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002693 case XML_ELEMENT_NODE:
2694 if ((reader->state == XML_TEXTREADER_END) ||
2695 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002696 return(XML_READER_TYPE_END_ELEMENT);
2697 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002698 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002699 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002700 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002701 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002702 if (xmlIsBlankNode(reader->node)) {
2703 if (xmlNodeGetSpacePreserve(reader->node))
2704 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2705 else
2706 return(XML_READER_TYPE_WHITESPACE);
2707 } else {
2708 return(XML_READER_TYPE_TEXT);
2709 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002710 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002711 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002712 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002713 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002714 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002715 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002716 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002717 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002718 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002719 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002720 case XML_DOCUMENT_NODE:
2721 case XML_HTML_DOCUMENT_NODE:
2722#ifdef LIBXML_DOCB_ENABLED
2723 case XML_DOCB_DOCUMENT_NODE:
2724#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002725 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002726 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002727 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002728 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002729 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002730 case XML_DOCUMENT_TYPE_NODE:
2731 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002732 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002733
2734 case XML_ELEMENT_DECL:
2735 case XML_ATTRIBUTE_DECL:
2736 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002737 case XML_XINCLUDE_START:
2738 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002739 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002740 }
2741 return(-1);
2742}
2743
2744/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002745 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002746 * @reader: the xmlTextReaderPtr used
2747 *
2748 * Check if the current node is empty
2749 *
2750 * Returns 1 if empty, 0 if not and -1 in case of error
2751 */
2752int
2753xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2754 if ((reader == NULL) || (reader->node == NULL))
2755 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002756 if (reader->node->type != XML_ELEMENT_NODE)
2757 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002758 if (reader->curnode != NULL)
2759 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002760 if (reader->node->children != NULL)
2761 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002762 if (reader->state == XML_TEXTREADER_END)
2763 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002764 if (reader->doc != NULL)
2765 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002766#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002767 if (reader->in_xinclude > 0)
2768 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002769#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002770 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002771}
2772
2773/**
2774 * xmlTextReaderLocalName:
2775 * @reader: the xmlTextReaderPtr used
2776 *
2777 * The local name of the node.
2778 *
2779 * Returns the local name or NULL if not available
2780 */
2781xmlChar *
2782xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002783 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002784 if ((reader == NULL) || (reader->node == NULL))
2785 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002786 if (reader->curnode != NULL)
2787 node = reader->curnode;
2788 else
2789 node = reader->node;
2790 if (node->type == XML_NAMESPACE_DECL) {
2791 xmlNsPtr ns = (xmlNsPtr) node;
2792 if (ns->prefix == NULL)
2793 return(xmlStrdup(BAD_CAST "xmlns"));
2794 else
2795 return(xmlStrdup(ns->prefix));
2796 }
2797 if ((node->type != XML_ELEMENT_NODE) &&
2798 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002799 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002800 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002801}
2802
2803/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002804 * xmlTextReaderConstLocalName:
2805 * @reader: the xmlTextReaderPtr used
2806 *
2807 * The local name of the node.
2808 *
2809 * Returns the local name or NULL if not available, the
2810 * string will be deallocated with the reader.
2811 */
2812const xmlChar *
2813xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2814 xmlNodePtr node;
2815 if ((reader == NULL) || (reader->node == NULL))
2816 return(NULL);
2817 if (reader->curnode != NULL)
2818 node = reader->curnode;
2819 else
2820 node = reader->node;
2821 if (node->type == XML_NAMESPACE_DECL) {
2822 xmlNsPtr ns = (xmlNsPtr) node;
2823 if (ns->prefix == NULL)
2824 return(CONSTSTR(BAD_CAST "xmlns"));
2825 else
2826 return(ns->prefix);
2827 }
2828 if ((node->type != XML_ELEMENT_NODE) &&
2829 (node->type != XML_ATTRIBUTE_NODE))
2830 return(xmlTextReaderConstName(reader));
2831 return(node->name);
2832}
2833
2834/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002835 * xmlTextReaderName:
2836 * @reader: the xmlTextReaderPtr used
2837 *
2838 * The qualified name of the node, equal to Prefix :LocalName.
2839 *
2840 * Returns the local name or NULL if not available
2841 */
2842xmlChar *
2843xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002844 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002845 xmlChar *ret;
2846
2847 if ((reader == NULL) || (reader->node == NULL))
2848 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002849 if (reader->curnode != NULL)
2850 node = reader->curnode;
2851 else
2852 node = reader->node;
2853 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002854 case XML_ELEMENT_NODE:
2855 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002856 if ((node->ns == NULL) ||
2857 (node->ns->prefix == NULL))
2858 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002859
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002860 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002861 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002862 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002863 return(ret);
2864 case XML_TEXT_NODE:
2865 return(xmlStrdup(BAD_CAST "#text"));
2866 case XML_CDATA_SECTION_NODE:
2867 return(xmlStrdup(BAD_CAST "#cdata-section"));
2868 case XML_ENTITY_NODE:
2869 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002870 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002871 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002872 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002873 case XML_COMMENT_NODE:
2874 return(xmlStrdup(BAD_CAST "#comment"));
2875 case XML_DOCUMENT_NODE:
2876 case XML_HTML_DOCUMENT_NODE:
2877#ifdef LIBXML_DOCB_ENABLED
2878 case XML_DOCB_DOCUMENT_NODE:
2879#endif
2880 return(xmlStrdup(BAD_CAST "#document"));
2881 case XML_DOCUMENT_FRAG_NODE:
2882 return(xmlStrdup(BAD_CAST "#document-fragment"));
2883 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002884 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002885 case XML_DOCUMENT_TYPE_NODE:
2886 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002887 return(xmlStrdup(node->name));
2888 case XML_NAMESPACE_DECL: {
2889 xmlNsPtr ns = (xmlNsPtr) node;
2890
2891 ret = xmlStrdup(BAD_CAST "xmlns");
2892 if (ns->prefix == NULL)
2893 return(ret);
2894 ret = xmlStrcat(ret, BAD_CAST ":");
2895 ret = xmlStrcat(ret, ns->prefix);
2896 return(ret);
2897 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002898
2899 case XML_ELEMENT_DECL:
2900 case XML_ATTRIBUTE_DECL:
2901 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002902 case XML_XINCLUDE_START:
2903 case XML_XINCLUDE_END:
2904 return(NULL);
2905 }
2906 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002907}
2908
2909/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002910 * xmlTextReaderConstName:
2911 * @reader: the xmlTextReaderPtr used
2912 *
2913 * The qualified name of the node, equal to Prefix :LocalName.
2914 *
2915 * Returns the local name or NULL if not available, the string is
2916 * deallocated with the reader.
2917 */
2918const xmlChar *
2919xmlTextReaderConstName(xmlTextReaderPtr reader) {
2920 xmlNodePtr node;
2921
2922 if ((reader == NULL) || (reader->node == NULL))
2923 return(NULL);
2924 if (reader->curnode != NULL)
2925 node = reader->curnode;
2926 else
2927 node = reader->node;
2928 switch (node->type) {
2929 case XML_ELEMENT_NODE:
2930 case XML_ATTRIBUTE_NODE:
2931 if ((node->ns == NULL) ||
2932 (node->ns->prefix == NULL))
2933 return(node->name);
2934 return(CONSTQSTR(node->ns->prefix, node->name));
2935 case XML_TEXT_NODE:
2936 return(CONSTSTR(BAD_CAST "#text"));
2937 case XML_CDATA_SECTION_NODE:
2938 return(CONSTSTR(BAD_CAST "#cdata-section"));
2939 case XML_ENTITY_NODE:
2940 case XML_ENTITY_REF_NODE:
2941 return(CONSTSTR(node->name));
2942 case XML_PI_NODE:
2943 return(CONSTSTR(node->name));
2944 case XML_COMMENT_NODE:
2945 return(CONSTSTR(BAD_CAST "#comment"));
2946 case XML_DOCUMENT_NODE:
2947 case XML_HTML_DOCUMENT_NODE:
2948#ifdef LIBXML_DOCB_ENABLED
2949 case XML_DOCB_DOCUMENT_NODE:
2950#endif
2951 return(CONSTSTR(BAD_CAST "#document"));
2952 case XML_DOCUMENT_FRAG_NODE:
2953 return(CONSTSTR(BAD_CAST "#document-fragment"));
2954 case XML_NOTATION_NODE:
2955 return(CONSTSTR(node->name));
2956 case XML_DOCUMENT_TYPE_NODE:
2957 case XML_DTD_NODE:
2958 return(CONSTSTR(node->name));
2959 case XML_NAMESPACE_DECL: {
2960 xmlNsPtr ns = (xmlNsPtr) node;
2961
2962 if (ns->prefix == NULL)
2963 return(CONSTSTR(BAD_CAST "xmlns"));
2964 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2965 }
2966
2967 case XML_ELEMENT_DECL:
2968 case XML_ATTRIBUTE_DECL:
2969 case XML_ENTITY_DECL:
2970 case XML_XINCLUDE_START:
2971 case XML_XINCLUDE_END:
2972 return(NULL);
2973 }
2974 return(NULL);
2975}
2976
2977/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002978 * xmlTextReaderPrefix:
2979 * @reader: the xmlTextReaderPtr used
2980 *
2981 * A shorthand reference to the namespace associated with the node.
2982 *
2983 * Returns the prefix or NULL if not available
2984 */
2985xmlChar *
2986xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002987 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002988 if ((reader == NULL) || (reader->node == NULL))
2989 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002990 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(NULL);
2998 return(xmlStrdup(BAD_CAST "xmlns"));
2999 }
3000 if ((node->type != XML_ELEMENT_NODE) &&
3001 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003002 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003003 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003004 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003005 return(NULL);
3006}
3007
3008/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003009 * xmlTextReaderConstPrefix:
3010 * @reader: the xmlTextReaderPtr used
3011 *
3012 * A shorthand reference to the namespace associated with the node.
3013 *
3014 * Returns the prefix or NULL if not available, the string is deallocated
3015 * with the reader.
3016 */
3017const xmlChar *
3018xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3019 xmlNodePtr node;
3020 if ((reader == NULL) || (reader->node == NULL))
3021 return(NULL);
3022 if (reader->curnode != NULL)
3023 node = reader->curnode;
3024 else
3025 node = reader->node;
3026 if (node->type == XML_NAMESPACE_DECL) {
3027 xmlNsPtr ns = (xmlNsPtr) node;
3028 if (ns->prefix == NULL)
3029 return(NULL);
3030 return(CONSTSTR(BAD_CAST "xmlns"));
3031 }
3032 if ((node->type != XML_ELEMENT_NODE) &&
3033 (node->type != XML_ATTRIBUTE_NODE))
3034 return(NULL);
3035 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3036 return(CONSTSTR(node->ns->prefix));
3037 return(NULL);
3038}
3039
3040/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003041 * xmlTextReaderNamespaceUri:
3042 * @reader: the xmlTextReaderPtr used
3043 *
3044 * The URI defining the namespace associated with the node.
3045 *
3046 * Returns the namespace URI or NULL if not available
3047 */
3048xmlChar *
3049xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003050 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003051 if ((reader == NULL) || (reader->node == NULL))
3052 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003053 if (reader->curnode != NULL)
3054 node = reader->curnode;
3055 else
3056 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003057 if (node->type == XML_NAMESPACE_DECL)
3058 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003059 if ((node->type != XML_ELEMENT_NODE) &&
3060 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003061 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003062 if (node->ns != NULL)
3063 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003064 return(NULL);
3065}
3066
3067/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003068 * xmlTextReaderConstNamespaceUri:
3069 * @reader: the xmlTextReaderPtr used
3070 *
3071 * The URI defining the namespace associated with the node.
3072 *
3073 * Returns the namespace URI or NULL if not available, the string
3074 * will be deallocated with the reader
3075 */
3076const xmlChar *
3077xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3078 xmlNodePtr node;
3079 if ((reader == NULL) || (reader->node == NULL))
3080 return(NULL);
3081 if (reader->curnode != NULL)
3082 node = reader->curnode;
3083 else
3084 node = reader->node;
3085 if (node->type == XML_NAMESPACE_DECL)
3086 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3087 if ((node->type != XML_ELEMENT_NODE) &&
3088 (node->type != XML_ATTRIBUTE_NODE))
3089 return(NULL);
3090 if (node->ns != NULL)
3091 return(CONSTSTR(node->ns->href));
3092 return(NULL);
3093}
3094
3095/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003096 * xmlTextReaderBaseUri:
3097 * @reader: the xmlTextReaderPtr used
3098 *
3099 * The base URI of the node.
3100 *
3101 * Returns the base URI or NULL if not available
3102 */
3103xmlChar *
3104xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3105 if ((reader == NULL) || (reader->node == NULL))
3106 return(NULL);
3107 return(xmlNodeGetBase(NULL, reader->node));
3108}
3109
3110/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003111 * xmlTextReaderConstBaseUri:
3112 * @reader: the xmlTextReaderPtr used
3113 *
3114 * The base URI of the node.
3115 *
3116 * Returns the base URI or NULL if not available, the string
3117 * will be deallocated with the reader
3118 */
3119const xmlChar *
3120xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3121 xmlChar *tmp;
3122 const xmlChar *ret;
3123
3124 if ((reader == NULL) || (reader->node == NULL))
3125 return(NULL);
3126 tmp = xmlNodeGetBase(NULL, reader->node);
3127 if (tmp == NULL)
3128 return(NULL);
3129 ret = CONSTSTR(tmp);
3130 xmlFree(tmp);
3131 return(ret);
3132}
3133
3134/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003135 * xmlTextReaderDepth:
3136 * @reader: the xmlTextReaderPtr used
3137 *
3138 * The depth of the node in the tree.
3139 *
3140 * Returns the depth or -1 in case of error
3141 */
3142int
3143xmlTextReaderDepth(xmlTextReaderPtr reader) {
3144 if (reader == NULL)
3145 return(-1);
3146 if (reader->node == NULL)
3147 return(0);
3148
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003149 if (reader->curnode != NULL) {
3150 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3151 (reader->curnode->type == XML_NAMESPACE_DECL))
3152 return(reader->depth + 1);
3153 return(reader->depth + 2);
3154 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003155 return(reader->depth);
3156}
3157
3158/**
3159 * xmlTextReaderHasAttributes:
3160 * @reader: the xmlTextReaderPtr used
3161 *
3162 * Whether the node has attributes.
3163 *
3164 * Returns 1 if true, 0 if false, and -1 in case or error
3165 */
3166int
3167xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003168 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003169 if (reader == NULL)
3170 return(-1);
3171 if (reader->node == NULL)
3172 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003173 if (reader->curnode != NULL)
3174 node = reader->curnode;
3175 else
3176 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003177
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003178 if ((node->type == XML_ELEMENT_NODE) &&
3179 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003180 return(1);
3181 /* TODO: handle the xmlDecl */
3182 return(0);
3183}
3184
3185/**
3186 * xmlTextReaderHasValue:
3187 * @reader: the xmlTextReaderPtr used
3188 *
3189 * Whether the node can have a text value.
3190 *
3191 * Returns 1 if true, 0 if false, and -1 in case or error
3192 */
3193int
3194xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003195 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003196 if (reader == NULL)
3197 return(-1);
3198 if (reader->node == NULL)
3199 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003200 if (reader->curnode != NULL)
3201 node = reader->curnode;
3202 else
3203 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003204
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003205 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003206 case XML_ATTRIBUTE_NODE:
3207 case XML_TEXT_NODE:
3208 case XML_CDATA_SECTION_NODE:
3209 case XML_PI_NODE:
3210 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003211 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003212 return(1);
3213 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003214 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003215 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003216 return(0);
3217}
3218
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003219/**
3220 * xmlTextReaderValue:
3221 * @reader: the xmlTextReaderPtr used
3222 *
3223 * Provides the text value of the node if present
3224 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003225 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003226 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003227 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003228xmlChar *
3229xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003230 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003231 if (reader == NULL)
3232 return(NULL);
3233 if (reader->node == NULL)
3234 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003235 if (reader->curnode != NULL)
3236 node = reader->curnode;
3237 else
3238 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003239
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003240 switch (node->type) {
3241 case XML_NAMESPACE_DECL:
3242 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003243 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003244 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003245
3246 if (attr->parent != NULL)
3247 return (xmlNodeListGetString
3248 (attr->parent->doc, attr->children, 1));
3249 else
3250 return (xmlNodeListGetString(NULL, attr->children, 1));
3251 break;
3252 }
3253 case XML_TEXT_NODE:
3254 case XML_CDATA_SECTION_NODE:
3255 case XML_PI_NODE:
3256 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003257 if (node->content != NULL)
3258 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003259 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003260 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003261 }
3262 return(NULL);
3263}
3264
3265/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003266 * xmlTextReaderConstValue:
3267 * @reader: the xmlTextReaderPtr used
3268 *
3269 * Provides the text value of the node if present
3270 *
3271 * Returns the string or NULL if not available. The result will be
3272 * deallocated on the next Read() operation.
3273 */
3274const xmlChar *
3275xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3276 xmlNodePtr node;
3277 if (reader == NULL)
3278 return(NULL);
3279 if (reader->node == NULL)
3280 return(NULL);
3281 if (reader->curnode != NULL)
3282 node = reader->curnode;
3283 else
3284 node = reader->node;
3285
3286 switch (node->type) {
3287 case XML_NAMESPACE_DECL:
3288 return(((xmlNsPtr) node)->href);
3289 case XML_ATTRIBUTE_NODE:{
3290 xmlAttrPtr attr = (xmlAttrPtr) node;
3291
3292 if ((attr->children != NULL) &&
3293 (attr->children->type == XML_TEXT_NODE) &&
3294 (attr->children->next == NULL))
3295 return(attr->children->content);
3296 else {
3297 reader->buffer->use = 0;
3298 xmlNodeBufGetContent(reader->buffer, node);
3299 return(reader->buffer->content);
3300 }
3301 break;
3302 }
3303 case XML_TEXT_NODE:
3304 case XML_CDATA_SECTION_NODE:
3305 case XML_PI_NODE:
3306 case XML_COMMENT_NODE:
3307 return(node->content);
3308 default:
3309 break;
3310 }
3311 return(NULL);
3312}
3313
3314/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003315 * xmlTextReaderIsDefault:
3316 * @reader: the xmlTextReaderPtr used
3317 *
3318 * Whether an Attribute node was generated from the default value
3319 * defined in the DTD or schema.
3320 *
3321 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3322 */
3323int
3324xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3325 if (reader == NULL)
3326 return(-1);
3327 return(0);
3328}
3329
3330/**
3331 * xmlTextReaderQuoteChar:
3332 * @reader: the xmlTextReaderPtr used
3333 *
3334 * The quotation mark character used to enclose the value of an attribute.
3335 *
3336 * Returns " or ' and -1 in case of error
3337 */
3338int
3339xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3340 if (reader == NULL)
3341 return(-1);
3342 /* TODO maybe lookup the attribute value for " first */
3343 return((int) '"');
3344}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003345
3346/**
3347 * xmlTextReaderXmlLang:
3348 * @reader: the xmlTextReaderPtr used
3349 *
3350 * The xml:lang scope within which the node resides.
3351 *
3352 * Returns the xml:lang value or NULL if none exists.
3353 */
3354xmlChar *
3355xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3356 if (reader == NULL)
3357 return(NULL);
3358 if (reader->node == NULL)
3359 return(NULL);
3360 return(xmlNodeGetLang(reader->node));
3361}
3362
Daniel Veillard67df8092002-12-16 22:04:11 +00003363/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003364 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003365 * @reader: the xmlTextReaderPtr used
3366 *
3367 * The xml:lang scope within which the node resides.
3368 *
3369 * Returns the xml:lang value or NULL if none exists.
3370 */
3371const xmlChar *
3372xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3373 xmlChar *tmp;
3374 const xmlChar *ret;
3375
3376 if (reader == NULL)
3377 return(NULL);
3378 if (reader->node == NULL)
3379 return(NULL);
3380 tmp = xmlNodeGetLang(reader->node);
3381 if (tmp == NULL)
3382 return(NULL);
3383 ret = CONSTSTR(tmp);
3384 xmlFree(tmp);
3385 return(ret);
3386}
3387
3388/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003389 * xmlTextReaderConstString:
3390 * @reader: the xmlTextReaderPtr used
3391 * @str: the string to intern.
3392 *
3393 * Get an interned string from the reader, allows for example to
3394 * speedup string name comparisons
3395 *
3396 * Returns an interned copy of the string or NULL in case of error. The
3397 * string will be deallocated with the reader.
3398 */
3399const xmlChar *
3400xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3401 if (reader == NULL)
3402 return(NULL);
3403 return(CONSTSTR(str));
3404}
3405
3406/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003407 * xmlTextReaderNormalization:
3408 * @reader: the xmlTextReaderPtr used
3409 *
3410 * The value indicating whether to normalize white space and attribute values.
3411 * Since attribute value and end of line normalizations are a MUST in the XML
3412 * specification only the value true is accepted. The broken bahaviour of
3413 * accepting out of range character entities like &#0; is of course not
3414 * supported either.
3415 *
3416 * Returns 1 or -1 in case of error.
3417 */
3418int
3419xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3420 if (reader == NULL)
3421 return(-1);
3422 return(1);
3423}
3424
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003425/************************************************************************
3426 * *
3427 * Extensions to the base APIs *
3428 * *
3429 ************************************************************************/
3430
3431/**
3432 * xmlTextReaderSetParserProp:
3433 * @reader: the xmlTextReaderPtr used
3434 * @prop: the xmlParserProperties to set
3435 * @value: usually 0 or 1 to (de)activate it
3436 *
3437 * Change the parser processing behaviour by changing some of its internal
3438 * properties. Note that some properties can only be changed before any
3439 * read has been done.
3440 *
3441 * Returns 0 if the call was successful, or -1 in case of error
3442 */
3443int
3444xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3445 xmlParserProperties p = (xmlParserProperties) prop;
3446 xmlParserCtxtPtr ctxt;
3447
3448 if ((reader == NULL) || (reader->ctxt == NULL))
3449 return(-1);
3450 ctxt = reader->ctxt;
3451
3452 switch (p) {
3453 case XML_PARSER_LOADDTD:
3454 if (value != 0) {
3455 if (ctxt->loadsubset == 0) {
3456 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3457 return(-1);
3458 ctxt->loadsubset = XML_DETECT_IDS;
3459 }
3460 } else {
3461 ctxt->loadsubset = 0;
3462 }
3463 return(0);
3464 case XML_PARSER_DEFAULTATTRS:
3465 if (value != 0) {
3466 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3467 } else {
3468 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3469 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3470 }
3471 return(0);
3472 case XML_PARSER_VALIDATE:
3473 if (value != 0) {
3474 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003475 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003476 } else {
3477 ctxt->validate = 0;
3478 }
3479 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003480 case XML_PARSER_SUBST_ENTITIES:
3481 if (value != 0) {
3482 ctxt->replaceEntities = 1;
3483 } else {
3484 ctxt->replaceEntities = 0;
3485 }
3486 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003487 }
3488 return(-1);
3489}
3490
3491/**
3492 * xmlTextReaderGetParserProp:
3493 * @reader: the xmlTextReaderPtr used
3494 * @prop: the xmlParserProperties to get
3495 *
3496 * Read the parser internal property.
3497 *
3498 * Returns the value, usually 0 or 1, or -1 in case of error.
3499 */
3500int
3501xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3502 xmlParserProperties p = (xmlParserProperties) prop;
3503 xmlParserCtxtPtr ctxt;
3504
3505 if ((reader == NULL) || (reader->ctxt == NULL))
3506 return(-1);
3507 ctxt = reader->ctxt;
3508
3509 switch (p) {
3510 case XML_PARSER_LOADDTD:
3511 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3512 return(1);
3513 return(0);
3514 case XML_PARSER_DEFAULTATTRS:
3515 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3516 return(1);
3517 return(0);
3518 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003519 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003520 case XML_PARSER_SUBST_ENTITIES:
3521 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003522 }
3523 return(-1);
3524}
3525
Daniel Veillarde18fc182002-12-28 22:56:33 +00003526/**
3527 * xmlTextReaderCurrentNode:
3528 * @reader: the xmlTextReaderPtr used
3529 *
3530 * Hacking interface allowing to get the xmlNodePtr correponding to the
3531 * current node being accessed by the xmlTextReader. This is dangerous
3532 * because the underlying node may be destroyed on the next Reads.
3533 *
3534 * Returns the xmlNodePtr or NULL in case of error.
3535 */
3536xmlNodePtr
3537xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3538 if (reader == NULL)
3539 return(NULL);
3540
3541 if (reader->curnode != NULL)
3542 return(reader->curnode);
3543 return(reader->node);
3544}
3545
3546/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003547 * xmlTextReaderPreserve:
3548 * @reader: the xmlTextReaderPtr used
3549 *
3550 *
3551 * current node being accessed by the xmlTextReader. This is dangerous
3552 * because the underlying node may be destroyed on the next Reads.
3553 *
3554 * Returns the xmlNodePtr or NULL in case of error.
3555 */
3556xmlNodePtr
3557xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3558 xmlNodePtr cur, parent;
3559
3560 if (reader == NULL)
3561 return(NULL);
3562
3563 if (reader->curnode != NULL)
3564 cur = reader->curnode;
3565 else
3566 cur = reader->node;
3567 if (cur == NULL)
3568 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003569
3570 if (cur->type != XML_DOCUMENT_NODE) {
3571 cur->extra |= NODE_IS_PRESERVED;
3572 cur->extra |= NODE_IS_SPRESERVED;
3573 }
3574 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003575
3576 parent = cur->parent;;
3577 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003578 if (parent->type == XML_ELEMENT_NODE)
3579 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003580 parent = parent->parent;
3581 }
3582 return(cur);
3583}
3584
Daniel Veillard1e906612003-12-05 14:57:46 +00003585#ifdef LIBXML_PATTERN_ENABLED
3586/**
3587 * xmlTextReaderPreservePattern:
3588 * @reader: the xmlTextReaderPtr used
3589 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003590 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003591 *
3592 * This tells the XML Reader to preserve all nodes matched by the
3593 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3594 * keep an handle on the resulting document once parsing has finished
3595 *
3596 * Returns a positive number in case of success and -1 in case of error
3597 */
3598int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003599xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3600 const xmlChar **namespaces)
3601{
Daniel Veillard1e906612003-12-05 14:57:46 +00003602 xmlPatternPtr comp;
3603
3604 if ((reader == NULL) || (pattern == NULL))
3605 return(-1);
3606
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003607 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003608 if (comp == NULL)
3609 return(-1);
3610
3611 if (reader->patternMax <= 0) {
3612 reader->patternMax = 4;
3613 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3614 sizeof(reader->patternTab[0]));
3615 if (reader->patternTab == NULL) {
3616 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3617 return (-1);
3618 }
3619 }
3620 if (reader->patternNr >= reader->patternMax) {
3621 xmlPatternPtr *tmp;
3622 reader->patternMax *= 2;
3623 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3624 reader->patternMax *
3625 sizeof(reader->patternTab[0]));
3626 if (tmp == NULL) {
3627 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3628 reader->patternMax /= 2;
3629 return (-1);
3630 }
3631 reader->patternTab = tmp;
3632 }
3633 reader->patternTab[reader->patternNr] = comp;
3634 return(reader->patternNr++);
3635}
3636#endif
3637
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003638/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003639 * xmlTextReaderCurrentDoc:
3640 * @reader: the xmlTextReaderPtr used
3641 *
3642 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003643 * current document being accessed by the xmlTextReader.
3644 * NOTE: as a result of this call, the reader will not destroy the
3645 * associated XML document and calling xmlFreeDoc() on the result
3646 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003647 *
3648 * Returns the xmlDocPtr or NULL in case of error.
3649 */
3650xmlDocPtr
3651xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003652 if (reader == NULL)
3653 return(NULL);
3654 if (reader->doc != NULL)
3655 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003656 if ((reader == NULL) || (reader->ctxt == NULL) ||
3657 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003658 return(NULL);
3659
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003660 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003661 return(reader->ctxt->myDoc);
3662}
3663
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003664#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003665/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003666 * xmlTextReaderRelaxNGSetSchema:
3667 * @reader: the xmlTextReaderPtr used
3668 * @schema: a precompiled RelaxNG schema
3669 *
3670 * Use RelaxNG to validate the document as it is processed.
3671 * Activation is only possible before the first Read().
3672 * if @schema is NULL, then RelaxNG validation is desactivated.
3673 @ The @schema should not be freed until the reader is deallocated
3674 * or its use has been deactivated.
3675 *
3676 * Returns 0 in case the RelaxNG validation could be (des)activated and
3677 * -1 in case of error.
3678 */
3679int
3680xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3681 if (schema == NULL) {
3682 if (reader->rngSchemas != NULL) {
3683 xmlRelaxNGFree(reader->rngSchemas);
3684 reader->rngSchemas = NULL;
3685 }
3686 if (reader->rngValidCtxt != NULL) {
3687 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3688 reader->rngValidCtxt = NULL;
3689 }
3690 return(0);
3691 }
3692 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3693 return(-1);
3694 if (reader->rngSchemas != NULL) {
3695 xmlRelaxNGFree(reader->rngSchemas);
3696 reader->rngSchemas = NULL;
3697 }
3698 if (reader->rngValidCtxt != NULL) {
3699 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3700 reader->rngValidCtxt = NULL;
3701 }
3702 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3703 if (reader->rngValidCtxt == NULL)
3704 return(-1);
3705 if (reader->errorFunc != NULL) {
3706 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3707 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3708 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3709 reader->errorFuncArg);
3710 }
3711 reader->rngValidErrors = 0;
3712 reader->rngFullNode = NULL;
3713 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3714 return(0);
3715}
3716
3717/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003718 * xmlTextReaderRelaxNGValidate:
3719 * @reader: the xmlTextReaderPtr used
3720 * @rng: the path to a RelaxNG schema or NULL
3721 *
3722 * Use RelaxNG to validate the document as it is processed.
3723 * Activation is only possible before the first Read().
3724 * if @rng is NULL, then RelaxNG validation is desactivated.
3725 *
3726 * Returns 0 in case the RelaxNG validation could be (des)activated and
3727 * -1 in case of error.
3728 */
3729int
3730xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3731 xmlRelaxNGParserCtxtPtr ctxt;
3732
3733 if (reader == NULL)
3734 return(-1);
3735
3736 if (rng == NULL) {
3737 if (reader->rngSchemas != NULL) {
3738 xmlRelaxNGFree(reader->rngSchemas);
3739 reader->rngSchemas = NULL;
3740 }
3741 if (reader->rngValidCtxt != NULL) {
3742 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3743 reader->rngValidCtxt = NULL;
3744 }
3745 return(0);
3746 }
3747 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3748 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003749 if (reader->rngSchemas != NULL) {
3750 xmlRelaxNGFree(reader->rngSchemas);
3751 reader->rngSchemas = NULL;
3752 }
3753 if (reader->rngValidCtxt != NULL) {
3754 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3755 reader->rngValidCtxt = NULL;
3756 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003757 ctxt = xmlRelaxNGNewParserCtxt(rng);
3758 if (reader->errorFunc != NULL) {
3759 xmlRelaxNGSetParserErrors(ctxt,
3760 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3761 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3762 reader->errorFuncArg);
3763 }
3764 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3765 xmlRelaxNGFreeParserCtxt(ctxt);
3766 if (reader->rngSchemas == NULL)
3767 return(-1);
3768 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3769 if (reader->rngValidCtxt == NULL)
3770 return(-1);
3771 if (reader->errorFunc != NULL) {
3772 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3773 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3774 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3775 reader->errorFuncArg);
3776 }
3777 reader->rngValidErrors = 0;
3778 reader->rngFullNode = NULL;
3779 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3780 return(0);
3781}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003782#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003783
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003784/************************************************************************
3785 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003786 * Error Handling Extensions *
3787 * *
3788 ************************************************************************/
3789
3790/* helper to build a xmlMalloc'ed string from a format and va_list */
3791static char *
3792xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3793 int size;
3794 int chars;
3795 char *larger;
3796 char *str;
3797
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003798 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003799 if (str == NULL) {
3800 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3801 return NULL;
3802 }
3803
3804 size = 150;
3805
3806 while (1) {
3807 chars = vsnprintf(str, size, msg, ap);
3808 if ((chars > -1) && (chars < size))
3809 break;
3810 if (chars > -1)
3811 size += chars + 1;
3812 else
3813 size += 100;
3814 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3815 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3816 xmlFree(str);
3817 return NULL;
3818 }
3819 str = larger;
3820 }
3821
3822 return str;
3823}
3824
Daniel Veillard417be3a2003-01-20 21:26:34 +00003825/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003826 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003827 * @locator: the xmlTextReaderLocatorPtr used
3828 *
3829 * Obtain the line number for the given locator.
3830 *
3831 * Returns the line number or -1 in case of error.
3832 */
3833int
3834xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3835 /* we know that locator is a xmlParserCtxtPtr */
3836 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3837 int ret = -1;
3838
3839 if (ctx->node != NULL) {
3840 ret = xmlGetLineNo(ctx->node);
3841 }
3842 else {
3843 /* inspired from error.c */
3844 xmlParserInputPtr input;
3845 input = ctx->input;
3846 if ((input->filename == NULL) && (ctx->inputNr > 1))
3847 input = ctx->inputTab[ctx->inputNr - 2];
3848 if (input != NULL) {
3849 ret = input->line;
3850 }
3851 else {
3852 ret = -1;
3853 }
3854 }
3855
3856 return ret;
3857}
3858
3859/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003860 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003861 * @locator: the xmlTextReaderLocatorPtr used
3862 *
3863 * Obtain the base URI for the given locator.
3864 *
3865 * Returns the base URI or NULL in case of error.
3866 */
3867xmlChar *
3868xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3869 /* we know that locator is a xmlParserCtxtPtr */
3870 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3871 xmlChar *ret = NULL;
3872
3873 if (ctx->node != NULL) {
3874 ret = xmlNodeGetBase(NULL,ctx->node);
3875 }
3876 else {
3877 /* inspired from error.c */
3878 xmlParserInputPtr input;
3879 input = ctx->input;
3880 if ((input->filename == NULL) && (ctx->inputNr > 1))
3881 input = ctx->inputTab[ctx->inputNr - 2];
3882 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003883 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003884 }
3885 else {
3886 ret = NULL;
3887 }
3888 }
3889
3890 return ret;
3891}
3892
Daniel Veillard26f70262003-01-16 22:45:08 +00003893static void
William M. Brack899e64a2003-09-26 18:03:42 +00003894xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003895 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3896 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3897
3898 if (str != NULL) {
3899 reader->errorFunc(reader->errorFuncArg,
3900 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003901 severity,
3902 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003903 xmlFree(str);
3904 }
3905}
3906
3907static void
William M. Brack93d004f2004-02-03 00:14:10 +00003908xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3909 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3910 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3911
3912 if (error && reader->sErrorFunc) {
3913 reader->sErrorFunc(reader->errorFuncArg,
3914 (xmlErrorPtr) error);
3915 }
3916}
3917
3918static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003919xmlTextReaderError(void *ctxt, const char *msg, ...) {
3920 va_list ap;
3921
3922 va_start(ap,msg);
3923 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003924 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003925 xmlTextReaderBuildMessage(msg,ap));
3926 va_end(ap);
3927
3928}
3929
3930static void
3931xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3932 va_list ap;
3933
3934 va_start(ap,msg);
3935 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003936 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003937 xmlTextReaderBuildMessage(msg,ap));
3938 va_end(ap);
3939}
3940
3941static void
3942xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3943 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003944 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003945
Daniel Veillard417be3a2003-01-20 21:26:34 +00003946 if ((len > 1) && (msg[len - 2] != ':')) {
3947 /*
3948 * some callbacks only report locator information:
3949 * skip them (mimicking behaviour in error.c)
3950 */
3951 va_start(ap,msg);
3952 xmlTextReaderGenericError(ctxt,
3953 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3954 xmlTextReaderBuildMessage(msg,ap));
3955 va_end(ap);
3956 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003957}
3958
3959static void
3960xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3961 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003962 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003963
Daniel Veillard417be3a2003-01-20 21:26:34 +00003964 if ((len != 0) && (msg[len - 1] != ':')) {
3965 /*
3966 * some callbacks only report locator information:
3967 * skip them (mimicking behaviour in error.c)
3968 */
3969 va_start(ap,msg);
3970 xmlTextReaderGenericError(ctxt,
3971 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3972 xmlTextReaderBuildMessage(msg,ap));
3973 va_end(ap);
3974 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003975}
3976
3977/**
3978 * xmlTextReaderSetErrorHandler:
3979 * @reader: the xmlTextReaderPtr used
3980 * @f: the callback function to call on error and warnings
3981 * @arg: a user argument to pass to the callback function
3982 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003983 * Register a callback function that will be called on error and warnings.
3984 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003985 * If @f is NULL, the default error and warning handlers are restored.
3986 */
3987void
3988xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3989 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003990 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003991 if (f != NULL) {
3992 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003993 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003994 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3995 reader->ctxt->sax->warning = xmlTextReaderWarning;
3996 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3997 reader->errorFunc = f;
3998 reader->errorFuncArg = arg;
3999 }
4000 else {
4001 /* restore defaults */
4002 reader->ctxt->sax->error = xmlParserError;
4003 reader->ctxt->vctxt.error = xmlParserValidityError;
4004 reader->ctxt->sax->warning = xmlParserWarning;
4005 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4006 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004007 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004008 reader->errorFuncArg = NULL;
4009 }
4010}
4011
Daniel Veillard417be3a2003-01-20 21:26:34 +00004012/**
William M. Brack93d004f2004-02-03 00:14:10 +00004013* xmlTextReaderSetStructuredErrorHandler:
4014 * @reader: the xmlTextReaderPtr used
4015 * @f: the callback function to call on error and warnings
4016 * @arg: a user argument to pass to the callback function
4017 *
4018 * Register a callback function that will be called on error and warnings.
4019 *
4020 * If @f is NULL, the default error and warning handlers are restored.
4021 */
4022void
4023xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4024 xmlStructuredErrorFunc f,
4025 void *arg) {
4026 if (f != NULL) {
4027 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4028 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4029 reader->ctxt->sax->warning = xmlTextReaderWarning;
4030 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4031 reader->sErrorFunc = f;
4032 reader->errorFunc = NULL;
4033 reader->errorFuncArg = arg;
4034 }
4035 else {
4036 /* restore defaults */
4037 reader->ctxt->sax->error = xmlParserError;
4038 reader->ctxt->sax->serror = NULL;
4039 reader->ctxt->vctxt.error = xmlParserValidityError;
4040 reader->ctxt->sax->warning = xmlParserWarning;
4041 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4042 reader->errorFunc = NULL;
4043 reader->sErrorFunc = NULL;
4044 reader->errorFuncArg = NULL;
4045 }
4046}
4047
4048/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004049 * xmlTextReaderIsValid:
4050 * @reader: the xmlTextReaderPtr used
4051 *
4052 * Retrieve the validity status from the parser context
4053 *
4054 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4055 */
4056int
4057xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004058 if (reader == NULL) return(-1);
4059#ifdef LIBXML_SCHEMAS_ENABLED
4060 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4061 return(reader->rngValidErrors == 0);
4062#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004063 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004064 return(reader->ctxt->valid);
4065 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004066}
4067
4068/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004069 * xmlTextReaderGetErrorHandler:
4070 * @reader: the xmlTextReaderPtr used
4071 * @f: the callback function or NULL is no callback has been registered
4072 * @arg: a user argument
4073 *
4074 * Retrieve the error callback function and user argument.
4075 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004076void
4077xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4078 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004079 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004080 *f = reader->errorFunc;
4081 *arg = reader->errorFuncArg;
4082}
4083
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004084
4085/************************************************************************
4086 * *
4087 * New set (2.6.0) of simpler and more flexible APIs *
4088 * *
4089 ************************************************************************/
4090
4091/**
4092 * xmlTextReaderSetup:
4093 * @reader: an XML reader
4094 * @URL: the base URL to use for the document
4095 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004096 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004097 * @reuse: keep the context for reuse
4098 *
4099 * Setup an XML reader with new options
4100 *
4101 * Returns 0 in case of success and -1 in case of error.
4102 */
4103static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004104xmlTextReaderSetup(xmlTextReaderPtr reader,
4105 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004106 const char *encoding, int options)
4107{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004108 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004109 return (-1);
4110
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004111 reader->doc = NULL;
4112 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004113 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004114 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004115 if ((input != NULL) && (reader->input != NULL) &&
4116 (reader->allocs & XML_TEXTREADER_INPUT)) {
4117 xmlFreeParserInputBuffer(reader->input);
4118 reader->input = NULL;
4119 reader->allocs -= XML_TEXTREADER_INPUT;
4120 }
4121 if (input != NULL) {
4122 reader->input = input;
4123 reader->allocs |= XML_TEXTREADER_INPUT;
4124 }
4125 if (reader->buffer == NULL)
4126 reader->buffer = xmlBufferCreateSize(100);
4127 if (reader->buffer == NULL) {
4128 xmlGenericError(xmlGenericErrorContext,
4129 "xmlTextReaderSetup : malloc failed\n");
4130 return (-1);
4131 }
4132 if (reader->sax == NULL)
4133 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4134 if (reader->sax == NULL) {
4135 xmlGenericError(xmlGenericErrorContext,
4136 "xmlTextReaderSetup : malloc failed\n");
4137 return (-1);
4138 }
4139 xmlSAXVersion(reader->sax, 2);
4140 reader->startElement = reader->sax->startElement;
4141 reader->sax->startElement = xmlTextReaderStartElement;
4142 reader->endElement = reader->sax->endElement;
4143 reader->sax->endElement = xmlTextReaderEndElement;
4144#ifdef LIBXML_SAX1_ENABLED
4145 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4146#endif /* LIBXML_SAX1_ENABLED */
4147 reader->startElementNs = reader->sax->startElementNs;
4148 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4149 reader->endElementNs = reader->sax->endElementNs;
4150 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4151#ifdef LIBXML_SAX1_ENABLED
4152 } else {
4153 reader->startElementNs = NULL;
4154 reader->endElementNs = NULL;
4155 }
4156#endif /* LIBXML_SAX1_ENABLED */
4157 reader->characters = reader->sax->characters;
4158 reader->sax->characters = xmlTextReaderCharacters;
4159 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4160 reader->cdataBlock = reader->sax->cdataBlock;
4161 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4162
4163 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4164 reader->node = NULL;
4165 reader->curnode = NULL;
4166 if (input != NULL) {
4167 if (reader->input->buffer->use < 4) {
4168 xmlParserInputBufferRead(input, 4);
4169 }
4170 if (reader->ctxt == NULL) {
4171 if (reader->input->buffer->use >= 4) {
4172 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4173 (const char *) reader->input->buffer->content, 4, URL);
4174 reader->base = 0;
4175 reader->cur = 4;
4176 } else {
4177 reader->ctxt =
4178 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4179 reader->base = 0;
4180 reader->cur = 0;
4181 }
4182 } else {
4183 xmlParserInputPtr inputStream;
4184 xmlParserInputBufferPtr buf;
4185 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4186
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004187 xmlCtxtReset(reader->ctxt);
4188 buf = xmlAllocParserInputBuffer(enc);
4189 if (buf == NULL) return(-1);
4190 inputStream = xmlNewInputStream(reader->ctxt);
4191 if (inputStream == NULL) {
4192 xmlFreeParserInputBuffer(buf);
4193 return(-1);
4194 }
4195
4196 if (URL == NULL)
4197 inputStream->filename = NULL;
4198 else
4199 inputStream->filename = (char *)
4200 xmlCanonicPath((const xmlChar *) URL);
4201 inputStream->buf = buf;
4202 inputStream->base = inputStream->buf->buffer->content;
4203 inputStream->cur = inputStream->buf->buffer->content;
4204 inputStream->end =
4205 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4206
4207 inputPush(reader->ctxt, inputStream);
4208 reader->cur = 0;
4209 }
4210 if (reader->ctxt == NULL) {
4211 xmlGenericError(xmlGenericErrorContext,
4212 "xmlTextReaderSetup : malloc failed\n");
4213 return (-1);
4214 }
4215 }
4216 if (reader->dict != NULL) {
4217 if (reader->ctxt->dict != NULL) {
4218 if (reader->dict != reader->ctxt->dict) {
4219 xmlDictFree(reader->dict);
4220 reader->dict = reader->ctxt->dict;
4221 }
4222 } else {
4223 reader->ctxt->dict = reader->dict;
4224 }
4225 } else {
4226 if (reader->ctxt->dict == NULL)
4227 reader->ctxt->dict = xmlDictCreate();
4228 reader->dict = reader->ctxt->dict;
4229 }
4230 reader->ctxt->_private = reader;
4231 reader->ctxt->linenumbers = 1;
4232 reader->ctxt->dictNames = 1;
4233 /*
4234 * use the parser dictionnary to allocate all elements and attributes names
4235 */
4236 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004237 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004238
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004239#ifdef LIBXML_XINCLUDE_ENABLED
4240 if (reader->xincctxt != NULL) {
4241 xmlXIncludeFreeContext(reader->xincctxt);
4242 reader->xincctxt = NULL;
4243 }
4244 if (options & XML_PARSE_XINCLUDE) {
4245 reader->xinclude = 1;
4246 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4247 options -= XML_PARSE_XINCLUDE;
4248 } else
4249 reader->xinclude = 0;
4250 reader->in_xinclude = 0;
4251#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004252#ifdef LIBXML_PATTERN_ENABLED
4253 if (reader->patternTab == NULL) {
4254 reader->patternNr = 0;
4255 reader->patternMax = 0;
4256 }
4257 while (reader->patternNr > 0) {
4258 reader->patternNr--;
4259 if (reader->patternTab[reader->patternNr] != NULL) {
4260 xmlFreePattern(reader->patternTab[reader->patternNr]);
4261 reader->patternTab[reader->patternNr] = NULL;
4262 }
4263 }
4264#endif
4265
Daniel Veillardc36965d2003-12-02 10:28:48 +00004266 if (options & XML_PARSE_DTDVALID)
4267 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4268
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004269 xmlCtxtUseOptions(reader->ctxt, options);
4270 if (encoding != NULL) {
4271 xmlCharEncodingHandlerPtr hdlr;
4272
4273 hdlr = xmlFindCharEncodingHandler(encoding);
4274 if (hdlr != NULL)
4275 xmlSwitchToEncoding(reader->ctxt, hdlr);
4276 }
4277 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4278 (reader->ctxt->input->filename == NULL))
4279 reader->ctxt->input->filename = (char *)
4280 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004281
4282 reader->doc = NULL;
4283
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004284 return (0);
4285}
4286
4287/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004288 * xmlReaderWalker:
4289 * @doc: a preparsed document
4290 *
4291 * Create an xmltextReader for a preparsed document.
4292 *
4293 * Returns the new reader or NULL in case of error.
4294 */
4295xmlTextReaderPtr
4296xmlReaderWalker(xmlDocPtr doc)
4297{
4298 xmlTextReaderPtr ret;
4299
4300 if (doc == NULL)
4301 return(NULL);
4302
4303 ret = xmlMalloc(sizeof(xmlTextReader));
4304 if (ret == NULL) {
4305 xmlGenericError(xmlGenericErrorContext,
4306 "xmlNewTextReader : malloc failed\n");
4307 return(NULL);
4308 }
4309 memset(ret, 0, sizeof(xmlTextReader));
4310 ret->entNr = 0;
4311 ret->input = NULL;
4312 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4313 ret->node = NULL;
4314 ret->curnode = NULL;
4315 ret->base = 0;
4316 ret->cur = 0;
4317 ret->allocs = XML_TEXTREADER_CTXT;
4318 ret->doc = doc;
4319 ret->state = XML_TEXTREADER_START;
4320 ret->dict = xmlDictCreate();
4321 return(ret);
4322}
4323
4324/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004325 * xmlReaderForDoc:
4326 * @cur: a pointer to a zero terminated string
4327 * @URL: the base URL to use for the document
4328 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004329 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004330 *
4331 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004332 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004333 *
4334 * Returns the new reader or NULL in case of error.
4335 */
4336xmlTextReaderPtr
4337xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4338 int options)
4339{
4340 int len;
4341
4342 if (cur == NULL)
4343 return (NULL);
4344 len = xmlStrlen(cur);
4345
4346 return (xmlReaderForMemory
4347 ((const char *) cur, len, URL, encoding, options));
4348}
4349
4350/**
4351 * xmlReaderForFile:
4352 * @filename: a file or URL
4353 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004354 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004355 *
4356 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004357 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004358 *
4359 * Returns the new reader or NULL in case of error.
4360 */
4361xmlTextReaderPtr
4362xmlReaderForFile(const char *filename, const char *encoding, int options)
4363{
4364 xmlTextReaderPtr reader;
4365
4366 reader = xmlNewTextReaderFilename(filename);
4367 if (reader == NULL)
4368 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004369 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004370 return (reader);
4371}
4372
4373/**
4374 * xmlReaderForMemory:
4375 * @buffer: a pointer to a char array
4376 * @size: the size of the array
4377 * @URL: the base URL to use for the document
4378 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004379 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004380 *
4381 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004382 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004383 *
4384 * Returns the new reader or NULL in case of error.
4385 */
4386xmlTextReaderPtr
4387xmlReaderForMemory(const char *buffer, int size, const char *URL,
4388 const char *encoding, int options)
4389{
4390 xmlTextReaderPtr reader;
4391 xmlParserInputBufferPtr buf;
4392
Daniel Veillard21924522004-02-19 16:37:07 +00004393 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004394 XML_CHAR_ENCODING_NONE);
4395 if (buf == NULL) {
4396 return (NULL);
4397 }
4398 reader = xmlNewTextReader(buf, URL);
4399 if (reader == NULL) {
4400 xmlFreeParserInputBuffer(buf);
4401 return (NULL);
4402 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004403 reader->allocs |= XML_TEXTREADER_INPUT;
4404 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004405 return (reader);
4406}
4407
4408/**
4409 * xmlReaderForFd:
4410 * @fd: an open file descriptor
4411 * @URL: the base URL to use for the document
4412 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004413 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004414 *
4415 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004416 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004417 * NOTE that the file descriptor will not be closed when the
4418 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004419 *
4420 * Returns the new reader or NULL in case of error.
4421 */
4422xmlTextReaderPtr
4423xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4424{
4425 xmlTextReaderPtr reader;
4426 xmlParserInputBufferPtr input;
4427
4428 if (fd < 0)
4429 return (NULL);
4430
4431 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4432 if (input == NULL)
4433 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004434 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004435 reader = xmlNewTextReader(input, URL);
4436 if (reader == NULL) {
4437 xmlFreeParserInputBuffer(input);
4438 return (NULL);
4439 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004440 reader->allocs |= XML_TEXTREADER_INPUT;
4441 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004442 return (reader);
4443}
4444
4445/**
4446 * xmlReaderForIO:
4447 * @ioread: an I/O read function
4448 * @ioclose: an I/O close function
4449 * @ioctx: an I/O handler
4450 * @URL: the base URL to use for the document
4451 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004452 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004453 *
4454 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004455 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004456 *
4457 * Returns the new reader or NULL in case of error.
4458 */
4459xmlTextReaderPtr
4460xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4461 void *ioctx, const char *URL, const char *encoding,
4462 int options)
4463{
4464 xmlTextReaderPtr reader;
4465 xmlParserInputBufferPtr input;
4466
4467 if (ioread == NULL)
4468 return (NULL);
4469
4470 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4471 XML_CHAR_ENCODING_NONE);
4472 if (input == NULL)
4473 return (NULL);
4474 reader = xmlNewTextReader(input, URL);
4475 if (reader == NULL) {
4476 xmlFreeParserInputBuffer(input);
4477 return (NULL);
4478 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004479 reader->allocs |= XML_TEXTREADER_INPUT;
4480 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004481 return (reader);
4482}
4483
4484/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004485 * xmlReaderNewWalker:
4486 * @reader: an XML reader
4487 * @doc: a preparsed document
4488 *
4489 * Setup an xmltextReader to parse a preparsed XML document.
4490 * This reuses the existing @reader xmlTextReader.
4491 *
4492 * Returns 0 in case of success and -1 in case of error
4493 */
4494int
4495xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4496{
4497 if (doc == NULL)
4498 return (-1);
4499 if (reader == NULL)
4500 return (-1);
4501
4502 if (reader->ctxt != NULL) {
4503 xmlCtxtReset(reader->ctxt);
4504 }
4505
4506 reader->entNr = 0;
4507 reader->input = NULL;
4508 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4509 reader->node = NULL;
4510 reader->curnode = NULL;
4511 reader->base = 0;
4512 reader->cur = 0;
4513 reader->allocs = XML_TEXTREADER_CTXT;
4514 reader->doc = doc;
4515 reader->state = XML_TEXTREADER_START;
4516 if (reader->dict == NULL) {
4517 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4518 reader->dict = reader->ctxt->dict;
4519 else
4520 reader->dict = xmlDictCreate();
4521 }
4522 return(0);
4523}
4524
4525/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004526 * xmlReaderNewDoc:
4527 * @reader: an XML reader
4528 * @cur: a pointer to a zero terminated string
4529 * @URL: the base URL to use for the document
4530 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004531 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004532 *
4533 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004534 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004535 * This reuses the existing @reader xmlTextReader.
4536 *
4537 * Returns 0 in case of success and -1 in case of error
4538 */
4539int
4540xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4541 const char *URL, const char *encoding, int options)
4542{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004543
4544 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004545
4546 if (cur == NULL)
4547 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004548 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004549 return (-1);
4550
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004551 len = xmlStrlen(cur);
4552 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4553 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004554}
4555
4556/**
4557 * xmlReaderNewFile:
4558 * @reader: an XML reader
4559 * @filename: a file or URL
4560 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004561 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004562 *
4563 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004564 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004565 * This reuses the existing @reader xmlTextReader.
4566 *
4567 * Returns 0 in case of success and -1 in case of error
4568 */
4569int
4570xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4571 const char *encoding, int options)
4572{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004573 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004574
4575 if (filename == NULL)
4576 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004577 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004578 return (-1);
4579
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004580 input =
4581 xmlParserInputBufferCreateFilename(filename,
4582 XML_CHAR_ENCODING_NONE);
4583 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004584 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004585 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004586}
4587
4588/**
4589 * xmlReaderNewMemory:
4590 * @reader: an XML reader
4591 * @buffer: a pointer to a char array
4592 * @size: the size of the array
4593 * @URL: the base URL to use for the document
4594 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004595 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004596 *
4597 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004598 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004599 * This reuses the existing @reader xmlTextReader.
4600 *
4601 * Returns 0 in case of success and -1 in case of error
4602 */
4603int
4604xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4605 const char *URL, const char *encoding, int options)
4606{
4607 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004608
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004609 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004610 return (-1);
4611 if (buffer == NULL)
4612 return (-1);
4613
Daniel Veillard21924522004-02-19 16:37:07 +00004614 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004615 XML_CHAR_ENCODING_NONE);
4616 if (input == NULL) {
4617 return (-1);
4618 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004619 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004620}
4621
4622/**
4623 * xmlReaderNewFd:
4624 * @reader: an XML reader
4625 * @fd: an open file descriptor
4626 * @URL: the base URL to use for the document
4627 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004628 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004629 *
4630 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004631 * NOTE that the file descriptor will not be closed when the
4632 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004633 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004634 * This reuses the existing @reader xmlTextReader.
4635 *
4636 * Returns 0 in case of success and -1 in case of error
4637 */
4638int
4639xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4640 const char *URL, const char *encoding, int options)
4641{
4642 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004643
4644 if (fd < 0)
4645 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004646 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004647 return (-1);
4648
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004649 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4650 if (input == NULL)
4651 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004652 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004653 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004654}
4655
4656/**
4657 * xmlReaderNewIO:
4658 * @reader: an XML reader
4659 * @ioread: an I/O read function
4660 * @ioclose: an I/O close function
4661 * @ioctx: an I/O handler
4662 * @URL: the base URL to use for the document
4663 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004664 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004665 *
4666 * Setup an xmltextReader to parse an XML document from I/O functions
4667 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004668 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004669 * This reuses the existing @reader xmlTextReader.
4670 *
4671 * Returns 0 in case of success and -1 in case of error
4672 */
4673int
4674xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4675 xmlInputCloseCallback ioclose, void *ioctx,
4676 const char *URL, const char *encoding, int options)
4677{
4678 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004679
4680 if (ioread == NULL)
4681 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004682 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004683 return (-1);
4684
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004685 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4686 XML_CHAR_ENCODING_NONE);
4687 if (input == NULL)
4688 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004689 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004690}
Daniel Veillard26f70262003-01-16 22:45:08 +00004691/************************************************************************
4692 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004693 * Utilities *
4694 * *
4695 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004696#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004697/**
4698 * xmlBase64Decode:
4699 * @in: the input buffer
4700 * @inlen: the size of the input (in), the size read from it (out)
4701 * @to: the output buffer
4702 * @tolen: the size of the output (in), the size written to (out)
4703 *
4704 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004705 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004706 *
4707 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4708 * 2 if there wasn't enough space on the output or -1 in case of error.
4709 */
4710static int
4711xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4712 unsigned char *to, unsigned long *tolen) {
4713 unsigned long incur; /* current index in in[] */
4714 unsigned long inblk; /* last block index in in[] */
4715 unsigned long outcur; /* current index in out[] */
4716 unsigned long inmax; /* size of in[] */
4717 unsigned long outmax; /* size of out[] */
4718 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004719 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004720 int nbintmp; /* number of byte in intmp[] */
4721 int is_ignore; /* cur should be ignored */
4722 int is_end = 0; /* the end of the base64 was found */
4723 int retval = 1;
4724 int i;
4725
4726 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4727 return(-1);
4728
4729 incur = 0;
4730 inblk = 0;
4731 outcur = 0;
4732 inmax = *inlen;
4733 outmax = *tolen;
4734 nbintmp = 0;
4735
4736 while (1) {
4737 if (incur >= inmax)
4738 break;
4739 cur = in[incur++];
4740 is_ignore = 0;
4741 if ((cur >= 'A') && (cur <= 'Z'))
4742 cur = cur - 'A';
4743 else if ((cur >= 'a') && (cur <= 'z'))
4744 cur = cur - 'a' + 26;
4745 else if ((cur >= '0') && (cur <= '9'))
4746 cur = cur - '0' + 52;
4747 else if (cur == '+')
4748 cur = 62;
4749 else if (cur == '/')
4750 cur = 63;
4751 else if (cur == '.')
4752 cur = 0;
4753 else if (cur == '=') /*no op , end of the base64 stream */
4754 is_end = 1;
4755 else {
4756 is_ignore = 1;
4757 if (nbintmp == 0)
4758 inblk = incur;
4759 }
4760
4761 if (!is_ignore) {
4762 int nbouttmp = 3;
4763 int is_break = 0;
4764
4765 if (is_end) {
4766 if (nbintmp == 0)
4767 break;
4768 if ((nbintmp == 1) || (nbintmp == 2))
4769 nbouttmp = 1;
4770 else
4771 nbouttmp = 2;
4772 nbintmp = 3;
4773 is_break = 1;
4774 }
4775 intmp[nbintmp++] = cur;
4776 /*
4777 * if intmp is full, push the 4byte sequence as a 3 byte
4778 * sequence out
4779 */
4780 if (nbintmp == 4) {
4781 nbintmp = 0;
4782 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4783 outtmp[1] =
4784 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4785 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4786 if (outcur + 3 >= outmax) {
4787 retval = 2;
4788 break;
4789 }
4790
4791 for (i = 0; i < nbouttmp; i++)
4792 to[outcur++] = outtmp[i];
4793 inblk = incur;
4794 }
4795
4796 if (is_break) {
4797 retval = 0;
4798 break;
4799 }
4800 }
4801 }
4802
4803 *tolen = outcur;
4804 *inlen = inblk;
4805 return (retval);
4806}
4807
4808/*
4809 * Test routine for the xmlBase64Decode function
4810 */
4811#if 0
4812int main(int argc, char **argv) {
4813 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4814 char output[100];
4815 char output2[100];
4816 char output3[100];
4817 unsigned long inlen = strlen(input);
4818 unsigned long outlen = 100;
4819 int ret;
4820 unsigned long cons, tmp, tmp2, prod;
4821
4822 /*
4823 * Direct
4824 */
4825 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4826
4827 output[outlen] = 0;
4828 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4829
4830 /*
4831 * output chunking
4832 */
4833 cons = 0;
4834 prod = 0;
4835 while (cons < inlen) {
4836 tmp = 5;
4837 tmp2 = inlen - cons;
4838
4839 printf("%ld %ld\n", cons, prod);
4840 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4841 cons += tmp2;
4842 prod += tmp;
4843 printf("%ld %ld\n", cons, prod);
4844 }
4845 output2[outlen] = 0;
4846 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4847
4848 /*
4849 * input chunking
4850 */
4851 cons = 0;
4852 prod = 0;
4853 while (cons < inlen) {
4854 tmp = 100 - prod;
4855 tmp2 = inlen - cons;
4856 if (tmp2 > 5)
4857 tmp2 = 5;
4858
4859 printf("%ld %ld\n", cons, prod);
4860 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4861 cons += tmp2;
4862 prod += tmp;
4863 printf("%ld %ld\n", cons, prod);
4864 }
4865 output3[outlen] = 0;
4866 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4867 return(0);
4868
4869}
4870#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004871#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004872#endif /* LIBXML_READER_ENABLED */