blob: f3225aab7cc58795af7aaf57e9720838a0924bd9 [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 Veillard1fdfd112003-01-03 01:18:43 +00001227 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001228 }
1229 oldstate = reader->state;
1230 olddepth = reader->ctxt->nodeNr;
1231 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001232
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001233get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001234 if (reader->node == NULL) {
1235 if (reader->mode == XML_TEXTREADER_DONE)
1236 return(0);
1237 else
1238 return(-1);
1239 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001240
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001241 /*
1242 * If we are not backtracking on ancestors or examined nodes,
1243 * that the parser didn't finished or that we arent at the end
1244 * of stream, continue processing.
1245 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001246 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001247 (reader->ctxt->nodeNr == olddepth) &&
1248 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001249 (reader->node->children == NULL) ||
1250 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001251 ((reader->node->children != NULL) &&
1252 (reader->node->children->type == XML_TEXT_NODE) &&
1253 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001254 (reader->node->type == XML_DTD_NODE) ||
1255 (reader->node->type == XML_DOCUMENT_NODE) ||
1256 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001257 ((reader->ctxt->node == NULL) ||
1258 (reader->ctxt->node == reader->node) ||
1259 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001260 (reader->ctxt->instate != XML_PARSER_EOF)) {
1261 val = xmlTextReaderPushData(reader);
1262 if (val < 0)
1263 return(-1);
1264 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001265 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001266 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001267 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 if ((reader->node->children != NULL) &&
1269 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001270 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001271 (reader->node->type != XML_DTD_NODE)) {
1272 reader->node = reader->node->children;
1273 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001274 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001275 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001276 }
1277 }
1278 if (reader->node->next != NULL) {
1279 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001280 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001281 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001282 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1283#ifdef LIBXML_XINCLUDE_ENABLED
1284 && (reader->in_xinclude <= 0)
1285#endif
1286 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001289 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001290#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001291 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001292 (reader->node->type == XML_ELEMENT_NODE))
1293 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001294#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001295 if ((reader->preserves > 0) &&
1296 (reader->node->extra & NODE_IS_SPRESERVED))
1297 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001298 reader->node = reader->node->next;
1299 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001300
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001301 /*
1302 * Cleanup of the old node
1303 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001304 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001305#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001306 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001307#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001308 (reader->entNr == 0) &&
1309 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001310 (reader->node->prev->type != XML_DTD_NODE) &&
1311 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001312 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001313 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001314 xmlUnlinkNode(tmp);
1315 xmlTextReaderFreeNode(reader, tmp);
1316 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001317 }
1318
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001319 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001320 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001321 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001322 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001323 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001324 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001325 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001326 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001327 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001328#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001329 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001330 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001331#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001332 if ((reader->preserves > 0) &&
1333 (reader->node->extra & NODE_IS_SPRESERVED))
1334 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 reader->node = reader->node->parent;
1336 if ((reader->node == NULL) ||
1337 (reader->node->type == XML_DOCUMENT_NODE) ||
1338#ifdef LIBXML_DOCB_ENABLED
1339 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1340#endif
1341 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001342 if (reader->mode != XML_TEXTREADER_DONE) {
1343 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1344 reader->mode = XML_TEXTREADER_DONE;
1345 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001346 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001347 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001348
1349 /*
1350 * Cleanup of the old node
1351 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001352 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001353#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001354 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001355#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001356 (reader->entNr == 0) &&
1357 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001358 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001359 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001360 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001361 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001362 }
1363
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001364 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001365 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001366 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001367#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001368 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001369#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001370 (reader->entNr == 0) &&
1371 (reader->node->last != NULL) &&
1372 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1373 xmlNodePtr tmp = reader->node->last;
1374 xmlUnlinkNode(tmp);
1375 xmlTextReaderFreeNode(reader, tmp);
1376 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001377 reader->depth--;
1378 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001379
1380node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001381 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001382
1383 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001384 * If we are in the middle of a piece of CDATA make sure it's finished
1385 */
1386 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001387 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001388 ((reader->node->type == XML_TEXT_NODE) ||
1389 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1390 xmlTextReaderExpand(reader);
1391 }
1392
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001393#ifdef LIBXML_XINCLUDE_ENABLED
1394 /*
1395 * Handle XInclude if asked for
1396 */
1397 if ((reader->xinclude) && (reader->node != NULL) &&
1398 (reader->node->type == XML_ELEMENT_NODE) &&
1399 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001400 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1401 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001402 if (reader->xincctxt == NULL) {
1403 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001404 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001405 }
1406 /*
1407 * expand that node and process it
1408 */
1409 xmlTextReaderExpand(reader);
1410 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1411 }
1412 if (reader->node->type == XML_XINCLUDE_START) {
1413 reader->in_xinclude++;
1414 goto get_next_node;
1415 }
1416 if (reader->node->type == XML_XINCLUDE_END) {
1417 reader->in_xinclude--;
1418 goto get_next_node;
1419 }
1420#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001421 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001422 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001423 */
1424 if ((reader->node != NULL) &&
1425 (reader->node->type == XML_ENTITY_REF_NODE) &&
1426 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1427 /*
1428 * Case where the underlying tree is not availble, lookup the entity
1429 * and walk it.
1430 */
1431 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1432 (reader->ctxt->sax->getEntity != NULL)) {
1433 reader->node->children = (xmlNodePtr)
1434 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1435 }
1436
1437 if ((reader->node->children != NULL) &&
1438 (reader->node->children->type == XML_ENTITY_DECL) &&
1439 (reader->node->children->children != NULL)) {
1440 xmlTextReaderEntPush(reader, reader->node);
1441 reader->node = reader->node->children->children;
1442 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001443#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001444 } else if ((reader->node != NULL) &&
1445 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001446 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001447 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001448#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001449 }
1450 if ((reader->node != NULL) &&
1451 (reader->node->type == XML_ENTITY_DECL) &&
1452 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1453 reader->node = xmlTextReaderEntPop(reader);
1454 reader->depth++;
1455 goto get_next_node;
1456 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001457#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001458 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001459 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001460
1461 if ((node->type == XML_ELEMENT_NODE) &&
1462 ((reader->state != XML_TEXTREADER_END) &&
1463 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1464 xmlTextReaderValidatePush(reader);
1465 } else if ((node->type == XML_TEXT_NODE) ||
1466 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001467 xmlTextReaderValidateCData(reader, node->content,
1468 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001469 }
1470 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001471#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001472#ifdef LIBXML_PATTERN_ENABLED
1473 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1474 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1475 int i;
1476 for (i = 0;i < reader->patternNr;i++) {
1477 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1478 xmlTextReaderPreserve(reader);
1479 break;
1480 }
1481 }
1482 }
1483#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001484 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001485node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001486 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001487 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001488}
1489
Daniel Veillard67df8092002-12-16 22:04:11 +00001490/**
1491 * xmlTextReaderReadState:
1492 * @reader: the xmlTextReaderPtr used
1493 *
1494 * Gets the read state of the reader.
1495 *
1496 * Returns the state value, or -1 in case of error
1497 */
1498int
1499xmlTextReaderReadState(xmlTextReaderPtr reader) {
1500 if (reader == NULL)
1501 return(-1);
1502 return(reader->mode);
1503}
1504
1505/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001506 * xmlTextReaderExpand:
1507 * @reader: the xmlTextReaderPtr used
1508 *
1509 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001510 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001511 *
1512 * Returns a node pointer valid until the next xmlTextReaderRead() call
1513 * or NULL in case of error.
1514 */
1515xmlNodePtr
1516xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001517 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001518 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001519 if (reader->doc != NULL)
1520 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001521 if (reader->ctxt == NULL)
1522 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001523 if (xmlTextReaderDoExpand(reader) < 0)
1524 return(NULL);
1525 return(reader->node);
1526}
1527
1528/**
1529 * xmlTextReaderNext:
1530 * @reader: the xmlTextReaderPtr used
1531 *
1532 * Skip to the node following the current one in document order while
1533 * avoiding the subtree if any.
1534 *
1535 * Returns 1 if the node was read successfully, 0 if there is no more
1536 * nodes to read, or -1 in case of error
1537 */
1538int
1539xmlTextReaderNext(xmlTextReaderPtr reader) {
1540 int ret;
1541 xmlNodePtr cur;
1542
1543 if (reader == NULL)
1544 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001545 if (reader->doc != NULL)
1546 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001547 cur = reader->node;
1548 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1549 return(xmlTextReaderRead(reader));
1550 if (reader->state == XML_TEXTREADER_END)
1551 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001552 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001553 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001554 do {
1555 ret = xmlTextReaderRead(reader);
1556 if (ret != 1)
1557 return(ret);
1558 } while (reader->node != cur);
1559 return(xmlTextReaderRead(reader));
1560}
1561
1562/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001563 * xmlTextReaderReadInnerXml:
1564 * @reader: the xmlTextReaderPtr used
1565 *
1566 * Reads the contents of the current node, including child nodes and markup.
1567 *
1568 * Returns a string containing the XML content, or NULL if the current node
1569 * is neither an element nor attribute, or has no child nodes. The
1570 * string must be deallocated by the caller.
1571 */
1572xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001573xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001574 TODO
1575 return(NULL);
1576}
1577
1578/**
1579 * xmlTextReaderReadOuterXml:
1580 * @reader: the xmlTextReaderPtr used
1581 *
1582 * Reads the contents of the current node, including child nodes and markup.
1583 *
1584 * Returns a string containing the XML content, or NULL if the current node
1585 * is neither an element nor attribute, or has no child nodes. The
1586 * string must be deallocated by the caller.
1587 */
1588xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001589xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001590 TODO
1591 return(NULL);
1592}
1593
1594/**
1595 * xmlTextReaderReadString:
1596 * @reader: the xmlTextReaderPtr used
1597 *
1598 * Reads the contents of an element or a text node as a string.
1599 *
1600 * Returns a string containing the contents of the Element or Text node,
1601 * or NULL if the reader is positioned on any other type of node.
1602 * The string must be deallocated by the caller.
1603 */
1604xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001605xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001606 TODO
1607 return(NULL);
1608}
1609
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001610#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001611/**
1612 * xmlTextReaderReadBase64:
1613 * @reader: the xmlTextReaderPtr used
1614 * @array: a byte array to store the content.
1615 * @offset: the zero-based index into array where the method should
1616 * begin to write.
1617 * @len: the number of bytes to write.
1618 *
1619 * Reads and decodes the Base64 encoded contents of an element and
1620 * stores the result in a byte buffer.
1621 *
1622 * Returns the number of bytes written to array, or zero if the current
1623 * instance is not positioned on an element or -1 in case of error.
1624 */
1625int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001626xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1627 unsigned char *array ATTRIBUTE_UNUSED,
1628 int offset ATTRIBUTE_UNUSED,
1629 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001630 if ((reader == NULL) || (reader->ctxt == NULL))
1631 return(-1);
1632 if (reader->ctxt->wellFormed != 1)
1633 return(-1);
1634
1635 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1636 return(0);
1637 TODO
1638 return(0);
1639}
1640
1641/**
1642 * xmlTextReaderReadBinHex:
1643 * @reader: the xmlTextReaderPtr used
1644 * @array: a byte array to store the content.
1645 * @offset: the zero-based index into array where the method should
1646 * begin to write.
1647 * @len: the number of bytes to write.
1648 *
1649 * Reads and decodes the BinHex encoded contents of an element and
1650 * stores the result in a byte buffer.
1651 *
1652 * Returns the number of bytes written to array, or zero if the current
1653 * instance is not positioned on an element or -1 in case of error.
1654 */
1655int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001656xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1657 unsigned char *array ATTRIBUTE_UNUSED,
1658 int offset ATTRIBUTE_UNUSED,
1659 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001660 if ((reader == NULL) || (reader->ctxt == NULL))
1661 return(-1);
1662 if (reader->ctxt->wellFormed != 1)
1663 return(-1);
1664
1665 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1666 return(0);
1667 TODO
1668 return(0);
1669}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001670#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001671
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001672/************************************************************************
1673 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001674 * Operating on a preparsed tree *
1675 * *
1676 ************************************************************************/
1677static int
1678xmlTextReaderNextTree(xmlTextReaderPtr reader)
1679{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001680 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001681 return(-1);
1682
1683 if (reader->state == XML_TEXTREADER_END)
1684 return(0);
1685
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001686 if (reader->node == NULL) {
1687 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001688 reader->state = XML_TEXTREADER_END;
1689 return(0);
1690 }
1691
1692 reader->node = reader->doc->children;
1693 reader->state = XML_TEXTREADER_START;
1694 return(1);
1695 }
1696
1697 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1698 if (reader->node->children != 0) {
1699 reader->node = reader->node->children;
1700 reader->depth++;
1701 reader->state = XML_TEXTREADER_START;
1702 return(1);
1703 }
1704
1705 if ((reader->node->type == XML_ELEMENT_NODE) ||
1706 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1707 reader->state = XML_TEXTREADER_BACKTRACK;
1708 return(1);
1709 }
1710 }
1711
1712 if (reader->node->next != 0) {
1713 reader->node = reader->node->next;
1714 reader->state = XML_TEXTREADER_START;
1715 return(1);
1716 }
1717
1718 if (reader->node->parent != 0) {
1719 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1720 reader->state = XML_TEXTREADER_END;
1721 return(0);
1722 }
1723
1724 reader->node = reader->node->parent;
1725 reader->depth--;
1726 reader->state = XML_TEXTREADER_BACKTRACK;
1727 return(1);
1728 }
1729
1730 reader->state = XML_TEXTREADER_END;
1731
1732 return(1);
1733}
1734
1735/**
1736 * xmlTextReaderReadTree:
1737 * @reader: the xmlTextReaderPtr used
1738 *
1739 * Moves the position of the current instance to the next node in
1740 * the stream, exposing its properties.
1741 *
1742 * Returns 1 if the node was read successfully, 0 if there is no more
1743 * nodes to read, or -1 in case of error
1744 */
1745static int
1746xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1747 if (reader->state == XML_TEXTREADER_END)
1748 return(0);
1749
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001750next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001751 if (reader->node == NULL) {
1752 if (reader->doc->children == NULL) {
1753 reader->state = XML_TEXTREADER_END;
1754 return(0);
1755 }
1756
1757 reader->node = reader->doc->children;
1758 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001759 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001760 }
1761
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001762 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1763 (reader->node->type != XML_DTD_NODE) &&
1764 (reader->node->type != XML_XINCLUDE_START) &&
1765 (reader->node->type != XML_ENTITY_REF_NODE)) {
1766 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001767 reader->node = reader->node->children;
1768 reader->depth++;
1769 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001770 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001771 }
1772
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001773 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001774 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001775 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001776 }
1777 }
1778
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001779 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001780 reader->node = reader->node->next;
1781 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001782 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001783 }
1784
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001785 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001786 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1787 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1788 reader->state = XML_TEXTREADER_END;
1789 return(0);
1790 }
1791
1792 reader->node = reader->node->parent;
1793 reader->depth--;
1794 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001795 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001796 }
1797
1798 reader->state = XML_TEXTREADER_END;
1799
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001800found_node:
1801 if ((reader->node->type == XML_XINCLUDE_START) ||
1802 (reader->node->type == XML_XINCLUDE_END))
1803 goto next_node;
1804
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001805 return(1);
1806}
1807
1808/**
William M. Brackb1d53162003-11-18 06:54:40 +00001809 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001810 * @reader: the xmlTextReaderPtr used
1811 *
1812 * Skip to the node following the current one in document order while
1813 * avoiding the subtree if any.
1814 * Currently implemented only for Readers built on a document
1815 *
1816 * Returns 1 if the node was read successfully, 0 if there is no more
1817 * nodes to read, or -1 in case of error
1818 */
1819int
1820xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1821 if (reader == NULL)
1822 return(-1);
1823 if (reader->doc == NULL) {
1824 TODO
1825 return(-1);
1826 }
1827
1828 if (reader->state == XML_TEXTREADER_END)
1829 return(0);
1830
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001831 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001832 return(xmlTextReaderNextTree(reader));
1833
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001834 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001835 reader->node = reader->node->next;
1836 reader->state = XML_TEXTREADER_START;
1837 return(1);
1838 }
1839
1840 return(0);
1841}
1842
1843/************************************************************************
1844 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001845 * Constructor and destructors *
1846 * *
1847 ************************************************************************/
1848/**
1849 * xmlNewTextReader:
1850 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001851 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001852 *
1853 * Create an xmlTextReader structure fed with @input
1854 *
1855 * Returns the new xmlTextReaderPtr or NULL in case of error
1856 */
1857xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001858xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001859 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001860
1861 if (input == NULL)
1862 return(NULL);
1863 ret = xmlMalloc(sizeof(xmlTextReader));
1864 if (ret == NULL) {
1865 xmlGenericError(xmlGenericErrorContext,
1866 "xmlNewTextReader : malloc failed\n");
1867 return(NULL);
1868 }
1869 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001870 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001871 ret->entTab = NULL;
1872 ret->entMax = 0;
1873 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001874 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001875 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001876 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1877 if (ret->sax == NULL) {
1878 xmlFree(ret);
1879 xmlGenericError(xmlGenericErrorContext,
1880 "xmlNewTextReader : malloc failed\n");
1881 return(NULL);
1882 }
Daniel Veillard81273902003-09-30 00:43:48 +00001883 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001884 ret->startElement = ret->sax->startElement;
1885 ret->sax->startElement = xmlTextReaderStartElement;
1886 ret->endElement = ret->sax->endElement;
1887 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001888#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001889 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001890#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001891 ret->startElementNs = ret->sax->startElementNs;
1892 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1893 ret->endElementNs = ret->sax->endElementNs;
1894 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001895#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001896 } else {
1897 ret->startElementNs = NULL;
1898 ret->endElementNs = NULL;
1899 }
Daniel Veillard81273902003-09-30 00:43:48 +00001900#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001901 ret->characters = ret->sax->characters;
1902 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001903 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001904 ret->cdataBlock = ret->sax->cdataBlock;
1905 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001906
Daniel Veillard67df8092002-12-16 22:04:11 +00001907 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001908 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001909 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001910 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001911 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001912 }
1913 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001914 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001915 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001916 ret->base = 0;
1917 ret->cur = 4;
1918 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001919 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001920 ret->base = 0;
1921 ret->cur = 0;
1922 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001923 if (ret->ctxt == NULL) {
1924 xmlGenericError(xmlGenericErrorContext,
1925 "xmlNewTextReader : malloc failed\n");
1926 xmlFree(ret->sax);
1927 xmlFree(ret);
1928 return(NULL);
1929 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001930 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001931 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001932 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001933 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001934 /*
1935 * use the parser dictionnary to allocate all elements and attributes names
1936 */
1937 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001938 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001939#ifdef LIBXML_XINCLUDE_ENABLED
1940 ret->xinclude = 0;
1941#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001942#ifdef LIBXML_PATTERN_ENABLED
1943 ret->patternMax = 0;
1944 ret->patternTab = NULL;
1945#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001946 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001947}
1948
1949/**
1950 * xmlNewTextReaderFilename:
1951 * @URI: the URI of the resource to process
1952 *
1953 * Create an xmlTextReader structure fed with the resource at @URI
1954 *
1955 * Returns the new xmlTextReaderPtr or NULL in case of error
1956 */
1957xmlTextReaderPtr
1958xmlNewTextReaderFilename(const char *URI) {
1959 xmlParserInputBufferPtr input;
1960 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001961 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001962
1963 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1964 if (input == NULL)
1965 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001966 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001967 if (ret == NULL) {
1968 xmlFreeParserInputBuffer(input);
1969 return(NULL);
1970 }
1971 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001972 if (ret->ctxt->directory == NULL)
1973 directory = xmlParserGetDirectory(URI);
1974 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1975 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1976 if (directory != NULL)
1977 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001978 return(ret);
1979}
1980
1981/**
1982 * xmlFreeTextReader:
1983 * @reader: the xmlTextReaderPtr
1984 *
1985 * Deallocate all the resources associated to the reader
1986 */
1987void
1988xmlFreeTextReader(xmlTextReaderPtr reader) {
1989 if (reader == NULL)
1990 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001991#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001992 if (reader->rngSchemas != NULL) {
1993 xmlRelaxNGFree(reader->rngSchemas);
1994 reader->rngSchemas = NULL;
1995 }
1996 if (reader->rngValidCtxt != NULL) {
1997 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1998 reader->rngValidCtxt = NULL;
1999 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002000#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002001#ifdef LIBXML_XINCLUDE_ENABLED
2002 if (reader->xincctxt != NULL)
2003 xmlXIncludeFreeContext(reader->xincctxt);
2004#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002005#ifdef LIBXML_PATTERN_ENABLED
2006 if (reader->patternTab != NULL) {
2007 int i;
2008 for (i = 0;i < reader->patternNr;i++) {
2009 if (reader->patternTab[i] != NULL)
2010 xmlFreePattern(reader->patternTab[i]);
2011 }
2012 xmlFree(reader->patternTab);
2013 }
2014#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002015 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002016 if (reader->dict == reader->ctxt->dict)
2017 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002018 if (reader->ctxt->myDoc != NULL) {
2019 if (reader->preserve == 0)
2020 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2021 reader->ctxt->myDoc = NULL;
2022 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002023 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2024 (reader->ctxt->vctxt.vstateMax > 0)){
2025 xmlFree(reader->ctxt->vctxt.vstateTab);
2026 reader->ctxt->vctxt.vstateTab = 0;
2027 reader->ctxt->vctxt.vstateMax = 0;
2028 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002029 if (reader->allocs & XML_TEXTREADER_CTXT)
2030 xmlFreeParserCtxt(reader->ctxt);
2031 }
2032 if (reader->sax != NULL)
2033 xmlFree(reader->sax);
2034 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2035 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002036 if (reader->faketext != NULL) {
2037 xmlFreeNode(reader->faketext);
2038 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002039 if (reader->buffer != NULL)
2040 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002041 if (reader->entTab != NULL)
2042 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002043 if (reader->dict != NULL)
2044 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002045 xmlFree(reader);
2046}
2047
2048/************************************************************************
2049 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002050 * Methods for XmlTextReader *
2051 * *
2052 ************************************************************************/
2053/**
2054 * xmlTextReaderClose:
2055 * @reader: the xmlTextReaderPtr used
2056 *
2057 * This method releases any resources allocated by the current instance
2058 * changes the state to Closed and close any underlying input.
2059 *
2060 * Returns 0 or -1 in case of error
2061 */
2062int
2063xmlTextReaderClose(xmlTextReaderPtr reader) {
2064 if (reader == NULL)
2065 return(-1);
2066 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002067 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002068 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2069 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002070 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002071 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002072 if (reader->preserve == 0)
2073 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002074 reader->ctxt->myDoc = NULL;
2075 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002076 }
2077 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2078 xmlFreeParserInputBuffer(reader->input);
2079 reader->allocs -= XML_TEXTREADER_INPUT;
2080 }
2081 return(0);
2082}
2083
2084/**
2085 * xmlTextReaderGetAttributeNo:
2086 * @reader: the xmlTextReaderPtr used
2087 * @no: the zero-based index of the attribute relative to the containing element
2088 *
2089 * Provides the value of the attribute with the specified index relative
2090 * to the containing element.
2091 *
2092 * Returns a string containing the value of the specified attribute, or NULL
2093 * in case of error. The string must be deallocated by the caller.
2094 */
2095xmlChar *
2096xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2097 xmlChar *ret;
2098 int i;
2099 xmlAttrPtr cur;
2100 xmlNsPtr ns;
2101
2102 if (reader == NULL)
2103 return(NULL);
2104 if (reader->node == NULL)
2105 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002106 if (reader->curnode != NULL)
2107 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002108 /* TODO: handle the xmlDecl */
2109 if (reader->node->type != XML_ELEMENT_NODE)
2110 return(NULL);
2111
2112 ns = reader->node->nsDef;
2113 for (i = 0;(i < no) && (ns != NULL);i++) {
2114 ns = ns->next;
2115 }
2116 if (ns != NULL)
2117 return(xmlStrdup(ns->href));
2118
2119 cur = reader->node->properties;
2120 if (cur == NULL)
2121 return(NULL);
2122 for (;i < no;i++) {
2123 cur = cur->next;
2124 if (cur == NULL)
2125 return(NULL);
2126 }
2127 /* TODO walk the DTD if present */
2128
2129 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2130 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2131 return(ret);
2132}
2133
2134/**
2135 * xmlTextReaderGetAttribute:
2136 * @reader: the xmlTextReaderPtr used
2137 * @name: the qualified name of the attribute.
2138 *
2139 * Provides the value of the attribute with the specified qualified name.
2140 *
2141 * Returns a string containing the value of the specified attribute, or NULL
2142 * in case of error. The string must be deallocated by the caller.
2143 */
2144xmlChar *
2145xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2146 xmlChar *prefix = NULL;
2147 xmlChar *localname;
2148 xmlNsPtr ns;
2149 xmlChar *ret = NULL;
2150
2151 if ((reader == NULL) || (name == NULL))
2152 return(NULL);
2153 if (reader->node == NULL)
2154 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002155 if (reader->curnode != NULL)
2156 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002157
2158 /* TODO: handle the xmlDecl */
2159 if (reader->node->type != XML_ELEMENT_NODE)
2160 return(NULL);
2161
2162 localname = xmlSplitQName2(name, &prefix);
2163 if (localname == NULL)
2164 return(xmlGetProp(reader->node, name));
2165
2166 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2167 if (ns != NULL)
2168 ret = xmlGetNsProp(reader->node, localname, ns->href);
2169
2170 if (localname != NULL)
2171 xmlFree(localname);
2172 if (prefix != NULL)
2173 xmlFree(prefix);
2174 return(ret);
2175}
2176
2177
2178/**
2179 * xmlTextReaderGetAttributeNs:
2180 * @reader: the xmlTextReaderPtr used
2181 * @localName: the local name of the attribute.
2182 * @namespaceURI: the namespace URI of the attribute.
2183 *
2184 * Provides the value of the specified attribute
2185 *
2186 * Returns a string containing the value of the specified attribute, or NULL
2187 * in case of error. The string must be deallocated by the caller.
2188 */
2189xmlChar *
2190xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2191 const xmlChar *namespaceURI) {
2192 if ((reader == NULL) || (localName == NULL))
2193 return(NULL);
2194 if (reader->node == NULL)
2195 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002196 if (reader->curnode != NULL)
2197 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002198
2199 /* TODO: handle the xmlDecl */
2200 if (reader->node->type != XML_ELEMENT_NODE)
2201 return(NULL);
2202
2203 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2204}
2205
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002206/**
2207 * xmlTextReaderGetRemainder:
2208 * @reader: the xmlTextReaderPtr used
2209 *
2210 * Method to get the remainder of the buffered XML. this method stops the
2211 * parser, set its state to End Of File and return the input stream with
2212 * what is left that the parser did not use.
2213 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002214 * The implementation is not good, the parser certainly procgressed past
2215 * what's left in reader->input, and there is an allocation problem. Best
2216 * would be to rewrite it differently.
2217 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002218 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2219 * in case of error.
2220 */
2221xmlParserInputBufferPtr
2222xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2223 xmlParserInputBufferPtr ret = NULL;
2224
2225 if (reader == NULL)
2226 return(NULL);
2227 if (reader->node == NULL)
2228 return(NULL);
2229
2230 reader->node = NULL;
2231 reader->curnode = NULL;
2232 reader->mode = XML_TEXTREADER_MODE_EOF;
2233 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002234 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002235 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002236 if (reader->preserve == 0)
2237 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002238 reader->ctxt->myDoc = NULL;
2239 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002240 }
2241 if (reader->allocs & XML_TEXTREADER_INPUT) {
2242 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002243 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002244 reader->allocs -= XML_TEXTREADER_INPUT;
2245 } else {
2246 /*
2247 * Hum, one may need to duplicate the data structure because
2248 * without reference counting the input may be freed twice:
2249 * - by the layer which allocated it.
2250 * - by the layer to which would have been returned to.
2251 */
2252 TODO
2253 return(NULL);
2254 }
2255 return(ret);
2256}
2257
2258/**
2259 * xmlTextReaderLookupNamespace:
2260 * @reader: the xmlTextReaderPtr used
2261 * @prefix: the prefix whose namespace URI is to be resolved. To return
2262 * the default namespace, specify NULL
2263 *
2264 * Resolves a namespace prefix in the scope of the current element.
2265 *
2266 * Returns a string containing the namespace URI to which the prefix maps
2267 * or NULL in case of error. The string must be deallocated by the caller.
2268 */
2269xmlChar *
2270xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2271 xmlNsPtr ns;
2272
2273 if (reader == NULL)
2274 return(NULL);
2275 if (reader->node == NULL)
2276 return(NULL);
2277
2278 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2279 if (ns == NULL)
2280 return(NULL);
2281 return(xmlStrdup(ns->href));
2282}
2283
2284/**
2285 * xmlTextReaderMoveToAttributeNo:
2286 * @reader: the xmlTextReaderPtr used
2287 * @no: the zero-based index of the attribute relative to the containing
2288 * element.
2289 *
2290 * Moves the position of the current instance to the attribute with
2291 * the specified index relative to the containing element.
2292 *
2293 * Returns 1 in case of success, -1 in case of error, 0 if not found
2294 */
2295int
2296xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2297 int i;
2298 xmlAttrPtr cur;
2299 xmlNsPtr ns;
2300
2301 if (reader == NULL)
2302 return(-1);
2303 if (reader->node == NULL)
2304 return(-1);
2305 /* TODO: handle the xmlDecl */
2306 if (reader->node->type != XML_ELEMENT_NODE)
2307 return(-1);
2308
2309 reader->curnode = NULL;
2310
2311 ns = reader->node->nsDef;
2312 for (i = 0;(i < no) && (ns != NULL);i++) {
2313 ns = ns->next;
2314 }
2315 if (ns != NULL) {
2316 reader->curnode = (xmlNodePtr) ns;
2317 return(1);
2318 }
2319
2320 cur = reader->node->properties;
2321 if (cur == NULL)
2322 return(0);
2323 for (;i < no;i++) {
2324 cur = cur->next;
2325 if (cur == NULL)
2326 return(0);
2327 }
2328 /* TODO walk the DTD if present */
2329
2330 reader->curnode = (xmlNodePtr) cur;
2331 return(1);
2332}
2333
2334/**
2335 * xmlTextReaderMoveToAttribute:
2336 * @reader: the xmlTextReaderPtr used
2337 * @name: the qualified name of the attribute.
2338 *
2339 * Moves the position of the current instance to the attribute with
2340 * the specified qualified name.
2341 *
2342 * Returns 1 in case of success, -1 in case of error, 0 if not found
2343 */
2344int
2345xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2346 xmlChar *prefix = NULL;
2347 xmlChar *localname;
2348 xmlNsPtr ns;
2349 xmlAttrPtr prop;
2350
2351 if ((reader == NULL) || (name == NULL))
2352 return(-1);
2353 if (reader->node == NULL)
2354 return(-1);
2355
2356 /* TODO: handle the xmlDecl */
2357 if (reader->node->type != XML_ELEMENT_NODE)
2358 return(0);
2359
2360 localname = xmlSplitQName2(name, &prefix);
2361 if (localname == NULL) {
2362 /*
2363 * Namespace default decl
2364 */
2365 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2366 ns = reader->node->nsDef;
2367 while (ns != NULL) {
2368 if (ns->prefix == NULL) {
2369 reader->curnode = (xmlNodePtr) ns;
2370 return(1);
2371 }
2372 ns = ns->next;
2373 }
2374 return(0);
2375 }
2376
2377 prop = reader->node->properties;
2378 while (prop != NULL) {
2379 /*
2380 * One need to have
2381 * - same attribute names
2382 * - and the attribute carrying that namespace
2383 */
2384 if ((xmlStrEqual(prop->name, name)) &&
2385 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2386 reader->curnode = (xmlNodePtr) prop;
2387 return(1);
2388 }
2389 prop = prop->next;
2390 }
2391 return(0);
2392 }
2393
2394 /*
2395 * Namespace default decl
2396 */
2397 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2398 ns = reader->node->nsDef;
2399 while (ns != NULL) {
2400 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2401 reader->curnode = (xmlNodePtr) ns;
2402 goto found;
2403 }
2404 ns = ns->next;
2405 }
2406 goto not_found;
2407 }
2408 prop = reader->node->properties;
2409 while (prop != NULL) {
2410 /*
2411 * One need to have
2412 * - same attribute names
2413 * - and the attribute carrying that namespace
2414 */
2415 if ((xmlStrEqual(prop->name, localname)) &&
2416 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2417 reader->curnode = (xmlNodePtr) prop;
2418 goto found;
2419 }
2420 prop = prop->next;
2421 }
2422not_found:
2423 if (localname != NULL)
2424 xmlFree(localname);
2425 if (prefix != NULL)
2426 xmlFree(prefix);
2427 return(0);
2428
2429found:
2430 if (localname != NULL)
2431 xmlFree(localname);
2432 if (prefix != NULL)
2433 xmlFree(prefix);
2434 return(1);
2435}
2436
2437/**
2438 * xmlTextReaderMoveToAttributeNs:
2439 * @reader: the xmlTextReaderPtr used
2440 * @localName: the local name of the attribute.
2441 * @namespaceURI: the namespace URI of the attribute.
2442 *
2443 * Moves the position of the current instance to the attribute with the
2444 * specified local name and namespace URI.
2445 *
2446 * Returns 1 in case of success, -1 in case of error, 0 if not found
2447 */
2448int
2449xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2450 const xmlChar *localName, const xmlChar *namespaceURI) {
2451 xmlAttrPtr prop;
2452 xmlNodePtr node;
2453
2454 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2455 return(-1);
2456 if (reader->node == NULL)
2457 return(-1);
2458 if (reader->node->type != XML_ELEMENT_NODE)
2459 return(0);
2460 node = reader->node;
2461
2462 /*
2463 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2464 * namespace name associated to "xmlns"
2465 */
2466 prop = node->properties;
2467 while (prop != NULL) {
2468 /*
2469 * One need to have
2470 * - same attribute names
2471 * - and the attribute carrying that namespace
2472 */
2473 if (xmlStrEqual(prop->name, localName) &&
2474 ((prop->ns != NULL) &&
2475 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2476 reader->curnode = (xmlNodePtr) prop;
2477 return(1);
2478 }
2479 prop = prop->next;
2480 }
2481 return(0);
2482}
2483
2484/**
2485 * xmlTextReaderMoveToFirstAttribute:
2486 * @reader: the xmlTextReaderPtr used
2487 *
2488 * Moves the position of the current instance to the first attribute
2489 * associated with the current node.
2490 *
2491 * Returns 1 in case of success, -1 in case of error, 0 if not found
2492 */
2493int
2494xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2495 if (reader == NULL)
2496 return(-1);
2497 if (reader->node == NULL)
2498 return(-1);
2499 if (reader->node->type != XML_ELEMENT_NODE)
2500 return(0);
2501
2502 if (reader->node->nsDef != NULL) {
2503 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2504 return(1);
2505 }
2506 if (reader->node->properties != NULL) {
2507 reader->curnode = (xmlNodePtr) reader->node->properties;
2508 return(1);
2509 }
2510 return(0);
2511}
2512
2513/**
2514 * xmlTextReaderMoveToNextAttribute:
2515 * @reader: the xmlTextReaderPtr used
2516 *
2517 * Moves the position of the current instance to the next attribute
2518 * associated with the current node.
2519 *
2520 * Returns 1 in case of success, -1 in case of error, 0 if not found
2521 */
2522int
2523xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2524 if (reader == NULL)
2525 return(-1);
2526 if (reader->node == NULL)
2527 return(-1);
2528 if (reader->node->type != XML_ELEMENT_NODE)
2529 return(0);
2530 if (reader->curnode == NULL)
2531 return(xmlTextReaderMoveToFirstAttribute(reader));
2532
2533 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2534 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2535 if (ns->next != NULL) {
2536 reader->curnode = (xmlNodePtr) ns->next;
2537 return(1);
2538 }
2539 if (reader->node->properties != NULL) {
2540 reader->curnode = (xmlNodePtr) reader->node->properties;
2541 return(1);
2542 }
2543 return(0);
2544 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2545 (reader->curnode->next != NULL)) {
2546 reader->curnode = reader->curnode->next;
2547 return(1);
2548 }
2549 return(0);
2550}
2551
2552/**
2553 * xmlTextReaderMoveToElement:
2554 * @reader: the xmlTextReaderPtr used
2555 *
2556 * Moves the position of the current instance to the node that
2557 * contains the current Attribute node.
2558 *
2559 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2560 */
2561int
2562xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2563 if (reader == NULL)
2564 return(-1);
2565 if (reader->node == NULL)
2566 return(-1);
2567 if (reader->node->type != XML_ELEMENT_NODE)
2568 return(0);
2569 if (reader->curnode != NULL) {
2570 reader->curnode = NULL;
2571 return(1);
2572 }
2573 return(0);
2574}
2575
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002576/**
2577 * xmlTextReaderReadAttributeValue:
2578 * @reader: the xmlTextReaderPtr used
2579 *
2580 * Parses an attribute value into one or more Text and EntityReference nodes.
2581 *
2582 * Returns 1 in case of success, 0 if the reader was not positionned on an
2583 * ttribute node or all the attribute values have been read, or -1
2584 * in case of error.
2585 */
2586int
2587xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2588 if (reader == NULL)
2589 return(-1);
2590 if (reader->node == NULL)
2591 return(-1);
2592 if (reader->curnode == NULL)
2593 return(0);
2594 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2595 if (reader->curnode->children == NULL)
2596 return(0);
2597 reader->curnode = reader->curnode->children;
2598 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2599 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2600
2601 if (reader->faketext == NULL) {
2602 reader->faketext = xmlNewDocText(reader->node->doc,
2603 ns->href);
2604 } else {
2605 if (reader->faketext->content != NULL)
2606 xmlFree(reader->faketext->content);
2607 reader->faketext->content = xmlStrdup(ns->href);
2608 }
2609 reader->curnode = reader->faketext;
2610 } else {
2611 if (reader->curnode->next == NULL)
2612 return(0);
2613 reader->curnode = reader->curnode->next;
2614 }
2615 return(1);
2616}
2617
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002618/************************************************************************
2619 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002620 * Acces API to the current node *
2621 * *
2622 ************************************************************************/
2623/**
2624 * xmlTextReaderAttributeCount:
2625 * @reader: the xmlTextReaderPtr used
2626 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002627 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002628 *
2629 * Returns 0 i no attributes, -1 in case of error or the attribute count
2630 */
2631int
2632xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2633 int ret;
2634 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002635 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002636 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002637
2638 if (reader == NULL)
2639 return(-1);
2640 if (reader->node == NULL)
2641 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002642
2643 if (reader->curnode != NULL)
2644 node = reader->curnode;
2645 else
2646 node = reader->node;
2647
2648 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002649 return(0);
2650 if ((reader->state == XML_TEXTREADER_END) ||
2651 (reader->state == XML_TEXTREADER_BACKTRACK))
2652 return(0);
2653 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002654 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002655 while (attr != NULL) {
2656 ret++;
2657 attr = attr->next;
2658 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002659 ns = node->nsDef;
2660 while (ns != NULL) {
2661 ret++;
2662 ns = ns->next;
2663 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002664 return(ret);
2665}
2666
2667/**
2668 * xmlTextReaderNodeType:
2669 * @reader: the xmlTextReaderPtr used
2670 *
2671 * Get the node type of the current node
2672 * Reference:
2673 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2674 *
2675 * Returns the xmlNodeType of the current node or -1 in case of error
2676 */
2677int
2678xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002679 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002680
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002681 if (reader == NULL)
2682 return(-1);
2683 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002684 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002685 if (reader->curnode != NULL)
2686 node = reader->curnode;
2687 else
2688 node = reader->node;
2689 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002690 case XML_ELEMENT_NODE:
2691 if ((reader->state == XML_TEXTREADER_END) ||
2692 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002693 return(XML_READER_TYPE_END_ELEMENT);
2694 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002695 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002696 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002697 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002698 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002699 if (xmlIsBlankNode(reader->node)) {
2700 if (xmlNodeGetSpacePreserve(reader->node))
2701 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2702 else
2703 return(XML_READER_TYPE_WHITESPACE);
2704 } else {
2705 return(XML_READER_TYPE_TEXT);
2706 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002707 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002708 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002709 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002710 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002711 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002712 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002713 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002714 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002715 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002716 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002717 case XML_DOCUMENT_NODE:
2718 case XML_HTML_DOCUMENT_NODE:
2719#ifdef LIBXML_DOCB_ENABLED
2720 case XML_DOCB_DOCUMENT_NODE:
2721#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002722 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002723 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002724 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002725 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002726 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002727 case XML_DOCUMENT_TYPE_NODE:
2728 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002729 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002730
2731 case XML_ELEMENT_DECL:
2732 case XML_ATTRIBUTE_DECL:
2733 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002734 case XML_XINCLUDE_START:
2735 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002736 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002737 }
2738 return(-1);
2739}
2740
2741/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002742 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002743 * @reader: the xmlTextReaderPtr used
2744 *
2745 * Check if the current node is empty
2746 *
2747 * Returns 1 if empty, 0 if not and -1 in case of error
2748 */
2749int
2750xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2751 if ((reader == NULL) || (reader->node == NULL))
2752 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002753 if (reader->node->type != XML_ELEMENT_NODE)
2754 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002755 if (reader->curnode != NULL)
2756 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002757 if (reader->node->children != NULL)
2758 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002759 if (reader->state == XML_TEXTREADER_END)
2760 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002761 if (reader->doc != NULL)
2762 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002763#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002764 if (reader->in_xinclude > 0)
2765 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002766#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002767 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002768}
2769
2770/**
2771 * xmlTextReaderLocalName:
2772 * @reader: the xmlTextReaderPtr used
2773 *
2774 * The local name of the node.
2775 *
2776 * Returns the local name or NULL if not available
2777 */
2778xmlChar *
2779xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002780 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002781 if ((reader == NULL) || (reader->node == NULL))
2782 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002783 if (reader->curnode != NULL)
2784 node = reader->curnode;
2785 else
2786 node = reader->node;
2787 if (node->type == XML_NAMESPACE_DECL) {
2788 xmlNsPtr ns = (xmlNsPtr) node;
2789 if (ns->prefix == NULL)
2790 return(xmlStrdup(BAD_CAST "xmlns"));
2791 else
2792 return(xmlStrdup(ns->prefix));
2793 }
2794 if ((node->type != XML_ELEMENT_NODE) &&
2795 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002796 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002797 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002798}
2799
2800/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002801 * xmlTextReaderConstLocalName:
2802 * @reader: the xmlTextReaderPtr used
2803 *
2804 * The local name of the node.
2805 *
2806 * Returns the local name or NULL if not available, the
2807 * string will be deallocated with the reader.
2808 */
2809const xmlChar *
2810xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2811 xmlNodePtr node;
2812 if ((reader == NULL) || (reader->node == NULL))
2813 return(NULL);
2814 if (reader->curnode != NULL)
2815 node = reader->curnode;
2816 else
2817 node = reader->node;
2818 if (node->type == XML_NAMESPACE_DECL) {
2819 xmlNsPtr ns = (xmlNsPtr) node;
2820 if (ns->prefix == NULL)
2821 return(CONSTSTR(BAD_CAST "xmlns"));
2822 else
2823 return(ns->prefix);
2824 }
2825 if ((node->type != XML_ELEMENT_NODE) &&
2826 (node->type != XML_ATTRIBUTE_NODE))
2827 return(xmlTextReaderConstName(reader));
2828 return(node->name);
2829}
2830
2831/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002832 * xmlTextReaderName:
2833 * @reader: the xmlTextReaderPtr used
2834 *
2835 * The qualified name of the node, equal to Prefix :LocalName.
2836 *
2837 * Returns the local name or NULL if not available
2838 */
2839xmlChar *
2840xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002841 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002842 xmlChar *ret;
2843
2844 if ((reader == NULL) || (reader->node == NULL))
2845 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002846 if (reader->curnode != NULL)
2847 node = reader->curnode;
2848 else
2849 node = reader->node;
2850 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002851 case XML_ELEMENT_NODE:
2852 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002853 if ((node->ns == NULL) ||
2854 (node->ns->prefix == NULL))
2855 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002856
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002857 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002858 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002859 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002860 return(ret);
2861 case XML_TEXT_NODE:
2862 return(xmlStrdup(BAD_CAST "#text"));
2863 case XML_CDATA_SECTION_NODE:
2864 return(xmlStrdup(BAD_CAST "#cdata-section"));
2865 case XML_ENTITY_NODE:
2866 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002867 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002868 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002869 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002870 case XML_COMMENT_NODE:
2871 return(xmlStrdup(BAD_CAST "#comment"));
2872 case XML_DOCUMENT_NODE:
2873 case XML_HTML_DOCUMENT_NODE:
2874#ifdef LIBXML_DOCB_ENABLED
2875 case XML_DOCB_DOCUMENT_NODE:
2876#endif
2877 return(xmlStrdup(BAD_CAST "#document"));
2878 case XML_DOCUMENT_FRAG_NODE:
2879 return(xmlStrdup(BAD_CAST "#document-fragment"));
2880 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002881 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002882 case XML_DOCUMENT_TYPE_NODE:
2883 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002884 return(xmlStrdup(node->name));
2885 case XML_NAMESPACE_DECL: {
2886 xmlNsPtr ns = (xmlNsPtr) node;
2887
2888 ret = xmlStrdup(BAD_CAST "xmlns");
2889 if (ns->prefix == NULL)
2890 return(ret);
2891 ret = xmlStrcat(ret, BAD_CAST ":");
2892 ret = xmlStrcat(ret, ns->prefix);
2893 return(ret);
2894 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002895
2896 case XML_ELEMENT_DECL:
2897 case XML_ATTRIBUTE_DECL:
2898 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002899 case XML_XINCLUDE_START:
2900 case XML_XINCLUDE_END:
2901 return(NULL);
2902 }
2903 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002904}
2905
2906/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002907 * xmlTextReaderConstName:
2908 * @reader: the xmlTextReaderPtr used
2909 *
2910 * The qualified name of the node, equal to Prefix :LocalName.
2911 *
2912 * Returns the local name or NULL if not available, the string is
2913 * deallocated with the reader.
2914 */
2915const xmlChar *
2916xmlTextReaderConstName(xmlTextReaderPtr reader) {
2917 xmlNodePtr node;
2918
2919 if ((reader == NULL) || (reader->node == NULL))
2920 return(NULL);
2921 if (reader->curnode != NULL)
2922 node = reader->curnode;
2923 else
2924 node = reader->node;
2925 switch (node->type) {
2926 case XML_ELEMENT_NODE:
2927 case XML_ATTRIBUTE_NODE:
2928 if ((node->ns == NULL) ||
2929 (node->ns->prefix == NULL))
2930 return(node->name);
2931 return(CONSTQSTR(node->ns->prefix, node->name));
2932 case XML_TEXT_NODE:
2933 return(CONSTSTR(BAD_CAST "#text"));
2934 case XML_CDATA_SECTION_NODE:
2935 return(CONSTSTR(BAD_CAST "#cdata-section"));
2936 case XML_ENTITY_NODE:
2937 case XML_ENTITY_REF_NODE:
2938 return(CONSTSTR(node->name));
2939 case XML_PI_NODE:
2940 return(CONSTSTR(node->name));
2941 case XML_COMMENT_NODE:
2942 return(CONSTSTR(BAD_CAST "#comment"));
2943 case XML_DOCUMENT_NODE:
2944 case XML_HTML_DOCUMENT_NODE:
2945#ifdef LIBXML_DOCB_ENABLED
2946 case XML_DOCB_DOCUMENT_NODE:
2947#endif
2948 return(CONSTSTR(BAD_CAST "#document"));
2949 case XML_DOCUMENT_FRAG_NODE:
2950 return(CONSTSTR(BAD_CAST "#document-fragment"));
2951 case XML_NOTATION_NODE:
2952 return(CONSTSTR(node->name));
2953 case XML_DOCUMENT_TYPE_NODE:
2954 case XML_DTD_NODE:
2955 return(CONSTSTR(node->name));
2956 case XML_NAMESPACE_DECL: {
2957 xmlNsPtr ns = (xmlNsPtr) node;
2958
2959 if (ns->prefix == NULL)
2960 return(CONSTSTR(BAD_CAST "xmlns"));
2961 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2962 }
2963
2964 case XML_ELEMENT_DECL:
2965 case XML_ATTRIBUTE_DECL:
2966 case XML_ENTITY_DECL:
2967 case XML_XINCLUDE_START:
2968 case XML_XINCLUDE_END:
2969 return(NULL);
2970 }
2971 return(NULL);
2972}
2973
2974/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002975 * xmlTextReaderPrefix:
2976 * @reader: the xmlTextReaderPtr used
2977 *
2978 * A shorthand reference to the namespace associated with the node.
2979 *
2980 * Returns the prefix or NULL if not available
2981 */
2982xmlChar *
2983xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002984 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002985 if ((reader == NULL) || (reader->node == NULL))
2986 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002987 if (reader->curnode != NULL)
2988 node = reader->curnode;
2989 else
2990 node = reader->node;
2991 if (node->type == XML_NAMESPACE_DECL) {
2992 xmlNsPtr ns = (xmlNsPtr) node;
2993 if (ns->prefix == NULL)
2994 return(NULL);
2995 return(xmlStrdup(BAD_CAST "xmlns"));
2996 }
2997 if ((node->type != XML_ELEMENT_NODE) &&
2998 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002999 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003000 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003001 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003002 return(NULL);
3003}
3004
3005/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003006 * xmlTextReaderConstPrefix:
3007 * @reader: the xmlTextReaderPtr used
3008 *
3009 * A shorthand reference to the namespace associated with the node.
3010 *
3011 * Returns the prefix or NULL if not available, the string is deallocated
3012 * with the reader.
3013 */
3014const xmlChar *
3015xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3016 xmlNodePtr node;
3017 if ((reader == NULL) || (reader->node == NULL))
3018 return(NULL);
3019 if (reader->curnode != NULL)
3020 node = reader->curnode;
3021 else
3022 node = reader->node;
3023 if (node->type == XML_NAMESPACE_DECL) {
3024 xmlNsPtr ns = (xmlNsPtr) node;
3025 if (ns->prefix == NULL)
3026 return(NULL);
3027 return(CONSTSTR(BAD_CAST "xmlns"));
3028 }
3029 if ((node->type != XML_ELEMENT_NODE) &&
3030 (node->type != XML_ATTRIBUTE_NODE))
3031 return(NULL);
3032 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3033 return(CONSTSTR(node->ns->prefix));
3034 return(NULL);
3035}
3036
3037/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003038 * xmlTextReaderNamespaceUri:
3039 * @reader: the xmlTextReaderPtr used
3040 *
3041 * The URI defining the namespace associated with the node.
3042 *
3043 * Returns the namespace URI or NULL if not available
3044 */
3045xmlChar *
3046xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003047 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003048 if ((reader == NULL) || (reader->node == NULL))
3049 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003050 if (reader->curnode != NULL)
3051 node = reader->curnode;
3052 else
3053 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003054 if (node->type == XML_NAMESPACE_DECL)
3055 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003056 if ((node->type != XML_ELEMENT_NODE) &&
3057 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003058 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003059 if (node->ns != NULL)
3060 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003061 return(NULL);
3062}
3063
3064/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003065 * xmlTextReaderConstNamespaceUri:
3066 * @reader: the xmlTextReaderPtr used
3067 *
3068 * The URI defining the namespace associated with the node.
3069 *
3070 * Returns the namespace URI or NULL if not available, the string
3071 * will be deallocated with the reader
3072 */
3073const xmlChar *
3074xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3075 xmlNodePtr node;
3076 if ((reader == NULL) || (reader->node == NULL))
3077 return(NULL);
3078 if (reader->curnode != NULL)
3079 node = reader->curnode;
3080 else
3081 node = reader->node;
3082 if (node->type == XML_NAMESPACE_DECL)
3083 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3084 if ((node->type != XML_ELEMENT_NODE) &&
3085 (node->type != XML_ATTRIBUTE_NODE))
3086 return(NULL);
3087 if (node->ns != NULL)
3088 return(CONSTSTR(node->ns->href));
3089 return(NULL);
3090}
3091
3092/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003093 * xmlTextReaderBaseUri:
3094 * @reader: the xmlTextReaderPtr used
3095 *
3096 * The base URI of the node.
3097 *
3098 * Returns the base URI or NULL if not available
3099 */
3100xmlChar *
3101xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3102 if ((reader == NULL) || (reader->node == NULL))
3103 return(NULL);
3104 return(xmlNodeGetBase(NULL, reader->node));
3105}
3106
3107/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003108 * xmlTextReaderConstBaseUri:
3109 * @reader: the xmlTextReaderPtr used
3110 *
3111 * The base URI of the node.
3112 *
3113 * Returns the base URI or NULL if not available, the string
3114 * will be deallocated with the reader
3115 */
3116const xmlChar *
3117xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3118 xmlChar *tmp;
3119 const xmlChar *ret;
3120
3121 if ((reader == NULL) || (reader->node == NULL))
3122 return(NULL);
3123 tmp = xmlNodeGetBase(NULL, reader->node);
3124 if (tmp == NULL)
3125 return(NULL);
3126 ret = CONSTSTR(tmp);
3127 xmlFree(tmp);
3128 return(ret);
3129}
3130
3131/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003132 * xmlTextReaderDepth:
3133 * @reader: the xmlTextReaderPtr used
3134 *
3135 * The depth of the node in the tree.
3136 *
3137 * Returns the depth or -1 in case of error
3138 */
3139int
3140xmlTextReaderDepth(xmlTextReaderPtr reader) {
3141 if (reader == NULL)
3142 return(-1);
3143 if (reader->node == NULL)
3144 return(0);
3145
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003146 if (reader->curnode != NULL) {
3147 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3148 (reader->curnode->type == XML_NAMESPACE_DECL))
3149 return(reader->depth + 1);
3150 return(reader->depth + 2);
3151 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003152 return(reader->depth);
3153}
3154
3155/**
3156 * xmlTextReaderHasAttributes:
3157 * @reader: the xmlTextReaderPtr used
3158 *
3159 * Whether the node has attributes.
3160 *
3161 * Returns 1 if true, 0 if false, and -1 in case or error
3162 */
3163int
3164xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003165 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003166 if (reader == NULL)
3167 return(-1);
3168 if (reader->node == NULL)
3169 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003170 if (reader->curnode != NULL)
3171 node = reader->curnode;
3172 else
3173 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003174
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003175 if ((node->type == XML_ELEMENT_NODE) &&
3176 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003177 return(1);
3178 /* TODO: handle the xmlDecl */
3179 return(0);
3180}
3181
3182/**
3183 * xmlTextReaderHasValue:
3184 * @reader: the xmlTextReaderPtr used
3185 *
3186 * Whether the node can have a text value.
3187 *
3188 * Returns 1 if true, 0 if false, and -1 in case or error
3189 */
3190int
3191xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003192 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003193 if (reader == NULL)
3194 return(-1);
3195 if (reader->node == NULL)
3196 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003197 if (reader->curnode != NULL)
3198 node = reader->curnode;
3199 else
3200 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003201
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003202 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003203 case XML_ATTRIBUTE_NODE:
3204 case XML_TEXT_NODE:
3205 case XML_CDATA_SECTION_NODE:
3206 case XML_PI_NODE:
3207 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003208 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003209 return(1);
3210 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003211 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003212 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003213 return(0);
3214}
3215
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003216/**
3217 * xmlTextReaderValue:
3218 * @reader: the xmlTextReaderPtr used
3219 *
3220 * Provides the text value of the node if present
3221 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003222 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003223 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003224 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003225xmlChar *
3226xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003227 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003228 if (reader == NULL)
3229 return(NULL);
3230 if (reader->node == NULL)
3231 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003232 if (reader->curnode != NULL)
3233 node = reader->curnode;
3234 else
3235 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003236
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003237 switch (node->type) {
3238 case XML_NAMESPACE_DECL:
3239 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003240 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003241 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003242
3243 if (attr->parent != NULL)
3244 return (xmlNodeListGetString
3245 (attr->parent->doc, attr->children, 1));
3246 else
3247 return (xmlNodeListGetString(NULL, attr->children, 1));
3248 break;
3249 }
3250 case XML_TEXT_NODE:
3251 case XML_CDATA_SECTION_NODE:
3252 case XML_PI_NODE:
3253 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003254 if (node->content != NULL)
3255 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003256 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003257 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003258 }
3259 return(NULL);
3260}
3261
3262/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003263 * xmlTextReaderConstValue:
3264 * @reader: the xmlTextReaderPtr used
3265 *
3266 * Provides the text value of the node if present
3267 *
3268 * Returns the string or NULL if not available. The result will be
3269 * deallocated on the next Read() operation.
3270 */
3271const xmlChar *
3272xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3273 xmlNodePtr node;
3274 if (reader == NULL)
3275 return(NULL);
3276 if (reader->node == NULL)
3277 return(NULL);
3278 if (reader->curnode != NULL)
3279 node = reader->curnode;
3280 else
3281 node = reader->node;
3282
3283 switch (node->type) {
3284 case XML_NAMESPACE_DECL:
3285 return(((xmlNsPtr) node)->href);
3286 case XML_ATTRIBUTE_NODE:{
3287 xmlAttrPtr attr = (xmlAttrPtr) node;
3288
3289 if ((attr->children != NULL) &&
3290 (attr->children->type == XML_TEXT_NODE) &&
3291 (attr->children->next == NULL))
3292 return(attr->children->content);
3293 else {
3294 reader->buffer->use = 0;
3295 xmlNodeBufGetContent(reader->buffer, node);
3296 return(reader->buffer->content);
3297 }
3298 break;
3299 }
3300 case XML_TEXT_NODE:
3301 case XML_CDATA_SECTION_NODE:
3302 case XML_PI_NODE:
3303 case XML_COMMENT_NODE:
3304 return(node->content);
3305 default:
3306 break;
3307 }
3308 return(NULL);
3309}
3310
3311/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003312 * xmlTextReaderIsDefault:
3313 * @reader: the xmlTextReaderPtr used
3314 *
3315 * Whether an Attribute node was generated from the default value
3316 * defined in the DTD or schema.
3317 *
3318 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3319 */
3320int
3321xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3322 if (reader == NULL)
3323 return(-1);
3324 return(0);
3325}
3326
3327/**
3328 * xmlTextReaderQuoteChar:
3329 * @reader: the xmlTextReaderPtr used
3330 *
3331 * The quotation mark character used to enclose the value of an attribute.
3332 *
3333 * Returns " or ' and -1 in case of error
3334 */
3335int
3336xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3337 if (reader == NULL)
3338 return(-1);
3339 /* TODO maybe lookup the attribute value for " first */
3340 return((int) '"');
3341}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003342
3343/**
3344 * xmlTextReaderXmlLang:
3345 * @reader: the xmlTextReaderPtr used
3346 *
3347 * The xml:lang scope within which the node resides.
3348 *
3349 * Returns the xml:lang value or NULL if none exists.
3350 */
3351xmlChar *
3352xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3353 if (reader == NULL)
3354 return(NULL);
3355 if (reader->node == NULL)
3356 return(NULL);
3357 return(xmlNodeGetLang(reader->node));
3358}
3359
Daniel Veillard67df8092002-12-16 22:04:11 +00003360/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003361 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003362 * @reader: the xmlTextReaderPtr used
3363 *
3364 * The xml:lang scope within which the node resides.
3365 *
3366 * Returns the xml:lang value or NULL if none exists.
3367 */
3368const xmlChar *
3369xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3370 xmlChar *tmp;
3371 const xmlChar *ret;
3372
3373 if (reader == NULL)
3374 return(NULL);
3375 if (reader->node == NULL)
3376 return(NULL);
3377 tmp = xmlNodeGetLang(reader->node);
3378 if (tmp == NULL)
3379 return(NULL);
3380 ret = CONSTSTR(tmp);
3381 xmlFree(tmp);
3382 return(ret);
3383}
3384
3385/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003386 * xmlTextReaderConstString:
3387 * @reader: the xmlTextReaderPtr used
3388 * @str: the string to intern.
3389 *
3390 * Get an interned string from the reader, allows for example to
3391 * speedup string name comparisons
3392 *
3393 * Returns an interned copy of the string or NULL in case of error. The
3394 * string will be deallocated with the reader.
3395 */
3396const xmlChar *
3397xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3398 if (reader == NULL)
3399 return(NULL);
3400 return(CONSTSTR(str));
3401}
3402
3403/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003404 * xmlTextReaderNormalization:
3405 * @reader: the xmlTextReaderPtr used
3406 *
3407 * The value indicating whether to normalize white space and attribute values.
3408 * Since attribute value and end of line normalizations are a MUST in the XML
3409 * specification only the value true is accepted. The broken bahaviour of
3410 * accepting out of range character entities like &#0; is of course not
3411 * supported either.
3412 *
3413 * Returns 1 or -1 in case of error.
3414 */
3415int
3416xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3417 if (reader == NULL)
3418 return(-1);
3419 return(1);
3420}
3421
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003422/************************************************************************
3423 * *
3424 * Extensions to the base APIs *
3425 * *
3426 ************************************************************************/
3427
3428/**
3429 * xmlTextReaderSetParserProp:
3430 * @reader: the xmlTextReaderPtr used
3431 * @prop: the xmlParserProperties to set
3432 * @value: usually 0 or 1 to (de)activate it
3433 *
3434 * Change the parser processing behaviour by changing some of its internal
3435 * properties. Note that some properties can only be changed before any
3436 * read has been done.
3437 *
3438 * Returns 0 if the call was successful, or -1 in case of error
3439 */
3440int
3441xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3442 xmlParserProperties p = (xmlParserProperties) prop;
3443 xmlParserCtxtPtr ctxt;
3444
3445 if ((reader == NULL) || (reader->ctxt == NULL))
3446 return(-1);
3447 ctxt = reader->ctxt;
3448
3449 switch (p) {
3450 case XML_PARSER_LOADDTD:
3451 if (value != 0) {
3452 if (ctxt->loadsubset == 0) {
3453 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3454 return(-1);
3455 ctxt->loadsubset = XML_DETECT_IDS;
3456 }
3457 } else {
3458 ctxt->loadsubset = 0;
3459 }
3460 return(0);
3461 case XML_PARSER_DEFAULTATTRS:
3462 if (value != 0) {
3463 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3464 } else {
3465 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3466 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3467 }
3468 return(0);
3469 case XML_PARSER_VALIDATE:
3470 if (value != 0) {
3471 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003472 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003473 } else {
3474 ctxt->validate = 0;
3475 }
3476 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003477 case XML_PARSER_SUBST_ENTITIES:
3478 if (value != 0) {
3479 ctxt->replaceEntities = 1;
3480 } else {
3481 ctxt->replaceEntities = 0;
3482 }
3483 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003484 }
3485 return(-1);
3486}
3487
3488/**
3489 * xmlTextReaderGetParserProp:
3490 * @reader: the xmlTextReaderPtr used
3491 * @prop: the xmlParserProperties to get
3492 *
3493 * Read the parser internal property.
3494 *
3495 * Returns the value, usually 0 or 1, or -1 in case of error.
3496 */
3497int
3498xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3499 xmlParserProperties p = (xmlParserProperties) prop;
3500 xmlParserCtxtPtr ctxt;
3501
3502 if ((reader == NULL) || (reader->ctxt == NULL))
3503 return(-1);
3504 ctxt = reader->ctxt;
3505
3506 switch (p) {
3507 case XML_PARSER_LOADDTD:
3508 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3509 return(1);
3510 return(0);
3511 case XML_PARSER_DEFAULTATTRS:
3512 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3513 return(1);
3514 return(0);
3515 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003516 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003517 case XML_PARSER_SUBST_ENTITIES:
3518 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003519 }
3520 return(-1);
3521}
3522
Daniel Veillarde18fc182002-12-28 22:56:33 +00003523/**
3524 * xmlTextReaderCurrentNode:
3525 * @reader: the xmlTextReaderPtr used
3526 *
3527 * Hacking interface allowing to get the xmlNodePtr correponding to the
3528 * current node being accessed by the xmlTextReader. This is dangerous
3529 * because the underlying node may be destroyed on the next Reads.
3530 *
3531 * Returns the xmlNodePtr or NULL in case of error.
3532 */
3533xmlNodePtr
3534xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3535 if (reader == NULL)
3536 return(NULL);
3537
3538 if (reader->curnode != NULL)
3539 return(reader->curnode);
3540 return(reader->node);
3541}
3542
3543/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003544 * xmlTextReaderPreserve:
3545 * @reader: the xmlTextReaderPtr used
3546 *
3547 *
3548 * current node being accessed by the xmlTextReader. This is dangerous
3549 * because the underlying node may be destroyed on the next Reads.
3550 *
3551 * Returns the xmlNodePtr or NULL in case of error.
3552 */
3553xmlNodePtr
3554xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3555 xmlNodePtr cur, parent;
3556
3557 if (reader == NULL)
3558 return(NULL);
3559
3560 if (reader->curnode != NULL)
3561 cur = reader->curnode;
3562 else
3563 cur = reader->node;
3564 if (cur == NULL)
3565 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003566
3567 if (cur->type != XML_DOCUMENT_NODE) {
3568 cur->extra |= NODE_IS_PRESERVED;
3569 cur->extra |= NODE_IS_SPRESERVED;
3570 }
3571 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003572
3573 parent = cur->parent;;
3574 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003575 if (parent->type == XML_ELEMENT_NODE)
3576 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003577 parent = parent->parent;
3578 }
3579 return(cur);
3580}
3581
Daniel Veillard1e906612003-12-05 14:57:46 +00003582#ifdef LIBXML_PATTERN_ENABLED
3583/**
3584 * xmlTextReaderPreservePattern:
3585 * @reader: the xmlTextReaderPtr used
3586 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003587 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003588 *
3589 * This tells the XML Reader to preserve all nodes matched by the
3590 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3591 * keep an handle on the resulting document once parsing has finished
3592 *
3593 * Returns a positive number in case of success and -1 in case of error
3594 */
3595int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003596xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3597 const xmlChar **namespaces)
3598{
Daniel Veillard1e906612003-12-05 14:57:46 +00003599 xmlPatternPtr comp;
3600
3601 if ((reader == NULL) || (pattern == NULL))
3602 return(-1);
3603
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003604 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003605 if (comp == NULL)
3606 return(-1);
3607
3608 if (reader->patternMax <= 0) {
3609 reader->patternMax = 4;
3610 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3611 sizeof(reader->patternTab[0]));
3612 if (reader->patternTab == NULL) {
3613 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3614 return (-1);
3615 }
3616 }
3617 if (reader->patternNr >= reader->patternMax) {
3618 xmlPatternPtr *tmp;
3619 reader->patternMax *= 2;
3620 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3621 reader->patternMax *
3622 sizeof(reader->patternTab[0]));
3623 if (tmp == NULL) {
3624 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3625 reader->patternMax /= 2;
3626 return (-1);
3627 }
3628 reader->patternTab = tmp;
3629 }
3630 reader->patternTab[reader->patternNr] = comp;
3631 return(reader->patternNr++);
3632}
3633#endif
3634
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003635/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003636 * xmlTextReaderCurrentDoc:
3637 * @reader: the xmlTextReaderPtr used
3638 *
3639 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003640 * current document being accessed by the xmlTextReader.
3641 * NOTE: as a result of this call, the reader will not destroy the
3642 * associated XML document and calling xmlFreeDoc() on the result
3643 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003644 *
3645 * Returns the xmlDocPtr or NULL in case of error.
3646 */
3647xmlDocPtr
3648xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003649 if (reader == NULL)
3650 return(NULL);
3651 if (reader->doc != NULL)
3652 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003653 if ((reader == NULL) || (reader->ctxt == NULL) ||
3654 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003655 return(NULL);
3656
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003657 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003658 return(reader->ctxt->myDoc);
3659}
3660
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003661#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003662/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003663 * xmlTextReaderRelaxNGSetSchema:
3664 * @reader: the xmlTextReaderPtr used
3665 * @schema: a precompiled RelaxNG schema
3666 *
3667 * Use RelaxNG to validate the document as it is processed.
3668 * Activation is only possible before the first Read().
3669 * if @schema is NULL, then RelaxNG validation is desactivated.
3670 @ The @schema should not be freed until the reader is deallocated
3671 * or its use has been deactivated.
3672 *
3673 * Returns 0 in case the RelaxNG validation could be (des)activated and
3674 * -1 in case of error.
3675 */
3676int
3677xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3678 if (schema == NULL) {
3679 if (reader->rngSchemas != NULL) {
3680 xmlRelaxNGFree(reader->rngSchemas);
3681 reader->rngSchemas = NULL;
3682 }
3683 if (reader->rngValidCtxt != NULL) {
3684 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3685 reader->rngValidCtxt = NULL;
3686 }
3687 return(0);
3688 }
3689 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3690 return(-1);
3691 if (reader->rngSchemas != NULL) {
3692 xmlRelaxNGFree(reader->rngSchemas);
3693 reader->rngSchemas = NULL;
3694 }
3695 if (reader->rngValidCtxt != NULL) {
3696 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3697 reader->rngValidCtxt = NULL;
3698 }
3699 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3700 if (reader->rngValidCtxt == NULL)
3701 return(-1);
3702 if (reader->errorFunc != NULL) {
3703 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3704 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3705 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3706 reader->errorFuncArg);
3707 }
3708 reader->rngValidErrors = 0;
3709 reader->rngFullNode = NULL;
3710 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3711 return(0);
3712}
3713
3714/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003715 * xmlTextReaderRelaxNGValidate:
3716 * @reader: the xmlTextReaderPtr used
3717 * @rng: the path to a RelaxNG schema or NULL
3718 *
3719 * Use RelaxNG to validate the document as it is processed.
3720 * Activation is only possible before the first Read().
3721 * if @rng is NULL, then RelaxNG validation is desactivated.
3722 *
3723 * Returns 0 in case the RelaxNG validation could be (des)activated and
3724 * -1 in case of error.
3725 */
3726int
3727xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3728 xmlRelaxNGParserCtxtPtr ctxt;
3729
3730 if (reader == NULL)
3731 return(-1);
3732
3733 if (rng == NULL) {
3734 if (reader->rngSchemas != NULL) {
3735 xmlRelaxNGFree(reader->rngSchemas);
3736 reader->rngSchemas = NULL;
3737 }
3738 if (reader->rngValidCtxt != NULL) {
3739 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3740 reader->rngValidCtxt = NULL;
3741 }
3742 return(0);
3743 }
3744 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3745 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003746 if (reader->rngSchemas != NULL) {
3747 xmlRelaxNGFree(reader->rngSchemas);
3748 reader->rngSchemas = NULL;
3749 }
3750 if (reader->rngValidCtxt != NULL) {
3751 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3752 reader->rngValidCtxt = NULL;
3753 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003754 ctxt = xmlRelaxNGNewParserCtxt(rng);
3755 if (reader->errorFunc != NULL) {
3756 xmlRelaxNGSetParserErrors(ctxt,
3757 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3758 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3759 reader->errorFuncArg);
3760 }
3761 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3762 xmlRelaxNGFreeParserCtxt(ctxt);
3763 if (reader->rngSchemas == NULL)
3764 return(-1);
3765 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3766 if (reader->rngValidCtxt == NULL)
3767 return(-1);
3768 if (reader->errorFunc != NULL) {
3769 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3770 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3771 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3772 reader->errorFuncArg);
3773 }
3774 reader->rngValidErrors = 0;
3775 reader->rngFullNode = NULL;
3776 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3777 return(0);
3778}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003779#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003780
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003781/************************************************************************
3782 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003783 * Error Handling Extensions *
3784 * *
3785 ************************************************************************/
3786
3787/* helper to build a xmlMalloc'ed string from a format and va_list */
3788static char *
3789xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3790 int size;
3791 int chars;
3792 char *larger;
3793 char *str;
3794
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003795 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003796 if (str == NULL) {
3797 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3798 return NULL;
3799 }
3800
3801 size = 150;
3802
3803 while (1) {
3804 chars = vsnprintf(str, size, msg, ap);
3805 if ((chars > -1) && (chars < size))
3806 break;
3807 if (chars > -1)
3808 size += chars + 1;
3809 else
3810 size += 100;
3811 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3812 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3813 xmlFree(str);
3814 return NULL;
3815 }
3816 str = larger;
3817 }
3818
3819 return str;
3820}
3821
Daniel Veillard417be3a2003-01-20 21:26:34 +00003822/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003823 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003824 * @locator: the xmlTextReaderLocatorPtr used
3825 *
3826 * Obtain the line number for the given locator.
3827 *
3828 * Returns the line number or -1 in case of error.
3829 */
3830int
3831xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3832 /* we know that locator is a xmlParserCtxtPtr */
3833 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3834 int ret = -1;
3835
3836 if (ctx->node != NULL) {
3837 ret = xmlGetLineNo(ctx->node);
3838 }
3839 else {
3840 /* inspired from error.c */
3841 xmlParserInputPtr input;
3842 input = ctx->input;
3843 if ((input->filename == NULL) && (ctx->inputNr > 1))
3844 input = ctx->inputTab[ctx->inputNr - 2];
3845 if (input != NULL) {
3846 ret = input->line;
3847 }
3848 else {
3849 ret = -1;
3850 }
3851 }
3852
3853 return ret;
3854}
3855
3856/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003857 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003858 * @locator: the xmlTextReaderLocatorPtr used
3859 *
3860 * Obtain the base URI for the given locator.
3861 *
3862 * Returns the base URI or NULL in case of error.
3863 */
3864xmlChar *
3865xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3866 /* we know that locator is a xmlParserCtxtPtr */
3867 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3868 xmlChar *ret = NULL;
3869
3870 if (ctx->node != NULL) {
3871 ret = xmlNodeGetBase(NULL,ctx->node);
3872 }
3873 else {
3874 /* inspired from error.c */
3875 xmlParserInputPtr input;
3876 input = ctx->input;
3877 if ((input->filename == NULL) && (ctx->inputNr > 1))
3878 input = ctx->inputTab[ctx->inputNr - 2];
3879 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003880 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003881 }
3882 else {
3883 ret = NULL;
3884 }
3885 }
3886
3887 return ret;
3888}
3889
Daniel Veillard26f70262003-01-16 22:45:08 +00003890static void
William M. Brack899e64a2003-09-26 18:03:42 +00003891xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003892 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3893 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3894
3895 if (str != NULL) {
3896 reader->errorFunc(reader->errorFuncArg,
3897 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003898 severity,
3899 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003900 xmlFree(str);
3901 }
3902}
3903
3904static void
William M. Brack93d004f2004-02-03 00:14:10 +00003905xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3906 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3907 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3908
3909 if (error && reader->sErrorFunc) {
3910 reader->sErrorFunc(reader->errorFuncArg,
3911 (xmlErrorPtr) error);
3912 }
3913}
3914
3915static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003916xmlTextReaderError(void *ctxt, const char *msg, ...) {
3917 va_list ap;
3918
3919 va_start(ap,msg);
3920 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003921 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003922 xmlTextReaderBuildMessage(msg,ap));
3923 va_end(ap);
3924
3925}
3926
3927static void
3928xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3929 va_list ap;
3930
3931 va_start(ap,msg);
3932 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003933 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003934 xmlTextReaderBuildMessage(msg,ap));
3935 va_end(ap);
3936}
3937
3938static void
3939xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3940 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003941 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003942
Daniel Veillard417be3a2003-01-20 21:26:34 +00003943 if ((len > 1) && (msg[len - 2] != ':')) {
3944 /*
3945 * some callbacks only report locator information:
3946 * skip them (mimicking behaviour in error.c)
3947 */
3948 va_start(ap,msg);
3949 xmlTextReaderGenericError(ctxt,
3950 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3951 xmlTextReaderBuildMessage(msg,ap));
3952 va_end(ap);
3953 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003954}
3955
3956static void
3957xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3958 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003959 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003960
Daniel Veillard417be3a2003-01-20 21:26:34 +00003961 if ((len != 0) && (msg[len - 1] != ':')) {
3962 /*
3963 * some callbacks only report locator information:
3964 * skip them (mimicking behaviour in error.c)
3965 */
3966 va_start(ap,msg);
3967 xmlTextReaderGenericError(ctxt,
3968 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3969 xmlTextReaderBuildMessage(msg,ap));
3970 va_end(ap);
3971 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003972}
3973
3974/**
3975 * xmlTextReaderSetErrorHandler:
3976 * @reader: the xmlTextReaderPtr used
3977 * @f: the callback function to call on error and warnings
3978 * @arg: a user argument to pass to the callback function
3979 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003980 * Register a callback function that will be called on error and warnings.
3981 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003982 * If @f is NULL, the default error and warning handlers are restored.
3983 */
3984void
3985xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3986 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003987 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003988 if (f != NULL) {
3989 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003990 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003991 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3992 reader->ctxt->sax->warning = xmlTextReaderWarning;
3993 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3994 reader->errorFunc = f;
3995 reader->errorFuncArg = arg;
3996 }
3997 else {
3998 /* restore defaults */
3999 reader->ctxt->sax->error = xmlParserError;
4000 reader->ctxt->vctxt.error = xmlParserValidityError;
4001 reader->ctxt->sax->warning = xmlParserWarning;
4002 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4003 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004004 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004005 reader->errorFuncArg = NULL;
4006 }
4007}
4008
Daniel Veillard417be3a2003-01-20 21:26:34 +00004009/**
William M. Brack93d004f2004-02-03 00:14:10 +00004010* xmlTextReaderSetStructuredErrorHandler:
4011 * @reader: the xmlTextReaderPtr used
4012 * @f: the callback function to call on error and warnings
4013 * @arg: a user argument to pass to the callback function
4014 *
4015 * Register a callback function that will be called on error and warnings.
4016 *
4017 * If @f is NULL, the default error and warning handlers are restored.
4018 */
4019void
4020xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4021 xmlStructuredErrorFunc f,
4022 void *arg) {
4023 if (f != NULL) {
4024 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4025 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4026 reader->ctxt->sax->warning = xmlTextReaderWarning;
4027 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4028 reader->sErrorFunc = f;
4029 reader->errorFunc = NULL;
4030 reader->errorFuncArg = arg;
4031 }
4032 else {
4033 /* restore defaults */
4034 reader->ctxt->sax->error = xmlParserError;
4035 reader->ctxt->sax->serror = NULL;
4036 reader->ctxt->vctxt.error = xmlParserValidityError;
4037 reader->ctxt->sax->warning = xmlParserWarning;
4038 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4039 reader->errorFunc = NULL;
4040 reader->sErrorFunc = NULL;
4041 reader->errorFuncArg = NULL;
4042 }
4043}
4044
4045/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004046 * xmlTextReaderIsValid:
4047 * @reader: the xmlTextReaderPtr used
4048 *
4049 * Retrieve the validity status from the parser context
4050 *
4051 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4052 */
4053int
4054xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004055 if (reader == NULL) return(-1);
4056#ifdef LIBXML_SCHEMAS_ENABLED
4057 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4058 return(reader->rngValidErrors == 0);
4059#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004060 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004061 return(reader->ctxt->valid);
4062 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004063}
4064
4065/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004066 * xmlTextReaderGetErrorHandler:
4067 * @reader: the xmlTextReaderPtr used
4068 * @f: the callback function or NULL is no callback has been registered
4069 * @arg: a user argument
4070 *
4071 * Retrieve the error callback function and user argument.
4072 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004073void
4074xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4075 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004076 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004077 *f = reader->errorFunc;
4078 *arg = reader->errorFuncArg;
4079}
4080
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004081
4082/************************************************************************
4083 * *
4084 * New set (2.6.0) of simpler and more flexible APIs *
4085 * *
4086 ************************************************************************/
4087
4088/**
4089 * xmlTextReaderSetup:
4090 * @reader: an XML reader
4091 * @URL: the base URL to use for the document
4092 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004093 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004094 * @reuse: keep the context for reuse
4095 *
4096 * Setup an XML reader with new options
4097 *
4098 * Returns 0 in case of success and -1 in case of error.
4099 */
4100static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004101xmlTextReaderSetup(xmlTextReaderPtr reader,
4102 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004103 const char *encoding, int options)
4104{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004105 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004106 return (-1);
4107
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004108 reader->doc = NULL;
4109 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004110 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004111 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004112 if ((input != NULL) && (reader->input != NULL) &&
4113 (reader->allocs & XML_TEXTREADER_INPUT)) {
4114 xmlFreeParserInputBuffer(reader->input);
4115 reader->input = NULL;
4116 reader->allocs -= XML_TEXTREADER_INPUT;
4117 }
4118 if (input != NULL) {
4119 reader->input = input;
4120 reader->allocs |= XML_TEXTREADER_INPUT;
4121 }
4122 if (reader->buffer == NULL)
4123 reader->buffer = xmlBufferCreateSize(100);
4124 if (reader->buffer == NULL) {
4125 xmlGenericError(xmlGenericErrorContext,
4126 "xmlTextReaderSetup : malloc failed\n");
4127 return (-1);
4128 }
4129 if (reader->sax == NULL)
4130 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4131 if (reader->sax == NULL) {
4132 xmlGenericError(xmlGenericErrorContext,
4133 "xmlTextReaderSetup : malloc failed\n");
4134 return (-1);
4135 }
4136 xmlSAXVersion(reader->sax, 2);
4137 reader->startElement = reader->sax->startElement;
4138 reader->sax->startElement = xmlTextReaderStartElement;
4139 reader->endElement = reader->sax->endElement;
4140 reader->sax->endElement = xmlTextReaderEndElement;
4141#ifdef LIBXML_SAX1_ENABLED
4142 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4143#endif /* LIBXML_SAX1_ENABLED */
4144 reader->startElementNs = reader->sax->startElementNs;
4145 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4146 reader->endElementNs = reader->sax->endElementNs;
4147 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4148#ifdef LIBXML_SAX1_ENABLED
4149 } else {
4150 reader->startElementNs = NULL;
4151 reader->endElementNs = NULL;
4152 }
4153#endif /* LIBXML_SAX1_ENABLED */
4154 reader->characters = reader->sax->characters;
4155 reader->sax->characters = xmlTextReaderCharacters;
4156 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4157 reader->cdataBlock = reader->sax->cdataBlock;
4158 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4159
4160 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4161 reader->node = NULL;
4162 reader->curnode = NULL;
4163 if (input != NULL) {
4164 if (reader->input->buffer->use < 4) {
4165 xmlParserInputBufferRead(input, 4);
4166 }
4167 if (reader->ctxt == NULL) {
4168 if (reader->input->buffer->use >= 4) {
4169 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4170 (const char *) reader->input->buffer->content, 4, URL);
4171 reader->base = 0;
4172 reader->cur = 4;
4173 } else {
4174 reader->ctxt =
4175 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4176 reader->base = 0;
4177 reader->cur = 0;
4178 }
4179 } else {
4180 xmlParserInputPtr inputStream;
4181 xmlParserInputBufferPtr buf;
4182 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4183
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004184 xmlCtxtReset(reader->ctxt);
4185 buf = xmlAllocParserInputBuffer(enc);
4186 if (buf == NULL) return(-1);
4187 inputStream = xmlNewInputStream(reader->ctxt);
4188 if (inputStream == NULL) {
4189 xmlFreeParserInputBuffer(buf);
4190 return(-1);
4191 }
4192
4193 if (URL == NULL)
4194 inputStream->filename = NULL;
4195 else
4196 inputStream->filename = (char *)
4197 xmlCanonicPath((const xmlChar *) URL);
4198 inputStream->buf = buf;
4199 inputStream->base = inputStream->buf->buffer->content;
4200 inputStream->cur = inputStream->buf->buffer->content;
4201 inputStream->end =
4202 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4203
4204 inputPush(reader->ctxt, inputStream);
4205 reader->cur = 0;
4206 }
4207 if (reader->ctxt == NULL) {
4208 xmlGenericError(xmlGenericErrorContext,
4209 "xmlTextReaderSetup : malloc failed\n");
4210 return (-1);
4211 }
4212 }
4213 if (reader->dict != NULL) {
4214 if (reader->ctxt->dict != NULL) {
4215 if (reader->dict != reader->ctxt->dict) {
4216 xmlDictFree(reader->dict);
4217 reader->dict = reader->ctxt->dict;
4218 }
4219 } else {
4220 reader->ctxt->dict = reader->dict;
4221 }
4222 } else {
4223 if (reader->ctxt->dict == NULL)
4224 reader->ctxt->dict = xmlDictCreate();
4225 reader->dict = reader->ctxt->dict;
4226 }
4227 reader->ctxt->_private = reader;
4228 reader->ctxt->linenumbers = 1;
4229 reader->ctxt->dictNames = 1;
4230 /*
4231 * use the parser dictionnary to allocate all elements and attributes names
4232 */
4233 reader->ctxt->docdict = 1;
4234
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004235#ifdef LIBXML_XINCLUDE_ENABLED
4236 if (reader->xincctxt != NULL) {
4237 xmlXIncludeFreeContext(reader->xincctxt);
4238 reader->xincctxt = NULL;
4239 }
4240 if (options & XML_PARSE_XINCLUDE) {
4241 reader->xinclude = 1;
4242 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4243 options -= XML_PARSE_XINCLUDE;
4244 } else
4245 reader->xinclude = 0;
4246 reader->in_xinclude = 0;
4247#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004248#ifdef LIBXML_PATTERN_ENABLED
4249 if (reader->patternTab == NULL) {
4250 reader->patternNr = 0;
4251 reader->patternMax = 0;
4252 }
4253 while (reader->patternNr > 0) {
4254 reader->patternNr--;
4255 if (reader->patternTab[reader->patternNr] != NULL) {
4256 xmlFreePattern(reader->patternTab[reader->patternNr]);
4257 reader->patternTab[reader->patternNr] = NULL;
4258 }
4259 }
4260#endif
4261
Daniel Veillardc36965d2003-12-02 10:28:48 +00004262 if (options & XML_PARSE_DTDVALID)
4263 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4264
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004265 xmlCtxtUseOptions(reader->ctxt, options);
4266 if (encoding != NULL) {
4267 xmlCharEncodingHandlerPtr hdlr;
4268
4269 hdlr = xmlFindCharEncodingHandler(encoding);
4270 if (hdlr != NULL)
4271 xmlSwitchToEncoding(reader->ctxt, hdlr);
4272 }
4273 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4274 (reader->ctxt->input->filename == NULL))
4275 reader->ctxt->input->filename = (char *)
4276 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004277
4278 reader->doc = NULL;
4279
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004280 return (0);
4281}
4282
4283/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004284 * xmlReaderWalker:
4285 * @doc: a preparsed document
4286 *
4287 * Create an xmltextReader for a preparsed document.
4288 *
4289 * Returns the new reader or NULL in case of error.
4290 */
4291xmlTextReaderPtr
4292xmlReaderWalker(xmlDocPtr doc)
4293{
4294 xmlTextReaderPtr ret;
4295
4296 if (doc == NULL)
4297 return(NULL);
4298
4299 ret = xmlMalloc(sizeof(xmlTextReader));
4300 if (ret == NULL) {
4301 xmlGenericError(xmlGenericErrorContext,
4302 "xmlNewTextReader : malloc failed\n");
4303 return(NULL);
4304 }
4305 memset(ret, 0, sizeof(xmlTextReader));
4306 ret->entNr = 0;
4307 ret->input = NULL;
4308 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4309 ret->node = NULL;
4310 ret->curnode = NULL;
4311 ret->base = 0;
4312 ret->cur = 0;
4313 ret->allocs = XML_TEXTREADER_CTXT;
4314 ret->doc = doc;
4315 ret->state = XML_TEXTREADER_START;
4316 ret->dict = xmlDictCreate();
4317 return(ret);
4318}
4319
4320/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004321 * xmlReaderForDoc:
4322 * @cur: a pointer to a zero terminated string
4323 * @URL: the base URL to use for the document
4324 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004325 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004326 *
4327 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004328 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004329 *
4330 * Returns the new reader or NULL in case of error.
4331 */
4332xmlTextReaderPtr
4333xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4334 int options)
4335{
4336 int len;
4337
4338 if (cur == NULL)
4339 return (NULL);
4340 len = xmlStrlen(cur);
4341
4342 return (xmlReaderForMemory
4343 ((const char *) cur, len, URL, encoding, options));
4344}
4345
4346/**
4347 * xmlReaderForFile:
4348 * @filename: a file or URL
4349 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004350 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004351 *
4352 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004353 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004354 *
4355 * Returns the new reader or NULL in case of error.
4356 */
4357xmlTextReaderPtr
4358xmlReaderForFile(const char *filename, const char *encoding, int options)
4359{
4360 xmlTextReaderPtr reader;
4361
4362 reader = xmlNewTextReaderFilename(filename);
4363 if (reader == NULL)
4364 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004365 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004366 return (reader);
4367}
4368
4369/**
4370 * xmlReaderForMemory:
4371 * @buffer: a pointer to a char array
4372 * @size: the size of the array
4373 * @URL: the base URL to use for the document
4374 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004375 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004376 *
4377 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004378 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004379 *
4380 * Returns the new reader or NULL in case of error.
4381 */
4382xmlTextReaderPtr
4383xmlReaderForMemory(const char *buffer, int size, const char *URL,
4384 const char *encoding, int options)
4385{
4386 xmlTextReaderPtr reader;
4387 xmlParserInputBufferPtr buf;
4388
Daniel Veillard21924522004-02-19 16:37:07 +00004389 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004390 XML_CHAR_ENCODING_NONE);
4391 if (buf == NULL) {
4392 return (NULL);
4393 }
4394 reader = xmlNewTextReader(buf, URL);
4395 if (reader == NULL) {
4396 xmlFreeParserInputBuffer(buf);
4397 return (NULL);
4398 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004399 reader->allocs |= XML_TEXTREADER_INPUT;
4400 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004401 return (reader);
4402}
4403
4404/**
4405 * xmlReaderForFd:
4406 * @fd: an open file descriptor
4407 * @URL: the base URL to use for the document
4408 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004409 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004410 *
4411 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004412 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004413 * NOTE that the file descriptor will not be closed when the
4414 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004415 *
4416 * Returns the new reader or NULL in case of error.
4417 */
4418xmlTextReaderPtr
4419xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4420{
4421 xmlTextReaderPtr reader;
4422 xmlParserInputBufferPtr input;
4423
4424 if (fd < 0)
4425 return (NULL);
4426
4427 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4428 if (input == NULL)
4429 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004430 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004431 reader = xmlNewTextReader(input, URL);
4432 if (reader == NULL) {
4433 xmlFreeParserInputBuffer(input);
4434 return (NULL);
4435 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004436 reader->allocs |= XML_TEXTREADER_INPUT;
4437 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004438 return (reader);
4439}
4440
4441/**
4442 * xmlReaderForIO:
4443 * @ioread: an I/O read function
4444 * @ioclose: an I/O close function
4445 * @ioctx: an I/O handler
4446 * @URL: the base URL to use for the document
4447 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004448 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004449 *
4450 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004451 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004452 *
4453 * Returns the new reader or NULL in case of error.
4454 */
4455xmlTextReaderPtr
4456xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4457 void *ioctx, const char *URL, const char *encoding,
4458 int options)
4459{
4460 xmlTextReaderPtr reader;
4461 xmlParserInputBufferPtr input;
4462
4463 if (ioread == NULL)
4464 return (NULL);
4465
4466 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4467 XML_CHAR_ENCODING_NONE);
4468 if (input == NULL)
4469 return (NULL);
4470 reader = xmlNewTextReader(input, URL);
4471 if (reader == NULL) {
4472 xmlFreeParserInputBuffer(input);
4473 return (NULL);
4474 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004475 reader->allocs |= XML_TEXTREADER_INPUT;
4476 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004477 return (reader);
4478}
4479
4480/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004481 * xmlReaderNewWalker:
4482 * @reader: an XML reader
4483 * @doc: a preparsed document
4484 *
4485 * Setup an xmltextReader to parse a preparsed XML document.
4486 * This reuses the existing @reader xmlTextReader.
4487 *
4488 * Returns 0 in case of success and -1 in case of error
4489 */
4490int
4491xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4492{
4493 if (doc == NULL)
4494 return (-1);
4495 if (reader == NULL)
4496 return (-1);
4497
4498 if (reader->ctxt != NULL) {
4499 xmlCtxtReset(reader->ctxt);
4500 }
4501
4502 reader->entNr = 0;
4503 reader->input = NULL;
4504 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4505 reader->node = NULL;
4506 reader->curnode = NULL;
4507 reader->base = 0;
4508 reader->cur = 0;
4509 reader->allocs = XML_TEXTREADER_CTXT;
4510 reader->doc = doc;
4511 reader->state = XML_TEXTREADER_START;
4512 if (reader->dict == NULL) {
4513 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4514 reader->dict = reader->ctxt->dict;
4515 else
4516 reader->dict = xmlDictCreate();
4517 }
4518 return(0);
4519}
4520
4521/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004522 * xmlReaderNewDoc:
4523 * @reader: an XML reader
4524 * @cur: a pointer to a zero terminated string
4525 * @URL: the base URL to use for the document
4526 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004527 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004528 *
4529 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004530 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004531 * This reuses the existing @reader xmlTextReader.
4532 *
4533 * Returns 0 in case of success and -1 in case of error
4534 */
4535int
4536xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4537 const char *URL, const char *encoding, int options)
4538{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004539
4540 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004541
4542 if (cur == NULL)
4543 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004544 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004545 return (-1);
4546
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004547 len = xmlStrlen(cur);
4548 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4549 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004550}
4551
4552/**
4553 * xmlReaderNewFile:
4554 * @reader: an XML reader
4555 * @filename: a file or URL
4556 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004557 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004558 *
4559 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004560 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004561 * This reuses the existing @reader xmlTextReader.
4562 *
4563 * Returns 0 in case of success and -1 in case of error
4564 */
4565int
4566xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4567 const char *encoding, int options)
4568{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004569 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004570
4571 if (filename == NULL)
4572 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004573 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004574 return (-1);
4575
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004576 input =
4577 xmlParserInputBufferCreateFilename(filename,
4578 XML_CHAR_ENCODING_NONE);
4579 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004580 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004581 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004582}
4583
4584/**
4585 * xmlReaderNewMemory:
4586 * @reader: an XML reader
4587 * @buffer: a pointer to a char array
4588 * @size: the size of the array
4589 * @URL: the base URL to use for the document
4590 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004591 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004592 *
4593 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004594 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004595 * This reuses the existing @reader xmlTextReader.
4596 *
4597 * Returns 0 in case of success and -1 in case of error
4598 */
4599int
4600xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4601 const char *URL, const char *encoding, int options)
4602{
4603 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004604
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004605 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004606 return (-1);
4607 if (buffer == NULL)
4608 return (-1);
4609
Daniel Veillard21924522004-02-19 16:37:07 +00004610 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004611 XML_CHAR_ENCODING_NONE);
4612 if (input == NULL) {
4613 return (-1);
4614 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004615 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004616}
4617
4618/**
4619 * xmlReaderNewFd:
4620 * @reader: an XML reader
4621 * @fd: an open file descriptor
4622 * @URL: the base URL to use for the document
4623 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004624 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004625 *
4626 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004627 * NOTE that the file descriptor will not be closed when the
4628 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004629 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004630 * This reuses the existing @reader xmlTextReader.
4631 *
4632 * Returns 0 in case of success and -1 in case of error
4633 */
4634int
4635xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4636 const char *URL, const char *encoding, int options)
4637{
4638 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004639
4640 if (fd < 0)
4641 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004642 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004643 return (-1);
4644
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004645 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4646 if (input == NULL)
4647 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004648 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004649 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004650}
4651
4652/**
4653 * xmlReaderNewIO:
4654 * @reader: an XML reader
4655 * @ioread: an I/O read function
4656 * @ioclose: an I/O close function
4657 * @ioctx: an I/O handler
4658 * @URL: the base URL to use for the document
4659 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004660 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004661 *
4662 * Setup an xmltextReader to parse an XML document from I/O functions
4663 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004664 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004665 * This reuses the existing @reader xmlTextReader.
4666 *
4667 * Returns 0 in case of success and -1 in case of error
4668 */
4669int
4670xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4671 xmlInputCloseCallback ioclose, void *ioctx,
4672 const char *URL, const char *encoding, int options)
4673{
4674 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004675
4676 if (ioread == NULL)
4677 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004678 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004679 return (-1);
4680
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004681 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4682 XML_CHAR_ENCODING_NONE);
4683 if (input == NULL)
4684 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004685 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004686}
Daniel Veillard26f70262003-01-16 22:45:08 +00004687/************************************************************************
4688 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004689 * Utilities *
4690 * *
4691 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004692#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004693/**
4694 * xmlBase64Decode:
4695 * @in: the input buffer
4696 * @inlen: the size of the input (in), the size read from it (out)
4697 * @to: the output buffer
4698 * @tolen: the size of the output (in), the size written to (out)
4699 *
4700 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004701 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004702 *
4703 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4704 * 2 if there wasn't enough space on the output or -1 in case of error.
4705 */
4706static int
4707xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4708 unsigned char *to, unsigned long *tolen) {
4709 unsigned long incur; /* current index in in[] */
4710 unsigned long inblk; /* last block index in in[] */
4711 unsigned long outcur; /* current index in out[] */
4712 unsigned long inmax; /* size of in[] */
4713 unsigned long outmax; /* size of out[] */
4714 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004715 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004716 int nbintmp; /* number of byte in intmp[] */
4717 int is_ignore; /* cur should be ignored */
4718 int is_end = 0; /* the end of the base64 was found */
4719 int retval = 1;
4720 int i;
4721
4722 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4723 return(-1);
4724
4725 incur = 0;
4726 inblk = 0;
4727 outcur = 0;
4728 inmax = *inlen;
4729 outmax = *tolen;
4730 nbintmp = 0;
4731
4732 while (1) {
4733 if (incur >= inmax)
4734 break;
4735 cur = in[incur++];
4736 is_ignore = 0;
4737 if ((cur >= 'A') && (cur <= 'Z'))
4738 cur = cur - 'A';
4739 else if ((cur >= 'a') && (cur <= 'z'))
4740 cur = cur - 'a' + 26;
4741 else if ((cur >= '0') && (cur <= '9'))
4742 cur = cur - '0' + 52;
4743 else if (cur == '+')
4744 cur = 62;
4745 else if (cur == '/')
4746 cur = 63;
4747 else if (cur == '.')
4748 cur = 0;
4749 else if (cur == '=') /*no op , end of the base64 stream */
4750 is_end = 1;
4751 else {
4752 is_ignore = 1;
4753 if (nbintmp == 0)
4754 inblk = incur;
4755 }
4756
4757 if (!is_ignore) {
4758 int nbouttmp = 3;
4759 int is_break = 0;
4760
4761 if (is_end) {
4762 if (nbintmp == 0)
4763 break;
4764 if ((nbintmp == 1) || (nbintmp == 2))
4765 nbouttmp = 1;
4766 else
4767 nbouttmp = 2;
4768 nbintmp = 3;
4769 is_break = 1;
4770 }
4771 intmp[nbintmp++] = cur;
4772 /*
4773 * if intmp is full, push the 4byte sequence as a 3 byte
4774 * sequence out
4775 */
4776 if (nbintmp == 4) {
4777 nbintmp = 0;
4778 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4779 outtmp[1] =
4780 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4781 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4782 if (outcur + 3 >= outmax) {
4783 retval = 2;
4784 break;
4785 }
4786
4787 for (i = 0; i < nbouttmp; i++)
4788 to[outcur++] = outtmp[i];
4789 inblk = incur;
4790 }
4791
4792 if (is_break) {
4793 retval = 0;
4794 break;
4795 }
4796 }
4797 }
4798
4799 *tolen = outcur;
4800 *inlen = inblk;
4801 return (retval);
4802}
4803
4804/*
4805 * Test routine for the xmlBase64Decode function
4806 */
4807#if 0
4808int main(int argc, char **argv) {
4809 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4810 char output[100];
4811 char output2[100];
4812 char output3[100];
4813 unsigned long inlen = strlen(input);
4814 unsigned long outlen = 100;
4815 int ret;
4816 unsigned long cons, tmp, tmp2, prod;
4817
4818 /*
4819 * Direct
4820 */
4821 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4822
4823 output[outlen] = 0;
4824 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4825
4826 /*
4827 * output chunking
4828 */
4829 cons = 0;
4830 prod = 0;
4831 while (cons < inlen) {
4832 tmp = 5;
4833 tmp2 = inlen - cons;
4834
4835 printf("%ld %ld\n", cons, prod);
4836 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4837 cons += tmp2;
4838 prod += tmp;
4839 printf("%ld %ld\n", cons, prod);
4840 }
4841 output2[outlen] = 0;
4842 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4843
4844 /*
4845 * input chunking
4846 */
4847 cons = 0;
4848 prod = 0;
4849 while (cons < inlen) {
4850 tmp = 100 - prod;
4851 tmp2 = inlen - cons;
4852 if (tmp2 > 5)
4853 tmp2 = 5;
4854
4855 printf("%ld %ld\n", cons, prod);
4856 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4857 cons += tmp2;
4858 prod += tmp;
4859 printf("%ld %ld\n", cons, prod);
4860 }
4861 output3[outlen] = 0;
4862 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4863 return(0);
4864
4865}
4866#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004867#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004868#endif /* LIBXML_READER_ENABLED */