blob: b07532883d66842309605cf233cea3b19ef6d463 [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;
William M. Brack9f797ab2004-07-28 07:40:12 +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;
William M. Brack9f797ab2004-07-28 07:40:12 +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;
William M. Brack9f797ab2004-07-28 07:40:12 +0000869 if ((val != 0) || (reader->ctxt->wellFormed == 0))
Daniel Veillard16ed5972003-11-20 18:22:31 +0000870 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
William M. Brack1af55582004-07-22 17:18:00 +00001184
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001185 if (reader == NULL)
1186 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001187 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001188 if (reader->doc != NULL)
1189 return(xmlTextReaderReadTree(reader));
1190 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001191 return(-1);
1192 if (reader->ctxt->wellFormed != 1)
1193 return(-1);
1194
1195#ifdef DEBUG_READER
1196 fprintf(stderr, "\nREAD ");
1197 DUMP_READER
1198#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001199 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1200 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001201 /*
1202 * Initial state
1203 */
1204 do {
1205 val = xmlTextReaderPushData(reader);
1206 if (val < 0)
1207 return(-1);
1208 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001209 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1210 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001212 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001213 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001214 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001215 if (reader->node == NULL)
1216 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001217 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001218 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001219 if (reader->ctxt->myDoc != NULL) {
1220 reader->node = reader->ctxt->myDoc->children;
1221 }
1222 if (reader->node == NULL)
1223 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001224 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001225 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001226 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001227 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001228 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001229 }
1230 oldstate = reader->state;
1231 olddepth = reader->ctxt->nodeNr;
1232 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001233
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001234get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001235 if (reader->node == NULL) {
1236 if (reader->mode == XML_TEXTREADER_DONE)
1237 return(0);
1238 else
1239 return(-1);
1240 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001241
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001242 /*
1243 * If we are not backtracking on ancestors or examined nodes,
1244 * that the parser didn't finished or that we arent at the end
1245 * of stream, continue processing.
1246 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001247 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001248 (reader->ctxt->nodeNr == olddepth) &&
1249 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001250 (reader->node->children == NULL) ||
1251 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001252 ((reader->node->children != NULL) &&
1253 (reader->node->children->type == XML_TEXT_NODE) &&
1254 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001255 (reader->node->type == XML_DTD_NODE) ||
1256 (reader->node->type == XML_DOCUMENT_NODE) ||
1257 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001258 ((reader->ctxt->node == NULL) ||
1259 (reader->ctxt->node == reader->node) ||
1260 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001261 (reader->ctxt->instate != XML_PARSER_EOF)) {
1262 val = xmlTextReaderPushData(reader);
1263 if (val < 0)
1264 return(-1);
1265 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001266 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001267 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001269 if ((reader->node->children != NULL) &&
1270 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001271 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 (reader->node->type != XML_DTD_NODE)) {
1273 reader->node = reader->node->children;
1274 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001275 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001276 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001277 }
1278 }
1279 if (reader->node->next != NULL) {
1280 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001281 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001282 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001283 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1284#ifdef LIBXML_XINCLUDE_ENABLED
1285 && (reader->in_xinclude <= 0)
1286#endif
1287 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001288 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001289 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001290 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001291#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001292 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001293 (reader->node->type == XML_ELEMENT_NODE))
1294 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001295#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001296 if ((reader->preserves > 0) &&
1297 (reader->node->extra & NODE_IS_SPRESERVED))
1298 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001299 reader->node = reader->node->next;
1300 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001301
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001302 /*
1303 * Cleanup of the old node
1304 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001305 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001306#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001307 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001308#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001309 (reader->entNr == 0) &&
1310 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001311 (reader->node->prev->type != XML_DTD_NODE) &&
1312 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001313 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001314 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001315 xmlUnlinkNode(tmp);
1316 xmlTextReaderFreeNode(reader, tmp);
1317 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001318 }
1319
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001320 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001321 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001322 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001323 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001324 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001325 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001326 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001327 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001328 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001329#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001330 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001331 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001332#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001333 if ((reader->preserves > 0) &&
1334 (reader->node->extra & NODE_IS_SPRESERVED))
1335 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001336 reader->node = reader->node->parent;
1337 if ((reader->node == NULL) ||
1338 (reader->node->type == XML_DOCUMENT_NODE) ||
1339#ifdef LIBXML_DOCB_ENABLED
1340 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1341#endif
1342 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001343 if (reader->mode != XML_TEXTREADER_DONE) {
1344 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1345 reader->mode = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001346 if (val != 0)
1347 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001348 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001349 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001350 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001351
1352 /*
1353 * Cleanup of the old node
1354 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001355 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001356#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001357 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001358#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001359 (reader->entNr == 0) &&
1360 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001361 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001362 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001364 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001365 }
1366
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001367 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001368 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001369 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001370#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001371 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001372#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001373 (reader->entNr == 0) &&
1374 (reader->node->last != NULL) &&
1375 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1376 xmlNodePtr tmp = reader->node->last;
1377 xmlUnlinkNode(tmp);
1378 xmlTextReaderFreeNode(reader, tmp);
1379 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001380 reader->depth--;
1381 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001382
1383node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001384 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001385
1386 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001387 * If we are in the middle of a piece of CDATA make sure it's finished
1388 */
1389 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001390 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001391 ((reader->node->type == XML_TEXT_NODE) ||
1392 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001393 if (xmlTextReaderExpand(reader) == NULL)
1394 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001395 }
1396
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001397#ifdef LIBXML_XINCLUDE_ENABLED
1398 /*
1399 * Handle XInclude if asked for
1400 */
1401 if ((reader->xinclude) && (reader->node != NULL) &&
1402 (reader->node->type == XML_ELEMENT_NODE) &&
1403 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001404 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1405 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001406 if (reader->xincctxt == NULL) {
1407 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001408 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001409 }
1410 /*
1411 * expand that node and process it
1412 */
William M. Brack42331a92004-07-29 07:07:16 +00001413 if (xmlTextReaderExpand(reader) == NULL)
1414 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001415 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1416 }
1417 if (reader->node->type == XML_XINCLUDE_START) {
1418 reader->in_xinclude++;
1419 goto get_next_node;
1420 }
1421 if (reader->node->type == XML_XINCLUDE_END) {
1422 reader->in_xinclude--;
1423 goto get_next_node;
1424 }
1425#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001426 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001427 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001428 */
1429 if ((reader->node != NULL) &&
1430 (reader->node->type == XML_ENTITY_REF_NODE) &&
1431 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1432 /*
1433 * Case where the underlying tree is not availble, lookup the entity
1434 * and walk it.
1435 */
1436 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1437 (reader->ctxt->sax->getEntity != NULL)) {
1438 reader->node->children = (xmlNodePtr)
1439 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1440 }
1441
1442 if ((reader->node->children != NULL) &&
1443 (reader->node->children->type == XML_ENTITY_DECL) &&
1444 (reader->node->children->children != NULL)) {
1445 xmlTextReaderEntPush(reader, reader->node);
1446 reader->node = reader->node->children->children;
1447 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001448#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001449 } else if ((reader->node != NULL) &&
1450 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001451 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001452 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001453#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001454 }
1455 if ((reader->node != NULL) &&
1456 (reader->node->type == XML_ENTITY_DECL) &&
1457 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1458 reader->node = xmlTextReaderEntPop(reader);
1459 reader->depth++;
1460 goto get_next_node;
1461 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001462#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001463 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001464 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001465
1466 if ((node->type == XML_ELEMENT_NODE) &&
1467 ((reader->state != XML_TEXTREADER_END) &&
1468 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1469 xmlTextReaderValidatePush(reader);
1470 } else if ((node->type == XML_TEXT_NODE) ||
1471 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001472 xmlTextReaderValidateCData(reader, node->content,
1473 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001474 }
1475 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001476#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001477#ifdef LIBXML_PATTERN_ENABLED
1478 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1479 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1480 int i;
1481 for (i = 0;i < reader->patternNr;i++) {
1482 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1483 xmlTextReaderPreserve(reader);
1484 break;
1485 }
1486 }
1487 }
1488#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001489 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001490node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001491 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001492 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001493}
1494
Daniel Veillard67df8092002-12-16 22:04:11 +00001495/**
1496 * xmlTextReaderReadState:
1497 * @reader: the xmlTextReaderPtr used
1498 *
1499 * Gets the read state of the reader.
1500 *
1501 * Returns the state value, or -1 in case of error
1502 */
1503int
1504xmlTextReaderReadState(xmlTextReaderPtr reader) {
1505 if (reader == NULL)
1506 return(-1);
1507 return(reader->mode);
1508}
1509
1510/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001511 * xmlTextReaderExpand:
1512 * @reader: the xmlTextReaderPtr used
1513 *
1514 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001515 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001516 *
1517 * Returns a node pointer valid until the next xmlTextReaderRead() call
1518 * or NULL in case of error.
1519 */
1520xmlNodePtr
1521xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001522 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001523 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001524 if (reader->doc != NULL)
1525 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001526 if (reader->ctxt == NULL)
1527 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001528 if (xmlTextReaderDoExpand(reader) < 0)
1529 return(NULL);
1530 return(reader->node);
1531}
1532
1533/**
1534 * xmlTextReaderNext:
1535 * @reader: the xmlTextReaderPtr used
1536 *
1537 * Skip to the node following the current one in document order while
1538 * avoiding the subtree if any.
1539 *
1540 * Returns 1 if the node was read successfully, 0 if there is no more
1541 * nodes to read, or -1 in case of error
1542 */
1543int
1544xmlTextReaderNext(xmlTextReaderPtr reader) {
1545 int ret;
1546 xmlNodePtr cur;
1547
1548 if (reader == NULL)
1549 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001550 if (reader->doc != NULL)
1551 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001552 cur = reader->node;
1553 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1554 return(xmlTextReaderRead(reader));
1555 if (reader->state == XML_TEXTREADER_END)
1556 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001557 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001558 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001559 do {
1560 ret = xmlTextReaderRead(reader);
1561 if (ret != 1)
1562 return(ret);
1563 } while (reader->node != cur);
1564 return(xmlTextReaderRead(reader));
1565}
1566
1567/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001568 * xmlTextReaderReadInnerXml:
1569 * @reader: the xmlTextReaderPtr used
1570 *
1571 * Reads the contents of the current node, including child nodes and markup.
1572 *
1573 * Returns a string containing the XML content, or NULL if the current node
1574 * is neither an element nor attribute, or has no child nodes. The
1575 * string must be deallocated by the caller.
1576 */
1577xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001578xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001579 TODO
1580 return(NULL);
1581}
1582
1583/**
1584 * xmlTextReaderReadOuterXml:
1585 * @reader: the xmlTextReaderPtr used
1586 *
1587 * Reads the contents of the current node, including child nodes and markup.
1588 *
1589 * Returns a string containing the XML content, or NULL if the current node
1590 * is neither an element nor attribute, or has no child nodes. The
1591 * string must be deallocated by the caller.
1592 */
1593xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001594xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001595 TODO
1596 return(NULL);
1597}
1598
1599/**
1600 * xmlTextReaderReadString:
1601 * @reader: the xmlTextReaderPtr used
1602 *
1603 * Reads the contents of an element or a text node as a string.
1604 *
1605 * Returns a string containing the contents of the Element or Text node,
1606 * or NULL if the reader is positioned on any other type of node.
1607 * The string must be deallocated by the caller.
1608 */
1609xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001610xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001611 TODO
1612 return(NULL);
1613}
1614
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001615#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001616/**
1617 * xmlTextReaderReadBase64:
1618 * @reader: the xmlTextReaderPtr used
1619 * @array: a byte array to store the content.
1620 * @offset: the zero-based index into array where the method should
1621 * begin to write.
1622 * @len: the number of bytes to write.
1623 *
1624 * Reads and decodes the Base64 encoded contents of an element and
1625 * stores the result in a byte buffer.
1626 *
1627 * Returns the number of bytes written to array, or zero if the current
1628 * instance is not positioned on an element or -1 in case of error.
1629 */
1630int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001631xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1632 unsigned char *array ATTRIBUTE_UNUSED,
1633 int offset ATTRIBUTE_UNUSED,
1634 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001635 if ((reader == NULL) || (reader->ctxt == NULL))
1636 return(-1);
1637 if (reader->ctxt->wellFormed != 1)
1638 return(-1);
1639
1640 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1641 return(0);
1642 TODO
1643 return(0);
1644}
1645
1646/**
1647 * xmlTextReaderReadBinHex:
1648 * @reader: the xmlTextReaderPtr used
1649 * @array: a byte array to store the content.
1650 * @offset: the zero-based index into array where the method should
1651 * begin to write.
1652 * @len: the number of bytes to write.
1653 *
1654 * Reads and decodes the BinHex encoded contents of an element and
1655 * stores the result in a byte buffer.
1656 *
1657 * Returns the number of bytes written to array, or zero if the current
1658 * instance is not positioned on an element or -1 in case of error.
1659 */
1660int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001661xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1662 unsigned char *array ATTRIBUTE_UNUSED,
1663 int offset ATTRIBUTE_UNUSED,
1664 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001665 if ((reader == NULL) || (reader->ctxt == NULL))
1666 return(-1);
1667 if (reader->ctxt->wellFormed != 1)
1668 return(-1);
1669
1670 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1671 return(0);
1672 TODO
1673 return(0);
1674}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001675#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001676
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001677/************************************************************************
1678 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001679 * Operating on a preparsed tree *
1680 * *
1681 ************************************************************************/
1682static int
1683xmlTextReaderNextTree(xmlTextReaderPtr reader)
1684{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001685 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001686 return(-1);
1687
1688 if (reader->state == XML_TEXTREADER_END)
1689 return(0);
1690
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001691 if (reader->node == NULL) {
1692 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001693 reader->state = XML_TEXTREADER_END;
1694 return(0);
1695 }
1696
1697 reader->node = reader->doc->children;
1698 reader->state = XML_TEXTREADER_START;
1699 return(1);
1700 }
1701
1702 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1703 if (reader->node->children != 0) {
1704 reader->node = reader->node->children;
1705 reader->depth++;
1706 reader->state = XML_TEXTREADER_START;
1707 return(1);
1708 }
1709
1710 if ((reader->node->type == XML_ELEMENT_NODE) ||
1711 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1712 reader->state = XML_TEXTREADER_BACKTRACK;
1713 return(1);
1714 }
1715 }
1716
1717 if (reader->node->next != 0) {
1718 reader->node = reader->node->next;
1719 reader->state = XML_TEXTREADER_START;
1720 return(1);
1721 }
1722
1723 if (reader->node->parent != 0) {
1724 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1725 reader->state = XML_TEXTREADER_END;
1726 return(0);
1727 }
1728
1729 reader->node = reader->node->parent;
1730 reader->depth--;
1731 reader->state = XML_TEXTREADER_BACKTRACK;
1732 return(1);
1733 }
1734
1735 reader->state = XML_TEXTREADER_END;
1736
1737 return(1);
1738}
1739
1740/**
1741 * xmlTextReaderReadTree:
1742 * @reader: the xmlTextReaderPtr used
1743 *
1744 * Moves the position of the current instance to the next node in
1745 * the stream, exposing its properties.
1746 *
1747 * Returns 1 if the node was read successfully, 0 if there is no more
1748 * nodes to read, or -1 in case of error
1749 */
1750static int
1751xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1752 if (reader->state == XML_TEXTREADER_END)
1753 return(0);
1754
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001755next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001756 if (reader->node == NULL) {
1757 if (reader->doc->children == NULL) {
1758 reader->state = XML_TEXTREADER_END;
1759 return(0);
1760 }
1761
1762 reader->node = reader->doc->children;
1763 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001764 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001765 }
1766
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001767 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1768 (reader->node->type != XML_DTD_NODE) &&
1769 (reader->node->type != XML_XINCLUDE_START) &&
1770 (reader->node->type != XML_ENTITY_REF_NODE)) {
1771 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001772 reader->node = reader->node->children;
1773 reader->depth++;
1774 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001775 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001776 }
1777
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001778 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001779 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001780 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001781 }
1782 }
1783
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001784 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001785 reader->node = reader->node->next;
1786 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001787 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001788 }
1789
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001790 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001791 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1792 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1793 reader->state = XML_TEXTREADER_END;
1794 return(0);
1795 }
1796
1797 reader->node = reader->node->parent;
1798 reader->depth--;
1799 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001800 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 }
1802
1803 reader->state = XML_TEXTREADER_END;
1804
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001805found_node:
1806 if ((reader->node->type == XML_XINCLUDE_START) ||
1807 (reader->node->type == XML_XINCLUDE_END))
1808 goto next_node;
1809
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001810 return(1);
1811}
1812
1813/**
William M. Brackb1d53162003-11-18 06:54:40 +00001814 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001815 * @reader: the xmlTextReaderPtr used
1816 *
1817 * Skip to the node following the current one in document order while
1818 * avoiding the subtree if any.
1819 * Currently implemented only for Readers built on a document
1820 *
1821 * Returns 1 if the node was read successfully, 0 if there is no more
1822 * nodes to read, or -1 in case of error
1823 */
1824int
1825xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1826 if (reader == NULL)
1827 return(-1);
1828 if (reader->doc == NULL) {
1829 TODO
1830 return(-1);
1831 }
1832
1833 if (reader->state == XML_TEXTREADER_END)
1834 return(0);
1835
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001836 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001837 return(xmlTextReaderNextTree(reader));
1838
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001839 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001840 reader->node = reader->node->next;
1841 reader->state = XML_TEXTREADER_START;
1842 return(1);
1843 }
1844
1845 return(0);
1846}
1847
1848/************************************************************************
1849 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001850 * Constructor and destructors *
1851 * *
1852 ************************************************************************/
1853/**
1854 * xmlNewTextReader:
1855 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001856 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001857 *
1858 * Create an xmlTextReader structure fed with @input
1859 *
1860 * Returns the new xmlTextReaderPtr or NULL in case of error
1861 */
1862xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001863xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001864 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001865
1866 if (input == NULL)
1867 return(NULL);
1868 ret = xmlMalloc(sizeof(xmlTextReader));
1869 if (ret == NULL) {
1870 xmlGenericError(xmlGenericErrorContext,
1871 "xmlNewTextReader : malloc failed\n");
1872 return(NULL);
1873 }
1874 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001875 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001876 ret->entTab = NULL;
1877 ret->entMax = 0;
1878 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001879 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001880 ret->buffer = xmlBufferCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00001881 if (ret->buffer == NULL) {
1882 xmlFree(ret);
1883 xmlGenericError(xmlGenericErrorContext,
1884 "xmlNewTextReader : malloc failed\n");
1885 return(NULL);
1886 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001887 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1888 if (ret->sax == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001889 xmlBufferFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001890 xmlFree(ret);
1891 xmlGenericError(xmlGenericErrorContext,
1892 "xmlNewTextReader : malloc failed\n");
1893 return(NULL);
1894 }
Daniel Veillard81273902003-09-30 00:43:48 +00001895 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001896 ret->startElement = ret->sax->startElement;
1897 ret->sax->startElement = xmlTextReaderStartElement;
1898 ret->endElement = ret->sax->endElement;
1899 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001900#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001901 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001902#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001903 ret->startElementNs = ret->sax->startElementNs;
1904 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1905 ret->endElementNs = ret->sax->endElementNs;
1906 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001907#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001908 } else {
1909 ret->startElementNs = NULL;
1910 ret->endElementNs = NULL;
1911 }
Daniel Veillard81273902003-09-30 00:43:48 +00001912#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001913 ret->characters = ret->sax->characters;
1914 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001915 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001916 ret->cdataBlock = ret->sax->cdataBlock;
1917 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001918
Daniel Veillard67df8092002-12-16 22:04:11 +00001919 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001920 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001921 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001922 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001923 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001924 }
1925 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001926 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001927 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001928 ret->base = 0;
1929 ret->cur = 4;
1930 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001931 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001932 ret->base = 0;
1933 ret->cur = 0;
1934 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001935
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001936 if (ret->ctxt == NULL) {
1937 xmlGenericError(xmlGenericErrorContext,
1938 "xmlNewTextReader : malloc failed\n");
William M. Brack42331a92004-07-29 07:07:16 +00001939 xmlBufferFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001940 xmlFree(ret->sax);
1941 xmlFree(ret);
1942 return(NULL);
1943 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001944 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001945 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001946 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001947 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001948 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001949 /*
1950 * use the parser dictionnary to allocate all elements and attributes names
1951 */
1952 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001953 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001954#ifdef LIBXML_XINCLUDE_ENABLED
1955 ret->xinclude = 0;
1956#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001957#ifdef LIBXML_PATTERN_ENABLED
1958 ret->patternMax = 0;
1959 ret->patternTab = NULL;
1960#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001961 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001962}
1963
1964/**
1965 * xmlNewTextReaderFilename:
1966 * @URI: the URI of the resource to process
1967 *
1968 * Create an xmlTextReader structure fed with the resource at @URI
1969 *
1970 * Returns the new xmlTextReaderPtr or NULL in case of error
1971 */
1972xmlTextReaderPtr
1973xmlNewTextReaderFilename(const char *URI) {
1974 xmlParserInputBufferPtr input;
1975 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001976 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001977
1978 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1979 if (input == NULL)
1980 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001981 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001982 if (ret == NULL) {
1983 xmlFreeParserInputBuffer(input);
1984 return(NULL);
1985 }
1986 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001987 if (ret->ctxt->directory == NULL)
1988 directory = xmlParserGetDirectory(URI);
1989 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1990 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1991 if (directory != NULL)
1992 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001993 return(ret);
1994}
1995
1996/**
1997 * xmlFreeTextReader:
1998 * @reader: the xmlTextReaderPtr
1999 *
2000 * Deallocate all the resources associated to the reader
2001 */
2002void
2003xmlFreeTextReader(xmlTextReaderPtr reader) {
2004 if (reader == NULL)
2005 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002006#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002007 if (reader->rngSchemas != NULL) {
2008 xmlRelaxNGFree(reader->rngSchemas);
2009 reader->rngSchemas = NULL;
2010 }
2011 if (reader->rngValidCtxt != NULL) {
2012 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2013 reader->rngValidCtxt = NULL;
2014 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002015#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002016#ifdef LIBXML_XINCLUDE_ENABLED
2017 if (reader->xincctxt != NULL)
2018 xmlXIncludeFreeContext(reader->xincctxt);
2019#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002020#ifdef LIBXML_PATTERN_ENABLED
2021 if (reader->patternTab != NULL) {
2022 int i;
2023 for (i = 0;i < reader->patternNr;i++) {
2024 if (reader->patternTab[i] != NULL)
2025 xmlFreePattern(reader->patternTab[i]);
2026 }
2027 xmlFree(reader->patternTab);
2028 }
2029#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002030 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002031 if (reader->dict == reader->ctxt->dict)
2032 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002033 if (reader->ctxt->myDoc != NULL) {
2034 if (reader->preserve == 0)
2035 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2036 reader->ctxt->myDoc = NULL;
2037 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002038 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2039 (reader->ctxt->vctxt.vstateMax > 0)){
2040 xmlFree(reader->ctxt->vctxt.vstateTab);
2041 reader->ctxt->vctxt.vstateTab = 0;
2042 reader->ctxt->vctxt.vstateMax = 0;
2043 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002044 if (reader->allocs & XML_TEXTREADER_CTXT)
2045 xmlFreeParserCtxt(reader->ctxt);
2046 }
2047 if (reader->sax != NULL)
2048 xmlFree(reader->sax);
2049 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2050 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002051 if (reader->faketext != NULL) {
2052 xmlFreeNode(reader->faketext);
2053 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002054 if (reader->buffer != NULL)
2055 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002056 if (reader->entTab != NULL)
2057 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002058 if (reader->dict != NULL)
2059 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002060 xmlFree(reader);
2061}
2062
2063/************************************************************************
2064 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002065 * Methods for XmlTextReader *
2066 * *
2067 ************************************************************************/
2068/**
2069 * xmlTextReaderClose:
2070 * @reader: the xmlTextReaderPtr used
2071 *
2072 * This method releases any resources allocated by the current instance
2073 * changes the state to Closed and close any underlying input.
2074 *
2075 * Returns 0 or -1 in case of error
2076 */
2077int
2078xmlTextReaderClose(xmlTextReaderPtr reader) {
2079 if (reader == NULL)
2080 return(-1);
2081 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002082 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002083 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2084 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002085 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002086 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002087 if (reader->preserve == 0)
2088 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002089 reader->ctxt->myDoc = NULL;
2090 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002091 }
2092 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2093 xmlFreeParserInputBuffer(reader->input);
2094 reader->allocs -= XML_TEXTREADER_INPUT;
2095 }
2096 return(0);
2097}
2098
2099/**
2100 * xmlTextReaderGetAttributeNo:
2101 * @reader: the xmlTextReaderPtr used
2102 * @no: the zero-based index of the attribute relative to the containing element
2103 *
2104 * Provides the value of the attribute with the specified index relative
2105 * to the containing element.
2106 *
2107 * Returns a string containing the value of the specified attribute, or NULL
2108 * in case of error. The string must be deallocated by the caller.
2109 */
2110xmlChar *
2111xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2112 xmlChar *ret;
2113 int i;
2114 xmlAttrPtr cur;
2115 xmlNsPtr ns;
2116
2117 if (reader == NULL)
2118 return(NULL);
2119 if (reader->node == NULL)
2120 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002121 if (reader->curnode != NULL)
2122 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002123 /* TODO: handle the xmlDecl */
2124 if (reader->node->type != XML_ELEMENT_NODE)
2125 return(NULL);
2126
2127 ns = reader->node->nsDef;
2128 for (i = 0;(i < no) && (ns != NULL);i++) {
2129 ns = ns->next;
2130 }
2131 if (ns != NULL)
2132 return(xmlStrdup(ns->href));
2133
2134 cur = reader->node->properties;
2135 if (cur == NULL)
2136 return(NULL);
2137 for (;i < no;i++) {
2138 cur = cur->next;
2139 if (cur == NULL)
2140 return(NULL);
2141 }
2142 /* TODO walk the DTD if present */
2143
2144 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2145 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2146 return(ret);
2147}
2148
2149/**
2150 * xmlTextReaderGetAttribute:
2151 * @reader: the xmlTextReaderPtr used
2152 * @name: the qualified name of the attribute.
2153 *
2154 * Provides the value of the attribute with the specified qualified name.
2155 *
2156 * Returns a string containing the value of the specified attribute, or NULL
2157 * in case of error. The string must be deallocated by the caller.
2158 */
2159xmlChar *
2160xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2161 xmlChar *prefix = NULL;
2162 xmlChar *localname;
2163 xmlNsPtr ns;
2164 xmlChar *ret = NULL;
2165
2166 if ((reader == NULL) || (name == NULL))
2167 return(NULL);
2168 if (reader->node == NULL)
2169 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002170 if (reader->curnode != NULL)
2171 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002172
2173 /* TODO: handle the xmlDecl */
2174 if (reader->node->type != XML_ELEMENT_NODE)
2175 return(NULL);
2176
2177 localname = xmlSplitQName2(name, &prefix);
2178 if (localname == NULL)
2179 return(xmlGetProp(reader->node, name));
2180
2181 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2182 if (ns != NULL)
2183 ret = xmlGetNsProp(reader->node, localname, ns->href);
2184
2185 if (localname != NULL)
2186 xmlFree(localname);
2187 if (prefix != NULL)
2188 xmlFree(prefix);
2189 return(ret);
2190}
2191
2192
2193/**
2194 * xmlTextReaderGetAttributeNs:
2195 * @reader: the xmlTextReaderPtr used
2196 * @localName: the local name of the attribute.
2197 * @namespaceURI: the namespace URI of the attribute.
2198 *
2199 * Provides the value of the specified attribute
2200 *
2201 * Returns a string containing the value of the specified attribute, or NULL
2202 * in case of error. The string must be deallocated by the caller.
2203 */
2204xmlChar *
2205xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2206 const xmlChar *namespaceURI) {
2207 if ((reader == NULL) || (localName == NULL))
2208 return(NULL);
2209 if (reader->node == NULL)
2210 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002211 if (reader->curnode != NULL)
2212 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002213
2214 /* TODO: handle the xmlDecl */
2215 if (reader->node->type != XML_ELEMENT_NODE)
2216 return(NULL);
2217
2218 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2219}
2220
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002221/**
2222 * xmlTextReaderGetRemainder:
2223 * @reader: the xmlTextReaderPtr used
2224 *
2225 * Method to get the remainder of the buffered XML. this method stops the
2226 * parser, set its state to End Of File and return the input stream with
2227 * what is left that the parser did not use.
2228 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002229 * The implementation is not good, the parser certainly procgressed past
2230 * what's left in reader->input, and there is an allocation problem. Best
2231 * would be to rewrite it differently.
2232 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002233 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2234 * in case of error.
2235 */
2236xmlParserInputBufferPtr
2237xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2238 xmlParserInputBufferPtr ret = NULL;
2239
2240 if (reader == NULL)
2241 return(NULL);
2242 if (reader->node == NULL)
2243 return(NULL);
2244
2245 reader->node = NULL;
2246 reader->curnode = NULL;
2247 reader->mode = XML_TEXTREADER_MODE_EOF;
2248 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002249 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002250 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002251 if (reader->preserve == 0)
2252 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002253 reader->ctxt->myDoc = NULL;
2254 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002255 }
2256 if (reader->allocs & XML_TEXTREADER_INPUT) {
2257 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002258 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002259 reader->allocs -= XML_TEXTREADER_INPUT;
2260 } else {
2261 /*
2262 * Hum, one may need to duplicate the data structure because
2263 * without reference counting the input may be freed twice:
2264 * - by the layer which allocated it.
2265 * - by the layer to which would have been returned to.
2266 */
2267 TODO
2268 return(NULL);
2269 }
2270 return(ret);
2271}
2272
2273/**
2274 * xmlTextReaderLookupNamespace:
2275 * @reader: the xmlTextReaderPtr used
2276 * @prefix: the prefix whose namespace URI is to be resolved. To return
2277 * the default namespace, specify NULL
2278 *
2279 * Resolves a namespace prefix in the scope of the current element.
2280 *
2281 * Returns a string containing the namespace URI to which the prefix maps
2282 * or NULL in case of error. The string must be deallocated by the caller.
2283 */
2284xmlChar *
2285xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2286 xmlNsPtr ns;
2287
2288 if (reader == NULL)
2289 return(NULL);
2290 if (reader->node == NULL)
2291 return(NULL);
2292
2293 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2294 if (ns == NULL)
2295 return(NULL);
2296 return(xmlStrdup(ns->href));
2297}
2298
2299/**
2300 * xmlTextReaderMoveToAttributeNo:
2301 * @reader: the xmlTextReaderPtr used
2302 * @no: the zero-based index of the attribute relative to the containing
2303 * element.
2304 *
2305 * Moves the position of the current instance to the attribute with
2306 * the specified index relative to the containing element.
2307 *
2308 * Returns 1 in case of success, -1 in case of error, 0 if not found
2309 */
2310int
2311xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2312 int i;
2313 xmlAttrPtr cur;
2314 xmlNsPtr ns;
2315
2316 if (reader == NULL)
2317 return(-1);
2318 if (reader->node == NULL)
2319 return(-1);
2320 /* TODO: handle the xmlDecl */
2321 if (reader->node->type != XML_ELEMENT_NODE)
2322 return(-1);
2323
2324 reader->curnode = NULL;
2325
2326 ns = reader->node->nsDef;
2327 for (i = 0;(i < no) && (ns != NULL);i++) {
2328 ns = ns->next;
2329 }
2330 if (ns != NULL) {
2331 reader->curnode = (xmlNodePtr) ns;
2332 return(1);
2333 }
2334
2335 cur = reader->node->properties;
2336 if (cur == NULL)
2337 return(0);
2338 for (;i < no;i++) {
2339 cur = cur->next;
2340 if (cur == NULL)
2341 return(0);
2342 }
2343 /* TODO walk the DTD if present */
2344
2345 reader->curnode = (xmlNodePtr) cur;
2346 return(1);
2347}
2348
2349/**
2350 * xmlTextReaderMoveToAttribute:
2351 * @reader: the xmlTextReaderPtr used
2352 * @name: the qualified name of the attribute.
2353 *
2354 * Moves the position of the current instance to the attribute with
2355 * the specified qualified name.
2356 *
2357 * Returns 1 in case of success, -1 in case of error, 0 if not found
2358 */
2359int
2360xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2361 xmlChar *prefix = NULL;
2362 xmlChar *localname;
2363 xmlNsPtr ns;
2364 xmlAttrPtr prop;
2365
2366 if ((reader == NULL) || (name == NULL))
2367 return(-1);
2368 if (reader->node == NULL)
2369 return(-1);
2370
2371 /* TODO: handle the xmlDecl */
2372 if (reader->node->type != XML_ELEMENT_NODE)
2373 return(0);
2374
2375 localname = xmlSplitQName2(name, &prefix);
2376 if (localname == NULL) {
2377 /*
2378 * Namespace default decl
2379 */
2380 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2381 ns = reader->node->nsDef;
2382 while (ns != NULL) {
2383 if (ns->prefix == NULL) {
2384 reader->curnode = (xmlNodePtr) ns;
2385 return(1);
2386 }
2387 ns = ns->next;
2388 }
2389 return(0);
2390 }
2391
2392 prop = reader->node->properties;
2393 while (prop != NULL) {
2394 /*
2395 * One need to have
2396 * - same attribute names
2397 * - and the attribute carrying that namespace
2398 */
2399 if ((xmlStrEqual(prop->name, name)) &&
2400 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2401 reader->curnode = (xmlNodePtr) prop;
2402 return(1);
2403 }
2404 prop = prop->next;
2405 }
2406 return(0);
2407 }
2408
2409 /*
2410 * Namespace default decl
2411 */
2412 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2413 ns = reader->node->nsDef;
2414 while (ns != NULL) {
2415 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2416 reader->curnode = (xmlNodePtr) ns;
2417 goto found;
2418 }
2419 ns = ns->next;
2420 }
2421 goto not_found;
2422 }
2423 prop = reader->node->properties;
2424 while (prop != NULL) {
2425 /*
2426 * One need to have
2427 * - same attribute names
2428 * - and the attribute carrying that namespace
2429 */
2430 if ((xmlStrEqual(prop->name, localname)) &&
2431 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2432 reader->curnode = (xmlNodePtr) prop;
2433 goto found;
2434 }
2435 prop = prop->next;
2436 }
2437not_found:
2438 if (localname != NULL)
2439 xmlFree(localname);
2440 if (prefix != NULL)
2441 xmlFree(prefix);
2442 return(0);
2443
2444found:
2445 if (localname != NULL)
2446 xmlFree(localname);
2447 if (prefix != NULL)
2448 xmlFree(prefix);
2449 return(1);
2450}
2451
2452/**
2453 * xmlTextReaderMoveToAttributeNs:
2454 * @reader: the xmlTextReaderPtr used
2455 * @localName: the local name of the attribute.
2456 * @namespaceURI: the namespace URI of the attribute.
2457 *
2458 * Moves the position of the current instance to the attribute with the
2459 * specified local name and namespace URI.
2460 *
2461 * Returns 1 in case of success, -1 in case of error, 0 if not found
2462 */
2463int
2464xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2465 const xmlChar *localName, const xmlChar *namespaceURI) {
2466 xmlAttrPtr prop;
2467 xmlNodePtr node;
2468
2469 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2470 return(-1);
2471 if (reader->node == NULL)
2472 return(-1);
2473 if (reader->node->type != XML_ELEMENT_NODE)
2474 return(0);
2475 node = reader->node;
2476
2477 /*
2478 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2479 * namespace name associated to "xmlns"
2480 */
2481 prop = node->properties;
2482 while (prop != NULL) {
2483 /*
2484 * One need to have
2485 * - same attribute names
2486 * - and the attribute carrying that namespace
2487 */
2488 if (xmlStrEqual(prop->name, localName) &&
2489 ((prop->ns != NULL) &&
2490 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2491 reader->curnode = (xmlNodePtr) prop;
2492 return(1);
2493 }
2494 prop = prop->next;
2495 }
2496 return(0);
2497}
2498
2499/**
2500 * xmlTextReaderMoveToFirstAttribute:
2501 * @reader: the xmlTextReaderPtr used
2502 *
2503 * Moves the position of the current instance to the first attribute
2504 * associated with the current node.
2505 *
2506 * Returns 1 in case of success, -1 in case of error, 0 if not found
2507 */
2508int
2509xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2510 if (reader == NULL)
2511 return(-1);
2512 if (reader->node == NULL)
2513 return(-1);
2514 if (reader->node->type != XML_ELEMENT_NODE)
2515 return(0);
2516
2517 if (reader->node->nsDef != NULL) {
2518 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2519 return(1);
2520 }
2521 if (reader->node->properties != NULL) {
2522 reader->curnode = (xmlNodePtr) reader->node->properties;
2523 return(1);
2524 }
2525 return(0);
2526}
2527
2528/**
2529 * xmlTextReaderMoveToNextAttribute:
2530 * @reader: the xmlTextReaderPtr used
2531 *
2532 * Moves the position of the current instance to the next attribute
2533 * associated with the current node.
2534 *
2535 * Returns 1 in case of success, -1 in case of error, 0 if not found
2536 */
2537int
2538xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2539 if (reader == NULL)
2540 return(-1);
2541 if (reader->node == NULL)
2542 return(-1);
2543 if (reader->node->type != XML_ELEMENT_NODE)
2544 return(0);
2545 if (reader->curnode == NULL)
2546 return(xmlTextReaderMoveToFirstAttribute(reader));
2547
2548 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2549 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2550 if (ns->next != NULL) {
2551 reader->curnode = (xmlNodePtr) ns->next;
2552 return(1);
2553 }
2554 if (reader->node->properties != NULL) {
2555 reader->curnode = (xmlNodePtr) reader->node->properties;
2556 return(1);
2557 }
2558 return(0);
2559 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2560 (reader->curnode->next != NULL)) {
2561 reader->curnode = reader->curnode->next;
2562 return(1);
2563 }
2564 return(0);
2565}
2566
2567/**
2568 * xmlTextReaderMoveToElement:
2569 * @reader: the xmlTextReaderPtr used
2570 *
2571 * Moves the position of the current instance to the node that
2572 * contains the current Attribute node.
2573 *
2574 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2575 */
2576int
2577xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2578 if (reader == NULL)
2579 return(-1);
2580 if (reader->node == NULL)
2581 return(-1);
2582 if (reader->node->type != XML_ELEMENT_NODE)
2583 return(0);
2584 if (reader->curnode != NULL) {
2585 reader->curnode = NULL;
2586 return(1);
2587 }
2588 return(0);
2589}
2590
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002591/**
2592 * xmlTextReaderReadAttributeValue:
2593 * @reader: the xmlTextReaderPtr used
2594 *
2595 * Parses an attribute value into one or more Text and EntityReference nodes.
2596 *
2597 * Returns 1 in case of success, 0 if the reader was not positionned on an
2598 * ttribute node or all the attribute values have been read, or -1
2599 * in case of error.
2600 */
2601int
2602xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2603 if (reader == NULL)
2604 return(-1);
2605 if (reader->node == NULL)
2606 return(-1);
2607 if (reader->curnode == NULL)
2608 return(0);
2609 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2610 if (reader->curnode->children == NULL)
2611 return(0);
2612 reader->curnode = reader->curnode->children;
2613 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2614 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2615
2616 if (reader->faketext == NULL) {
2617 reader->faketext = xmlNewDocText(reader->node->doc,
2618 ns->href);
2619 } else {
2620 if (reader->faketext->content != NULL)
2621 xmlFree(reader->faketext->content);
2622 reader->faketext->content = xmlStrdup(ns->href);
2623 }
2624 reader->curnode = reader->faketext;
2625 } else {
2626 if (reader->curnode->next == NULL)
2627 return(0);
2628 reader->curnode = reader->curnode->next;
2629 }
2630 return(1);
2631}
2632
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002633/************************************************************************
2634 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002635 * Acces API to the current node *
2636 * *
2637 ************************************************************************/
2638/**
2639 * xmlTextReaderAttributeCount:
2640 * @reader: the xmlTextReaderPtr used
2641 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002642 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002643 *
2644 * Returns 0 i no attributes, -1 in case of error or the attribute count
2645 */
2646int
2647xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2648 int ret;
2649 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002650 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002651 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002652
2653 if (reader == NULL)
2654 return(-1);
2655 if (reader->node == NULL)
2656 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002657
2658 if (reader->curnode != NULL)
2659 node = reader->curnode;
2660 else
2661 node = reader->node;
2662
2663 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002664 return(0);
2665 if ((reader->state == XML_TEXTREADER_END) ||
2666 (reader->state == XML_TEXTREADER_BACKTRACK))
2667 return(0);
2668 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002669 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002670 while (attr != NULL) {
2671 ret++;
2672 attr = attr->next;
2673 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002674 ns = node->nsDef;
2675 while (ns != NULL) {
2676 ret++;
2677 ns = ns->next;
2678 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002679 return(ret);
2680}
2681
2682/**
2683 * xmlTextReaderNodeType:
2684 * @reader: the xmlTextReaderPtr used
2685 *
2686 * Get the node type of the current node
2687 * Reference:
2688 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2689 *
2690 * Returns the xmlNodeType of the current node or -1 in case of error
2691 */
2692int
2693xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002694 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002695
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002696 if (reader == NULL)
2697 return(-1);
2698 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002699 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002700 if (reader->curnode != NULL)
2701 node = reader->curnode;
2702 else
2703 node = reader->node;
2704 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002705 case XML_ELEMENT_NODE:
2706 if ((reader->state == XML_TEXTREADER_END) ||
2707 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002708 return(XML_READER_TYPE_END_ELEMENT);
2709 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002710 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002711 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002712 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002713 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002714 if (xmlIsBlankNode(reader->node)) {
2715 if (xmlNodeGetSpacePreserve(reader->node))
2716 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2717 else
2718 return(XML_READER_TYPE_WHITESPACE);
2719 } else {
2720 return(XML_READER_TYPE_TEXT);
2721 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002722 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002723 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002724 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002725 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002726 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002727 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002728 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002729 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002730 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002731 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002732 case XML_DOCUMENT_NODE:
2733 case XML_HTML_DOCUMENT_NODE:
2734#ifdef LIBXML_DOCB_ENABLED
2735 case XML_DOCB_DOCUMENT_NODE:
2736#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002737 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002738 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002739 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002740 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002741 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002742 case XML_DOCUMENT_TYPE_NODE:
2743 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002744 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002745
2746 case XML_ELEMENT_DECL:
2747 case XML_ATTRIBUTE_DECL:
2748 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002749 case XML_XINCLUDE_START:
2750 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002751 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002752 }
2753 return(-1);
2754}
2755
2756/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002757 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002758 * @reader: the xmlTextReaderPtr used
2759 *
2760 * Check if the current node is empty
2761 *
2762 * Returns 1 if empty, 0 if not and -1 in case of error
2763 */
2764int
2765xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2766 if ((reader == NULL) || (reader->node == NULL))
2767 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002768 if (reader->node->type != XML_ELEMENT_NODE)
2769 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002770 if (reader->curnode != NULL)
2771 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002772 if (reader->node->children != NULL)
2773 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002774 if (reader->state == XML_TEXTREADER_END)
2775 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002776 if (reader->doc != NULL)
2777 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002778#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002779 if (reader->in_xinclude > 0)
2780 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002781#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002782 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002783}
2784
2785/**
2786 * xmlTextReaderLocalName:
2787 * @reader: the xmlTextReaderPtr used
2788 *
2789 * The local name of the node.
2790 *
2791 * Returns the local name or NULL if not available
2792 */
2793xmlChar *
2794xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002795 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002796 if ((reader == NULL) || (reader->node == NULL))
2797 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002798 if (reader->curnode != NULL)
2799 node = reader->curnode;
2800 else
2801 node = reader->node;
2802 if (node->type == XML_NAMESPACE_DECL) {
2803 xmlNsPtr ns = (xmlNsPtr) node;
2804 if (ns->prefix == NULL)
2805 return(xmlStrdup(BAD_CAST "xmlns"));
2806 else
2807 return(xmlStrdup(ns->prefix));
2808 }
2809 if ((node->type != XML_ELEMENT_NODE) &&
2810 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002811 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002812 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002813}
2814
2815/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002816 * xmlTextReaderConstLocalName:
2817 * @reader: the xmlTextReaderPtr used
2818 *
2819 * The local name of the node.
2820 *
2821 * Returns the local name or NULL if not available, the
2822 * string will be deallocated with the reader.
2823 */
2824const xmlChar *
2825xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2826 xmlNodePtr node;
2827 if ((reader == NULL) || (reader->node == NULL))
2828 return(NULL);
2829 if (reader->curnode != NULL)
2830 node = reader->curnode;
2831 else
2832 node = reader->node;
2833 if (node->type == XML_NAMESPACE_DECL) {
2834 xmlNsPtr ns = (xmlNsPtr) node;
2835 if (ns->prefix == NULL)
2836 return(CONSTSTR(BAD_CAST "xmlns"));
2837 else
2838 return(ns->prefix);
2839 }
2840 if ((node->type != XML_ELEMENT_NODE) &&
2841 (node->type != XML_ATTRIBUTE_NODE))
2842 return(xmlTextReaderConstName(reader));
2843 return(node->name);
2844}
2845
2846/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002847 * xmlTextReaderName:
2848 * @reader: the xmlTextReaderPtr used
2849 *
2850 * The qualified name of the node, equal to Prefix :LocalName.
2851 *
2852 * Returns the local name or NULL if not available
2853 */
2854xmlChar *
2855xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002856 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002857 xmlChar *ret;
2858
2859 if ((reader == NULL) || (reader->node == NULL))
2860 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002861 if (reader->curnode != NULL)
2862 node = reader->curnode;
2863 else
2864 node = reader->node;
2865 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002866 case XML_ELEMENT_NODE:
2867 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002868 if ((node->ns == NULL) ||
2869 (node->ns->prefix == NULL))
2870 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002871
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002872 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002873 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002874 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002875 return(ret);
2876 case XML_TEXT_NODE:
2877 return(xmlStrdup(BAD_CAST "#text"));
2878 case XML_CDATA_SECTION_NODE:
2879 return(xmlStrdup(BAD_CAST "#cdata-section"));
2880 case XML_ENTITY_NODE:
2881 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002882 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002883 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002884 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002885 case XML_COMMENT_NODE:
2886 return(xmlStrdup(BAD_CAST "#comment"));
2887 case XML_DOCUMENT_NODE:
2888 case XML_HTML_DOCUMENT_NODE:
2889#ifdef LIBXML_DOCB_ENABLED
2890 case XML_DOCB_DOCUMENT_NODE:
2891#endif
2892 return(xmlStrdup(BAD_CAST "#document"));
2893 case XML_DOCUMENT_FRAG_NODE:
2894 return(xmlStrdup(BAD_CAST "#document-fragment"));
2895 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002896 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002897 case XML_DOCUMENT_TYPE_NODE:
2898 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002899 return(xmlStrdup(node->name));
2900 case XML_NAMESPACE_DECL: {
2901 xmlNsPtr ns = (xmlNsPtr) node;
2902
2903 ret = xmlStrdup(BAD_CAST "xmlns");
2904 if (ns->prefix == NULL)
2905 return(ret);
2906 ret = xmlStrcat(ret, BAD_CAST ":");
2907 ret = xmlStrcat(ret, ns->prefix);
2908 return(ret);
2909 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002910
2911 case XML_ELEMENT_DECL:
2912 case XML_ATTRIBUTE_DECL:
2913 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002914 case XML_XINCLUDE_START:
2915 case XML_XINCLUDE_END:
2916 return(NULL);
2917 }
2918 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002919}
2920
2921/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002922 * xmlTextReaderConstName:
2923 * @reader: the xmlTextReaderPtr used
2924 *
2925 * The qualified name of the node, equal to Prefix :LocalName.
2926 *
2927 * Returns the local name or NULL if not available, the string is
2928 * deallocated with the reader.
2929 */
2930const xmlChar *
2931xmlTextReaderConstName(xmlTextReaderPtr reader) {
2932 xmlNodePtr node;
2933
2934 if ((reader == NULL) || (reader->node == NULL))
2935 return(NULL);
2936 if (reader->curnode != NULL)
2937 node = reader->curnode;
2938 else
2939 node = reader->node;
2940 switch (node->type) {
2941 case XML_ELEMENT_NODE:
2942 case XML_ATTRIBUTE_NODE:
2943 if ((node->ns == NULL) ||
2944 (node->ns->prefix == NULL))
2945 return(node->name);
2946 return(CONSTQSTR(node->ns->prefix, node->name));
2947 case XML_TEXT_NODE:
2948 return(CONSTSTR(BAD_CAST "#text"));
2949 case XML_CDATA_SECTION_NODE:
2950 return(CONSTSTR(BAD_CAST "#cdata-section"));
2951 case XML_ENTITY_NODE:
2952 case XML_ENTITY_REF_NODE:
2953 return(CONSTSTR(node->name));
2954 case XML_PI_NODE:
2955 return(CONSTSTR(node->name));
2956 case XML_COMMENT_NODE:
2957 return(CONSTSTR(BAD_CAST "#comment"));
2958 case XML_DOCUMENT_NODE:
2959 case XML_HTML_DOCUMENT_NODE:
2960#ifdef LIBXML_DOCB_ENABLED
2961 case XML_DOCB_DOCUMENT_NODE:
2962#endif
2963 return(CONSTSTR(BAD_CAST "#document"));
2964 case XML_DOCUMENT_FRAG_NODE:
2965 return(CONSTSTR(BAD_CAST "#document-fragment"));
2966 case XML_NOTATION_NODE:
2967 return(CONSTSTR(node->name));
2968 case XML_DOCUMENT_TYPE_NODE:
2969 case XML_DTD_NODE:
2970 return(CONSTSTR(node->name));
2971 case XML_NAMESPACE_DECL: {
2972 xmlNsPtr ns = (xmlNsPtr) node;
2973
2974 if (ns->prefix == NULL)
2975 return(CONSTSTR(BAD_CAST "xmlns"));
2976 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2977 }
2978
2979 case XML_ELEMENT_DECL:
2980 case XML_ATTRIBUTE_DECL:
2981 case XML_ENTITY_DECL:
2982 case XML_XINCLUDE_START:
2983 case XML_XINCLUDE_END:
2984 return(NULL);
2985 }
2986 return(NULL);
2987}
2988
2989/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002990 * xmlTextReaderPrefix:
2991 * @reader: the xmlTextReaderPtr used
2992 *
2993 * A shorthand reference to the namespace associated with the node.
2994 *
2995 * Returns the prefix or NULL if not available
2996 */
2997xmlChar *
2998xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002999 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003000 if ((reader == NULL) || (reader->node == NULL))
3001 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003002 if (reader->curnode != NULL)
3003 node = reader->curnode;
3004 else
3005 node = reader->node;
3006 if (node->type == XML_NAMESPACE_DECL) {
3007 xmlNsPtr ns = (xmlNsPtr) node;
3008 if (ns->prefix == NULL)
3009 return(NULL);
3010 return(xmlStrdup(BAD_CAST "xmlns"));
3011 }
3012 if ((node->type != XML_ELEMENT_NODE) &&
3013 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003014 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003015 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003016 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003017 return(NULL);
3018}
3019
3020/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003021 * xmlTextReaderConstPrefix:
3022 * @reader: the xmlTextReaderPtr used
3023 *
3024 * A shorthand reference to the namespace associated with the node.
3025 *
3026 * Returns the prefix or NULL if not available, the string is deallocated
3027 * with the reader.
3028 */
3029const xmlChar *
3030xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3031 xmlNodePtr node;
3032 if ((reader == NULL) || (reader->node == NULL))
3033 return(NULL);
3034 if (reader->curnode != NULL)
3035 node = reader->curnode;
3036 else
3037 node = reader->node;
3038 if (node->type == XML_NAMESPACE_DECL) {
3039 xmlNsPtr ns = (xmlNsPtr) node;
3040 if (ns->prefix == NULL)
3041 return(NULL);
3042 return(CONSTSTR(BAD_CAST "xmlns"));
3043 }
3044 if ((node->type != XML_ELEMENT_NODE) &&
3045 (node->type != XML_ATTRIBUTE_NODE))
3046 return(NULL);
3047 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3048 return(CONSTSTR(node->ns->prefix));
3049 return(NULL);
3050}
3051
3052/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003053 * xmlTextReaderNamespaceUri:
3054 * @reader: the xmlTextReaderPtr used
3055 *
3056 * The URI defining the namespace associated with the node.
3057 *
3058 * Returns the namespace URI or NULL if not available
3059 */
3060xmlChar *
3061xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003062 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003063 if ((reader == NULL) || (reader->node == NULL))
3064 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003065 if (reader->curnode != NULL)
3066 node = reader->curnode;
3067 else
3068 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003069 if (node->type == XML_NAMESPACE_DECL)
3070 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003071 if ((node->type != XML_ELEMENT_NODE) &&
3072 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003073 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003074 if (node->ns != NULL)
3075 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003076 return(NULL);
3077}
3078
3079/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003080 * xmlTextReaderConstNamespaceUri:
3081 * @reader: the xmlTextReaderPtr used
3082 *
3083 * The URI defining the namespace associated with the node.
3084 *
3085 * Returns the namespace URI or NULL if not available, the string
3086 * will be deallocated with the reader
3087 */
3088const xmlChar *
3089xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3090 xmlNodePtr node;
3091 if ((reader == NULL) || (reader->node == NULL))
3092 return(NULL);
3093 if (reader->curnode != NULL)
3094 node = reader->curnode;
3095 else
3096 node = reader->node;
3097 if (node->type == XML_NAMESPACE_DECL)
3098 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3099 if ((node->type != XML_ELEMENT_NODE) &&
3100 (node->type != XML_ATTRIBUTE_NODE))
3101 return(NULL);
3102 if (node->ns != NULL)
3103 return(CONSTSTR(node->ns->href));
3104 return(NULL);
3105}
3106
3107/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003108 * xmlTextReaderBaseUri:
3109 * @reader: the xmlTextReaderPtr used
3110 *
3111 * The base URI of the node.
3112 *
3113 * Returns the base URI or NULL if not available
3114 */
3115xmlChar *
3116xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3117 if ((reader == NULL) || (reader->node == NULL))
3118 return(NULL);
3119 return(xmlNodeGetBase(NULL, reader->node));
3120}
3121
3122/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003123 * xmlTextReaderConstBaseUri:
3124 * @reader: the xmlTextReaderPtr used
3125 *
3126 * The base URI of the node.
3127 *
3128 * Returns the base URI or NULL if not available, the string
3129 * will be deallocated with the reader
3130 */
3131const xmlChar *
3132xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3133 xmlChar *tmp;
3134 const xmlChar *ret;
3135
3136 if ((reader == NULL) || (reader->node == NULL))
3137 return(NULL);
3138 tmp = xmlNodeGetBase(NULL, reader->node);
3139 if (tmp == NULL)
3140 return(NULL);
3141 ret = CONSTSTR(tmp);
3142 xmlFree(tmp);
3143 return(ret);
3144}
3145
3146/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003147 * xmlTextReaderDepth:
3148 * @reader: the xmlTextReaderPtr used
3149 *
3150 * The depth of the node in the tree.
3151 *
3152 * Returns the depth or -1 in case of error
3153 */
3154int
3155xmlTextReaderDepth(xmlTextReaderPtr reader) {
3156 if (reader == NULL)
3157 return(-1);
3158 if (reader->node == NULL)
3159 return(0);
3160
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003161 if (reader->curnode != NULL) {
3162 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3163 (reader->curnode->type == XML_NAMESPACE_DECL))
3164 return(reader->depth + 1);
3165 return(reader->depth + 2);
3166 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003167 return(reader->depth);
3168}
3169
3170/**
3171 * xmlTextReaderHasAttributes:
3172 * @reader: the xmlTextReaderPtr used
3173 *
3174 * Whether the node has attributes.
3175 *
3176 * Returns 1 if true, 0 if false, and -1 in case or error
3177 */
3178int
3179xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003180 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003181 if (reader == NULL)
3182 return(-1);
3183 if (reader->node == NULL)
3184 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003185 if (reader->curnode != NULL)
3186 node = reader->curnode;
3187 else
3188 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003189
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003190 if ((node->type == XML_ELEMENT_NODE) &&
3191 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003192 return(1);
3193 /* TODO: handle the xmlDecl */
3194 return(0);
3195}
3196
3197/**
3198 * xmlTextReaderHasValue:
3199 * @reader: the xmlTextReaderPtr used
3200 *
3201 * Whether the node can have a text value.
3202 *
3203 * Returns 1 if true, 0 if false, and -1 in case or error
3204 */
3205int
3206xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003207 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003208 if (reader == NULL)
3209 return(-1);
3210 if (reader->node == NULL)
3211 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003212 if (reader->curnode != NULL)
3213 node = reader->curnode;
3214 else
3215 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003216
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003217 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003218 case XML_ATTRIBUTE_NODE:
3219 case XML_TEXT_NODE:
3220 case XML_CDATA_SECTION_NODE:
3221 case XML_PI_NODE:
3222 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003223 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003224 return(1);
3225 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003226 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003227 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003228 return(0);
3229}
3230
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003231/**
3232 * xmlTextReaderValue:
3233 * @reader: the xmlTextReaderPtr used
3234 *
3235 * Provides the text value of the node if present
3236 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003237 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003238 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003239 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003240xmlChar *
3241xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003242 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003243 if (reader == NULL)
3244 return(NULL);
3245 if (reader->node == NULL)
3246 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003247 if (reader->curnode != NULL)
3248 node = reader->curnode;
3249 else
3250 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003251
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003252 switch (node->type) {
3253 case XML_NAMESPACE_DECL:
3254 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003255 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003256 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003257
3258 if (attr->parent != NULL)
3259 return (xmlNodeListGetString
3260 (attr->parent->doc, attr->children, 1));
3261 else
3262 return (xmlNodeListGetString(NULL, attr->children, 1));
3263 break;
3264 }
3265 case XML_TEXT_NODE:
3266 case XML_CDATA_SECTION_NODE:
3267 case XML_PI_NODE:
3268 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003269 if (node->content != NULL)
3270 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003271 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003272 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003273 }
3274 return(NULL);
3275}
3276
3277/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003278 * xmlTextReaderConstValue:
3279 * @reader: the xmlTextReaderPtr used
3280 *
3281 * Provides the text value of the node if present
3282 *
3283 * Returns the string or NULL if not available. The result will be
3284 * deallocated on the next Read() operation.
3285 */
3286const xmlChar *
3287xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3288 xmlNodePtr node;
3289 if (reader == NULL)
3290 return(NULL);
3291 if (reader->node == NULL)
3292 return(NULL);
3293 if (reader->curnode != NULL)
3294 node = reader->curnode;
3295 else
3296 node = reader->node;
3297
3298 switch (node->type) {
3299 case XML_NAMESPACE_DECL:
3300 return(((xmlNsPtr) node)->href);
3301 case XML_ATTRIBUTE_NODE:{
3302 xmlAttrPtr attr = (xmlAttrPtr) node;
3303
3304 if ((attr->children != NULL) &&
3305 (attr->children->type == XML_TEXT_NODE) &&
3306 (attr->children->next == NULL))
3307 return(attr->children->content);
3308 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003309 if (reader->buffer == NULL)
3310 reader->buffer = xmlBufferCreateSize(100);
3311 if (reader->buffer == NULL) {
3312 xmlGenericError(xmlGenericErrorContext,
3313 "xmlTextReaderSetup : malloc failed\n");
3314 return (NULL);
3315 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003316 reader->buffer->use = 0;
3317 xmlNodeBufGetContent(reader->buffer, node);
3318 return(reader->buffer->content);
3319 }
3320 break;
3321 }
3322 case XML_TEXT_NODE:
3323 case XML_CDATA_SECTION_NODE:
3324 case XML_PI_NODE:
3325 case XML_COMMENT_NODE:
3326 return(node->content);
3327 default:
3328 break;
3329 }
3330 return(NULL);
3331}
3332
3333/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003334 * xmlTextReaderIsDefault:
3335 * @reader: the xmlTextReaderPtr used
3336 *
3337 * Whether an Attribute node was generated from the default value
3338 * defined in the DTD or schema.
3339 *
3340 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3341 */
3342int
3343xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3344 if (reader == NULL)
3345 return(-1);
3346 return(0);
3347}
3348
3349/**
3350 * xmlTextReaderQuoteChar:
3351 * @reader: the xmlTextReaderPtr used
3352 *
3353 * The quotation mark character used to enclose the value of an attribute.
3354 *
3355 * Returns " or ' and -1 in case of error
3356 */
3357int
3358xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3359 if (reader == NULL)
3360 return(-1);
3361 /* TODO maybe lookup the attribute value for " first */
3362 return((int) '"');
3363}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003364
3365/**
3366 * xmlTextReaderXmlLang:
3367 * @reader: the xmlTextReaderPtr used
3368 *
3369 * The xml:lang scope within which the node resides.
3370 *
3371 * Returns the xml:lang value or NULL if none exists.
3372 */
3373xmlChar *
3374xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3375 if (reader == NULL)
3376 return(NULL);
3377 if (reader->node == NULL)
3378 return(NULL);
3379 return(xmlNodeGetLang(reader->node));
3380}
3381
Daniel Veillard67df8092002-12-16 22:04:11 +00003382/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003383 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003384 * @reader: the xmlTextReaderPtr used
3385 *
3386 * The xml:lang scope within which the node resides.
3387 *
3388 * Returns the xml:lang value or NULL if none exists.
3389 */
3390const xmlChar *
3391xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3392 xmlChar *tmp;
3393 const xmlChar *ret;
3394
3395 if (reader == NULL)
3396 return(NULL);
3397 if (reader->node == NULL)
3398 return(NULL);
3399 tmp = xmlNodeGetLang(reader->node);
3400 if (tmp == NULL)
3401 return(NULL);
3402 ret = CONSTSTR(tmp);
3403 xmlFree(tmp);
3404 return(ret);
3405}
3406
3407/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003408 * xmlTextReaderConstString:
3409 * @reader: the xmlTextReaderPtr used
3410 * @str: the string to intern.
3411 *
3412 * Get an interned string from the reader, allows for example to
3413 * speedup string name comparisons
3414 *
3415 * Returns an interned copy of the string or NULL in case of error. The
3416 * string will be deallocated with the reader.
3417 */
3418const xmlChar *
3419xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3420 if (reader == NULL)
3421 return(NULL);
3422 return(CONSTSTR(str));
3423}
3424
3425/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003426 * xmlTextReaderNormalization:
3427 * @reader: the xmlTextReaderPtr used
3428 *
3429 * The value indicating whether to normalize white space and attribute values.
3430 * Since attribute value and end of line normalizations are a MUST in the XML
3431 * specification only the value true is accepted. The broken bahaviour of
3432 * accepting out of range character entities like &#0; is of course not
3433 * supported either.
3434 *
3435 * Returns 1 or -1 in case of error.
3436 */
3437int
3438xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3439 if (reader == NULL)
3440 return(-1);
3441 return(1);
3442}
3443
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003444/************************************************************************
3445 * *
3446 * Extensions to the base APIs *
3447 * *
3448 ************************************************************************/
3449
3450/**
3451 * xmlTextReaderSetParserProp:
3452 * @reader: the xmlTextReaderPtr used
3453 * @prop: the xmlParserProperties to set
3454 * @value: usually 0 or 1 to (de)activate it
3455 *
3456 * Change the parser processing behaviour by changing some of its internal
3457 * properties. Note that some properties can only be changed before any
3458 * read has been done.
3459 *
3460 * Returns 0 if the call was successful, or -1 in case of error
3461 */
3462int
3463xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3464 xmlParserProperties p = (xmlParserProperties) prop;
3465 xmlParserCtxtPtr ctxt;
3466
3467 if ((reader == NULL) || (reader->ctxt == NULL))
3468 return(-1);
3469 ctxt = reader->ctxt;
3470
3471 switch (p) {
3472 case XML_PARSER_LOADDTD:
3473 if (value != 0) {
3474 if (ctxt->loadsubset == 0) {
3475 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3476 return(-1);
3477 ctxt->loadsubset = XML_DETECT_IDS;
3478 }
3479 } else {
3480 ctxt->loadsubset = 0;
3481 }
3482 return(0);
3483 case XML_PARSER_DEFAULTATTRS:
3484 if (value != 0) {
3485 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3486 } else {
3487 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3488 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3489 }
3490 return(0);
3491 case XML_PARSER_VALIDATE:
3492 if (value != 0) {
3493 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003494 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003495 } else {
3496 ctxt->validate = 0;
3497 }
3498 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003499 case XML_PARSER_SUBST_ENTITIES:
3500 if (value != 0) {
3501 ctxt->replaceEntities = 1;
3502 } else {
3503 ctxt->replaceEntities = 0;
3504 }
3505 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003506 }
3507 return(-1);
3508}
3509
3510/**
3511 * xmlTextReaderGetParserProp:
3512 * @reader: the xmlTextReaderPtr used
3513 * @prop: the xmlParserProperties to get
3514 *
3515 * Read the parser internal property.
3516 *
3517 * Returns the value, usually 0 or 1, or -1 in case of error.
3518 */
3519int
3520xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3521 xmlParserProperties p = (xmlParserProperties) prop;
3522 xmlParserCtxtPtr ctxt;
3523
3524 if ((reader == NULL) || (reader->ctxt == NULL))
3525 return(-1);
3526 ctxt = reader->ctxt;
3527
3528 switch (p) {
3529 case XML_PARSER_LOADDTD:
3530 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3531 return(1);
3532 return(0);
3533 case XML_PARSER_DEFAULTATTRS:
3534 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3535 return(1);
3536 return(0);
3537 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003538 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003539 case XML_PARSER_SUBST_ENTITIES:
3540 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003541 }
3542 return(-1);
3543}
3544
Daniel Veillarde18fc182002-12-28 22:56:33 +00003545/**
3546 * xmlTextReaderCurrentNode:
3547 * @reader: the xmlTextReaderPtr used
3548 *
3549 * Hacking interface allowing to get the xmlNodePtr correponding to the
3550 * current node being accessed by the xmlTextReader. This is dangerous
3551 * because the underlying node may be destroyed on the next Reads.
3552 *
3553 * Returns the xmlNodePtr or NULL in case of error.
3554 */
3555xmlNodePtr
3556xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3557 if (reader == NULL)
3558 return(NULL);
3559
3560 if (reader->curnode != NULL)
3561 return(reader->curnode);
3562 return(reader->node);
3563}
3564
3565/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003566 * xmlTextReaderPreserve:
3567 * @reader: the xmlTextReaderPtr used
3568 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003569 * This tells the XML Reader to preserve the current node.
3570 * The caller must also use xmlTextReaderCurrentDoc() to
3571 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003572 *
3573 * Returns the xmlNodePtr or NULL in case of error.
3574 */
3575xmlNodePtr
3576xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3577 xmlNodePtr cur, parent;
3578
3579 if (reader == NULL)
3580 return(NULL);
3581
3582 if (reader->curnode != NULL)
3583 cur = reader->curnode;
3584 else
3585 cur = reader->node;
3586 if (cur == NULL)
3587 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003588
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003589 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003590 cur->extra |= NODE_IS_PRESERVED;
3591 cur->extra |= NODE_IS_SPRESERVED;
3592 }
3593 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003594
3595 parent = cur->parent;;
3596 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003597 if (parent->type == XML_ELEMENT_NODE)
3598 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003599 parent = parent->parent;
3600 }
3601 return(cur);
3602}
3603
Daniel Veillard1e906612003-12-05 14:57:46 +00003604#ifdef LIBXML_PATTERN_ENABLED
3605/**
3606 * xmlTextReaderPreservePattern:
3607 * @reader: the xmlTextReaderPtr used
3608 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003609 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003610 *
3611 * This tells the XML Reader to preserve all nodes matched by the
3612 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3613 * keep an handle on the resulting document once parsing has finished
3614 *
3615 * Returns a positive number in case of success and -1 in case of error
3616 */
3617int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003618xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3619 const xmlChar **namespaces)
3620{
Daniel Veillard1e906612003-12-05 14:57:46 +00003621 xmlPatternPtr comp;
3622
3623 if ((reader == NULL) || (pattern == NULL))
3624 return(-1);
3625
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003626 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003627 if (comp == NULL)
3628 return(-1);
3629
3630 if (reader->patternMax <= 0) {
3631 reader->patternMax = 4;
3632 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3633 sizeof(reader->patternTab[0]));
3634 if (reader->patternTab == NULL) {
3635 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3636 return (-1);
3637 }
3638 }
3639 if (reader->patternNr >= reader->patternMax) {
3640 xmlPatternPtr *tmp;
3641 reader->patternMax *= 2;
3642 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3643 reader->patternMax *
3644 sizeof(reader->patternTab[0]));
3645 if (tmp == NULL) {
3646 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3647 reader->patternMax /= 2;
3648 return (-1);
3649 }
3650 reader->patternTab = tmp;
3651 }
3652 reader->patternTab[reader->patternNr] = comp;
3653 return(reader->patternNr++);
3654}
3655#endif
3656
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003657/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003658 * xmlTextReaderCurrentDoc:
3659 * @reader: the xmlTextReaderPtr used
3660 *
3661 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003662 * current document being accessed by the xmlTextReader.
3663 * NOTE: as a result of this call, the reader will not destroy the
3664 * associated XML document and calling xmlFreeDoc() on the result
3665 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003666 *
3667 * Returns the xmlDocPtr or NULL in case of error.
3668 */
3669xmlDocPtr
3670xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003671 if (reader == NULL)
3672 return(NULL);
3673 if (reader->doc != NULL)
3674 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003675 if ((reader == NULL) || (reader->ctxt == NULL) ||
3676 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003677 return(NULL);
3678
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003679 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003680 return(reader->ctxt->myDoc);
3681}
3682
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003683#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003684/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003685 * xmlTextReaderRelaxNGSetSchema:
3686 * @reader: the xmlTextReaderPtr used
3687 * @schema: a precompiled RelaxNG schema
3688 *
3689 * Use RelaxNG to validate the document as it is processed.
3690 * Activation is only possible before the first Read().
3691 * if @schema is NULL, then RelaxNG validation is desactivated.
3692 @ The @schema should not be freed until the reader is deallocated
3693 * or its use has been deactivated.
3694 *
3695 * Returns 0 in case the RelaxNG validation could be (des)activated and
3696 * -1 in case of error.
3697 */
3698int
3699xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3700 if (schema == NULL) {
3701 if (reader->rngSchemas != NULL) {
3702 xmlRelaxNGFree(reader->rngSchemas);
3703 reader->rngSchemas = NULL;
3704 }
3705 if (reader->rngValidCtxt != NULL) {
3706 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3707 reader->rngValidCtxt = NULL;
3708 }
3709 return(0);
3710 }
3711 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3712 return(-1);
3713 if (reader->rngSchemas != NULL) {
3714 xmlRelaxNGFree(reader->rngSchemas);
3715 reader->rngSchemas = NULL;
3716 }
3717 if (reader->rngValidCtxt != NULL) {
3718 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3719 reader->rngValidCtxt = NULL;
3720 }
3721 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3722 if (reader->rngValidCtxt == NULL)
3723 return(-1);
3724 if (reader->errorFunc != NULL) {
3725 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3726 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3727 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3728 reader->errorFuncArg);
3729 }
3730 reader->rngValidErrors = 0;
3731 reader->rngFullNode = NULL;
3732 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3733 return(0);
3734}
3735
3736/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003737 * xmlTextReaderRelaxNGValidate:
3738 * @reader: the xmlTextReaderPtr used
3739 * @rng: the path to a RelaxNG schema or NULL
3740 *
3741 * Use RelaxNG to validate the document as it is processed.
3742 * Activation is only possible before the first Read().
3743 * if @rng is NULL, then RelaxNG validation is desactivated.
3744 *
3745 * Returns 0 in case the RelaxNG validation could be (des)activated and
3746 * -1 in case of error.
3747 */
3748int
3749xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3750 xmlRelaxNGParserCtxtPtr ctxt;
3751
3752 if (reader == NULL)
3753 return(-1);
3754
3755 if (rng == NULL) {
3756 if (reader->rngSchemas != NULL) {
3757 xmlRelaxNGFree(reader->rngSchemas);
3758 reader->rngSchemas = NULL;
3759 }
3760 if (reader->rngValidCtxt != NULL) {
3761 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3762 reader->rngValidCtxt = NULL;
3763 }
3764 return(0);
3765 }
3766 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3767 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003768 if (reader->rngSchemas != NULL) {
3769 xmlRelaxNGFree(reader->rngSchemas);
3770 reader->rngSchemas = NULL;
3771 }
3772 if (reader->rngValidCtxt != NULL) {
3773 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3774 reader->rngValidCtxt = NULL;
3775 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003776 ctxt = xmlRelaxNGNewParserCtxt(rng);
3777 if (reader->errorFunc != NULL) {
3778 xmlRelaxNGSetParserErrors(ctxt,
3779 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3780 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3781 reader->errorFuncArg);
3782 }
3783 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3784 xmlRelaxNGFreeParserCtxt(ctxt);
3785 if (reader->rngSchemas == NULL)
3786 return(-1);
3787 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3788 if (reader->rngValidCtxt == NULL)
3789 return(-1);
3790 if (reader->errorFunc != NULL) {
3791 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3792 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3793 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3794 reader->errorFuncArg);
3795 }
3796 reader->rngValidErrors = 0;
3797 reader->rngFullNode = NULL;
3798 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3799 return(0);
3800}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003801#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003802
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003803/************************************************************************
3804 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003805 * Error Handling Extensions *
3806 * *
3807 ************************************************************************/
3808
3809/* helper to build a xmlMalloc'ed string from a format and va_list */
3810static char *
3811xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3812 int size;
3813 int chars;
3814 char *larger;
3815 char *str;
3816
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003817 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003818 if (str == NULL) {
3819 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3820 return NULL;
3821 }
3822
3823 size = 150;
3824
3825 while (1) {
3826 chars = vsnprintf(str, size, msg, ap);
3827 if ((chars > -1) && (chars < size))
3828 break;
3829 if (chars > -1)
3830 size += chars + 1;
3831 else
3832 size += 100;
3833 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3834 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3835 xmlFree(str);
3836 return NULL;
3837 }
3838 str = larger;
3839 }
3840
3841 return str;
3842}
3843
Daniel Veillard417be3a2003-01-20 21:26:34 +00003844/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003845 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003846 * @locator: the xmlTextReaderLocatorPtr used
3847 *
3848 * Obtain the line number for the given locator.
3849 *
3850 * Returns the line number or -1 in case of error.
3851 */
3852int
3853xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3854 /* we know that locator is a xmlParserCtxtPtr */
3855 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3856 int ret = -1;
3857
3858 if (ctx->node != NULL) {
3859 ret = xmlGetLineNo(ctx->node);
3860 }
3861 else {
3862 /* inspired from error.c */
3863 xmlParserInputPtr input;
3864 input = ctx->input;
3865 if ((input->filename == NULL) && (ctx->inputNr > 1))
3866 input = ctx->inputTab[ctx->inputNr - 2];
3867 if (input != NULL) {
3868 ret = input->line;
3869 }
3870 else {
3871 ret = -1;
3872 }
3873 }
3874
3875 return ret;
3876}
3877
3878/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003879 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003880 * @locator: the xmlTextReaderLocatorPtr used
3881 *
3882 * Obtain the base URI for the given locator.
3883 *
3884 * Returns the base URI or NULL in case of error.
3885 */
3886xmlChar *
3887xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3888 /* we know that locator is a xmlParserCtxtPtr */
3889 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3890 xmlChar *ret = NULL;
3891
3892 if (ctx->node != NULL) {
3893 ret = xmlNodeGetBase(NULL,ctx->node);
3894 }
3895 else {
3896 /* inspired from error.c */
3897 xmlParserInputPtr input;
3898 input = ctx->input;
3899 if ((input->filename == NULL) && (ctx->inputNr > 1))
3900 input = ctx->inputTab[ctx->inputNr - 2];
3901 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003902 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003903 }
3904 else {
3905 ret = NULL;
3906 }
3907 }
3908
3909 return ret;
3910}
3911
Daniel Veillard26f70262003-01-16 22:45:08 +00003912static void
William M. Brack899e64a2003-09-26 18:03:42 +00003913xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003914 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3915 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3916
William M. Bracka3215c72004-07-31 16:24:01 +00003917 if (str != NULL) {
3918 if (reader->errorFunc)
Daniel Veillard26f70262003-01-16 22:45:08 +00003919 reader->errorFunc(reader->errorFuncArg,
3920 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003921 severity,
3922 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003923 xmlFree(str);
3924 }
3925}
3926
3927static void
William M. Brack93d004f2004-02-03 00:14:10 +00003928xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3929 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3930 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3931
3932 if (error && reader->sErrorFunc) {
3933 reader->sErrorFunc(reader->errorFuncArg,
3934 (xmlErrorPtr) error);
3935 }
3936}
3937
3938static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003939xmlTextReaderError(void *ctxt, const char *msg, ...) {
3940 va_list ap;
3941
3942 va_start(ap,msg);
3943 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003944 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003945 xmlTextReaderBuildMessage(msg,ap));
3946 va_end(ap);
3947
3948}
3949
3950static void
3951xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3952 va_list ap;
3953
3954 va_start(ap,msg);
3955 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003956 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003957 xmlTextReaderBuildMessage(msg,ap));
3958 va_end(ap);
3959}
3960
3961static void
3962xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3963 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003964 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003965
Daniel Veillard417be3a2003-01-20 21:26:34 +00003966 if ((len > 1) && (msg[len - 2] != ':')) {
3967 /*
3968 * some callbacks only report locator information:
3969 * skip them (mimicking behaviour in error.c)
3970 */
3971 va_start(ap,msg);
3972 xmlTextReaderGenericError(ctxt,
3973 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3974 xmlTextReaderBuildMessage(msg,ap));
3975 va_end(ap);
3976 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003977}
3978
3979static void
3980xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3981 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003982 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003983
Daniel Veillard417be3a2003-01-20 21:26:34 +00003984 if ((len != 0) && (msg[len - 1] != ':')) {
3985 /*
3986 * some callbacks only report locator information:
3987 * skip them (mimicking behaviour in error.c)
3988 */
3989 va_start(ap,msg);
3990 xmlTextReaderGenericError(ctxt,
3991 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3992 xmlTextReaderBuildMessage(msg,ap));
3993 va_end(ap);
3994 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003995}
3996
3997/**
3998 * xmlTextReaderSetErrorHandler:
3999 * @reader: the xmlTextReaderPtr used
4000 * @f: the callback function to call on error and warnings
4001 * @arg: a user argument to pass to the callback function
4002 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004003 * Register a callback function that will be called on error and warnings.
4004 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004005 * If @f is NULL, the default error and warning handlers are restored.
4006 */
4007void
4008xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4009 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004010 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004011 if (f != NULL) {
4012 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00004013 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004014 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4015 reader->ctxt->sax->warning = xmlTextReaderWarning;
4016 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4017 reader->errorFunc = f;
William M. Brack9f797ab2004-07-28 07:40:12 +00004018 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004019 reader->errorFuncArg = arg;
4020 }
4021 else {
4022 /* restore defaults */
4023 reader->ctxt->sax->error = xmlParserError;
4024 reader->ctxt->vctxt.error = xmlParserValidityError;
4025 reader->ctxt->sax->warning = xmlParserWarning;
4026 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4027 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004028 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004029 reader->errorFuncArg = NULL;
4030 }
4031}
4032
Daniel Veillard417be3a2003-01-20 21:26:34 +00004033/**
William M. Brack93d004f2004-02-03 00:14:10 +00004034* xmlTextReaderSetStructuredErrorHandler:
4035 * @reader: the xmlTextReaderPtr used
4036 * @f: the callback function to call on error and warnings
4037 * @arg: a user argument to pass to the callback function
4038 *
4039 * Register a callback function that will be called on error and warnings.
4040 *
4041 * If @f is NULL, the default error and warning handlers are restored.
4042 */
4043void
4044xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4045 xmlStructuredErrorFunc f,
4046 void *arg) {
4047 if (f != NULL) {
William M. Brack9f797ab2004-07-28 07:40:12 +00004048 reader->ctxt->sax->error = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004049 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4050 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4051 reader->ctxt->sax->warning = xmlTextReaderWarning;
4052 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4053 reader->sErrorFunc = f;
4054 reader->errorFunc = NULL;
4055 reader->errorFuncArg = arg;
4056 }
4057 else {
4058 /* restore defaults */
4059 reader->ctxt->sax->error = xmlParserError;
4060 reader->ctxt->sax->serror = NULL;
4061 reader->ctxt->vctxt.error = xmlParserValidityError;
4062 reader->ctxt->sax->warning = xmlParserWarning;
4063 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4064 reader->errorFunc = NULL;
4065 reader->sErrorFunc = NULL;
4066 reader->errorFuncArg = NULL;
4067 }
4068}
4069
4070/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004071 * xmlTextReaderIsValid:
4072 * @reader: the xmlTextReaderPtr used
4073 *
4074 * Retrieve the validity status from the parser context
4075 *
4076 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4077 */
4078int
4079xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004080 if (reader == NULL) return(-1);
4081#ifdef LIBXML_SCHEMAS_ENABLED
4082 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4083 return(reader->rngValidErrors == 0);
4084#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004085 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004086 return(reader->ctxt->valid);
4087 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004088}
4089
4090/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004091 * xmlTextReaderGetErrorHandler:
4092 * @reader: the xmlTextReaderPtr used
4093 * @f: the callback function or NULL is no callback has been registered
4094 * @arg: a user argument
4095 *
4096 * Retrieve the error callback function and user argument.
4097 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004098void
4099xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4100 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004101 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004102 *f = reader->errorFunc;
4103 *arg = reader->errorFuncArg;
4104}
4105
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004106
4107/************************************************************************
4108 * *
4109 * New set (2.6.0) of simpler and more flexible APIs *
4110 * *
4111 ************************************************************************/
4112
4113/**
4114 * xmlTextReaderSetup:
4115 * @reader: an XML reader
4116 * @URL: the base URL to use for the document
4117 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004118 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004119 * @reuse: keep the context for reuse
4120 *
4121 * Setup an XML reader with new options
4122 *
4123 * Returns 0 in case of success and -1 in case of error.
4124 */
4125static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004126xmlTextReaderSetup(xmlTextReaderPtr reader,
4127 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004128 const char *encoding, int options)
4129{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004130 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004131 return (-1);
4132
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004133 reader->doc = NULL;
4134 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004135 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004136 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004137 if ((input != NULL) && (reader->input != NULL) &&
4138 (reader->allocs & XML_TEXTREADER_INPUT)) {
4139 xmlFreeParserInputBuffer(reader->input);
4140 reader->input = NULL;
4141 reader->allocs -= XML_TEXTREADER_INPUT;
4142 }
4143 if (input != NULL) {
4144 reader->input = input;
4145 reader->allocs |= XML_TEXTREADER_INPUT;
4146 }
4147 if (reader->buffer == NULL)
4148 reader->buffer = xmlBufferCreateSize(100);
4149 if (reader->buffer == NULL) {
4150 xmlGenericError(xmlGenericErrorContext,
4151 "xmlTextReaderSetup : malloc failed\n");
4152 return (-1);
4153 }
4154 if (reader->sax == NULL)
4155 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4156 if (reader->sax == NULL) {
4157 xmlGenericError(xmlGenericErrorContext,
4158 "xmlTextReaderSetup : malloc failed\n");
4159 return (-1);
4160 }
4161 xmlSAXVersion(reader->sax, 2);
4162 reader->startElement = reader->sax->startElement;
4163 reader->sax->startElement = xmlTextReaderStartElement;
4164 reader->endElement = reader->sax->endElement;
4165 reader->sax->endElement = xmlTextReaderEndElement;
4166#ifdef LIBXML_SAX1_ENABLED
4167 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4168#endif /* LIBXML_SAX1_ENABLED */
4169 reader->startElementNs = reader->sax->startElementNs;
4170 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4171 reader->endElementNs = reader->sax->endElementNs;
4172 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4173#ifdef LIBXML_SAX1_ENABLED
4174 } else {
4175 reader->startElementNs = NULL;
4176 reader->endElementNs = NULL;
4177 }
4178#endif /* LIBXML_SAX1_ENABLED */
4179 reader->characters = reader->sax->characters;
4180 reader->sax->characters = xmlTextReaderCharacters;
4181 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4182 reader->cdataBlock = reader->sax->cdataBlock;
4183 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4184
4185 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4186 reader->node = NULL;
4187 reader->curnode = NULL;
4188 if (input != NULL) {
4189 if (reader->input->buffer->use < 4) {
4190 xmlParserInputBufferRead(input, 4);
4191 }
4192 if (reader->ctxt == NULL) {
4193 if (reader->input->buffer->use >= 4) {
4194 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4195 (const char *) reader->input->buffer->content, 4, URL);
4196 reader->base = 0;
4197 reader->cur = 4;
4198 } else {
4199 reader->ctxt =
4200 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4201 reader->base = 0;
4202 reader->cur = 0;
4203 }
4204 } else {
4205 xmlParserInputPtr inputStream;
4206 xmlParserInputBufferPtr buf;
4207 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4208
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004209 xmlCtxtReset(reader->ctxt);
4210 buf = xmlAllocParserInputBuffer(enc);
4211 if (buf == NULL) return(-1);
4212 inputStream = xmlNewInputStream(reader->ctxt);
4213 if (inputStream == NULL) {
4214 xmlFreeParserInputBuffer(buf);
4215 return(-1);
4216 }
4217
4218 if (URL == NULL)
4219 inputStream->filename = NULL;
4220 else
4221 inputStream->filename = (char *)
4222 xmlCanonicPath((const xmlChar *) URL);
4223 inputStream->buf = buf;
4224 inputStream->base = inputStream->buf->buffer->content;
4225 inputStream->cur = inputStream->buf->buffer->content;
4226 inputStream->end =
4227 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4228
4229 inputPush(reader->ctxt, inputStream);
4230 reader->cur = 0;
4231 }
4232 if (reader->ctxt == NULL) {
4233 xmlGenericError(xmlGenericErrorContext,
4234 "xmlTextReaderSetup : malloc failed\n");
4235 return (-1);
4236 }
4237 }
4238 if (reader->dict != NULL) {
4239 if (reader->ctxt->dict != NULL) {
4240 if (reader->dict != reader->ctxt->dict) {
4241 xmlDictFree(reader->dict);
4242 reader->dict = reader->ctxt->dict;
4243 }
4244 } else {
4245 reader->ctxt->dict = reader->dict;
4246 }
4247 } else {
4248 if (reader->ctxt->dict == NULL)
4249 reader->ctxt->dict = xmlDictCreate();
4250 reader->dict = reader->ctxt->dict;
4251 }
4252 reader->ctxt->_private = reader;
4253 reader->ctxt->linenumbers = 1;
4254 reader->ctxt->dictNames = 1;
4255 /*
4256 * use the parser dictionnary to allocate all elements and attributes names
4257 */
4258 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00004259 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004260
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004261#ifdef LIBXML_XINCLUDE_ENABLED
4262 if (reader->xincctxt != NULL) {
4263 xmlXIncludeFreeContext(reader->xincctxt);
4264 reader->xincctxt = NULL;
4265 }
4266 if (options & XML_PARSE_XINCLUDE) {
4267 reader->xinclude = 1;
4268 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4269 options -= XML_PARSE_XINCLUDE;
4270 } else
4271 reader->xinclude = 0;
4272 reader->in_xinclude = 0;
4273#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004274#ifdef LIBXML_PATTERN_ENABLED
4275 if (reader->patternTab == NULL) {
4276 reader->patternNr = 0;
4277 reader->patternMax = 0;
4278 }
4279 while (reader->patternNr > 0) {
4280 reader->patternNr--;
4281 if (reader->patternTab[reader->patternNr] != NULL) {
4282 xmlFreePattern(reader->patternTab[reader->patternNr]);
4283 reader->patternTab[reader->patternNr] = NULL;
4284 }
4285 }
4286#endif
4287
Daniel Veillardc36965d2003-12-02 10:28:48 +00004288 if (options & XML_PARSE_DTDVALID)
4289 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4290
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004291 xmlCtxtUseOptions(reader->ctxt, options);
4292 if (encoding != NULL) {
4293 xmlCharEncodingHandlerPtr hdlr;
4294
4295 hdlr = xmlFindCharEncodingHandler(encoding);
4296 if (hdlr != NULL)
4297 xmlSwitchToEncoding(reader->ctxt, hdlr);
4298 }
4299 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4300 (reader->ctxt->input->filename == NULL))
4301 reader->ctxt->input->filename = (char *)
4302 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004303
4304 reader->doc = NULL;
4305
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004306 return (0);
4307}
4308
4309/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004310 * xmlReaderWalker:
4311 * @doc: a preparsed document
4312 *
4313 * Create an xmltextReader for a preparsed document.
4314 *
4315 * Returns the new reader or NULL in case of error.
4316 */
4317xmlTextReaderPtr
4318xmlReaderWalker(xmlDocPtr doc)
4319{
4320 xmlTextReaderPtr ret;
4321
4322 if (doc == NULL)
4323 return(NULL);
4324
4325 ret = xmlMalloc(sizeof(xmlTextReader));
4326 if (ret == NULL) {
4327 xmlGenericError(xmlGenericErrorContext,
4328 "xmlNewTextReader : malloc failed\n");
4329 return(NULL);
4330 }
4331 memset(ret, 0, sizeof(xmlTextReader));
4332 ret->entNr = 0;
4333 ret->input = NULL;
4334 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4335 ret->node = NULL;
4336 ret->curnode = NULL;
4337 ret->base = 0;
4338 ret->cur = 0;
4339 ret->allocs = XML_TEXTREADER_CTXT;
4340 ret->doc = doc;
4341 ret->state = XML_TEXTREADER_START;
4342 ret->dict = xmlDictCreate();
4343 return(ret);
4344}
4345
4346/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004347 * xmlReaderForDoc:
4348 * @cur: a pointer to a zero terminated string
4349 * @URL: the base URL to use for the document
4350 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004351 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004352 *
4353 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004354 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004355 *
4356 * Returns the new reader or NULL in case of error.
4357 */
4358xmlTextReaderPtr
4359xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4360 int options)
4361{
4362 int len;
4363
4364 if (cur == NULL)
4365 return (NULL);
4366 len = xmlStrlen(cur);
4367
4368 return (xmlReaderForMemory
4369 ((const char *) cur, len, URL, encoding, options));
4370}
4371
4372/**
4373 * xmlReaderForFile:
4374 * @filename: a file or URL
4375 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004376 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004377 *
4378 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004379 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004380 *
4381 * Returns the new reader or NULL in case of error.
4382 */
4383xmlTextReaderPtr
4384xmlReaderForFile(const char *filename, const char *encoding, int options)
4385{
4386 xmlTextReaderPtr reader;
4387
4388 reader = xmlNewTextReaderFilename(filename);
4389 if (reader == NULL)
4390 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004391 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004392 return (reader);
4393}
4394
4395/**
4396 * xmlReaderForMemory:
4397 * @buffer: a pointer to a char array
4398 * @size: the size of the array
4399 * @URL: the base URL to use for the document
4400 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004401 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004402 *
4403 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004404 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004405 *
4406 * Returns the new reader or NULL in case of error.
4407 */
4408xmlTextReaderPtr
4409xmlReaderForMemory(const char *buffer, int size, const char *URL,
4410 const char *encoding, int options)
4411{
4412 xmlTextReaderPtr reader;
4413 xmlParserInputBufferPtr buf;
4414
Daniel Veillard21924522004-02-19 16:37:07 +00004415 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004416 XML_CHAR_ENCODING_NONE);
4417 if (buf == NULL) {
4418 return (NULL);
4419 }
4420 reader = xmlNewTextReader(buf, URL);
4421 if (reader == NULL) {
4422 xmlFreeParserInputBuffer(buf);
4423 return (NULL);
4424 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004425 reader->allocs |= XML_TEXTREADER_INPUT;
4426 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004427 return (reader);
4428}
4429
4430/**
4431 * xmlReaderForFd:
4432 * @fd: an open file descriptor
4433 * @URL: the base URL to use for the document
4434 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004435 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004436 *
4437 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004438 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004439 * NOTE that the file descriptor will not be closed when the
4440 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004441 *
4442 * Returns the new reader or NULL in case of error.
4443 */
4444xmlTextReaderPtr
4445xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4446{
4447 xmlTextReaderPtr reader;
4448 xmlParserInputBufferPtr input;
4449
4450 if (fd < 0)
4451 return (NULL);
4452
4453 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4454 if (input == NULL)
4455 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004456 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004457 reader = xmlNewTextReader(input, URL);
4458 if (reader == NULL) {
4459 xmlFreeParserInputBuffer(input);
4460 return (NULL);
4461 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004462 reader->allocs |= XML_TEXTREADER_INPUT;
4463 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004464 return (reader);
4465}
4466
4467/**
4468 * xmlReaderForIO:
4469 * @ioread: an I/O read function
4470 * @ioclose: an I/O close function
4471 * @ioctx: an I/O handler
4472 * @URL: the base URL to use for the document
4473 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004474 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004475 *
4476 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004477 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004478 *
4479 * Returns the new reader or NULL in case of error.
4480 */
4481xmlTextReaderPtr
4482xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4483 void *ioctx, const char *URL, const char *encoding,
4484 int options)
4485{
4486 xmlTextReaderPtr reader;
4487 xmlParserInputBufferPtr input;
4488
4489 if (ioread == NULL)
4490 return (NULL);
4491
4492 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4493 XML_CHAR_ENCODING_NONE);
4494 if (input == NULL)
4495 return (NULL);
4496 reader = xmlNewTextReader(input, URL);
4497 if (reader == NULL) {
4498 xmlFreeParserInputBuffer(input);
4499 return (NULL);
4500 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004501 reader->allocs |= XML_TEXTREADER_INPUT;
4502 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004503 return (reader);
4504}
4505
4506/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004507 * xmlReaderNewWalker:
4508 * @reader: an XML reader
4509 * @doc: a preparsed document
4510 *
4511 * Setup an xmltextReader to parse a preparsed XML document.
4512 * This reuses the existing @reader xmlTextReader.
4513 *
4514 * Returns 0 in case of success and -1 in case of error
4515 */
4516int
4517xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4518{
4519 if (doc == NULL)
4520 return (-1);
4521 if (reader == NULL)
4522 return (-1);
4523
4524 if (reader->ctxt != NULL) {
4525 xmlCtxtReset(reader->ctxt);
4526 }
4527
4528 reader->entNr = 0;
4529 reader->input = NULL;
4530 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4531 reader->node = NULL;
4532 reader->curnode = NULL;
4533 reader->base = 0;
4534 reader->cur = 0;
4535 reader->allocs = XML_TEXTREADER_CTXT;
4536 reader->doc = doc;
4537 reader->state = XML_TEXTREADER_START;
4538 if (reader->dict == NULL) {
4539 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4540 reader->dict = reader->ctxt->dict;
4541 else
4542 reader->dict = xmlDictCreate();
4543 }
4544 return(0);
4545}
4546
4547/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004548 * xmlReaderNewDoc:
4549 * @reader: an XML reader
4550 * @cur: a pointer to a zero terminated string
4551 * @URL: the base URL to use for the document
4552 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004553 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004554 *
4555 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004556 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004557 * This reuses the existing @reader xmlTextReader.
4558 *
4559 * Returns 0 in case of success and -1 in case of error
4560 */
4561int
4562xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4563 const char *URL, const char *encoding, int options)
4564{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004565
4566 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004567
4568 if (cur == NULL)
4569 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004570 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004571 return (-1);
4572
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004573 len = xmlStrlen(cur);
4574 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4575 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004576}
4577
4578/**
4579 * xmlReaderNewFile:
4580 * @reader: an XML reader
4581 * @filename: a file or URL
4582 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004583 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004584 *
4585 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004586 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004587 * This reuses the existing @reader xmlTextReader.
4588 *
4589 * Returns 0 in case of success and -1 in case of error
4590 */
4591int
4592xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4593 const char *encoding, int options)
4594{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004595 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004596
4597 if (filename == NULL)
4598 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004599 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004600 return (-1);
4601
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004602 input =
4603 xmlParserInputBufferCreateFilename(filename,
4604 XML_CHAR_ENCODING_NONE);
4605 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004606 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004607 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004608}
4609
4610/**
4611 * xmlReaderNewMemory:
4612 * @reader: an XML reader
4613 * @buffer: a pointer to a char array
4614 * @size: the size of the array
4615 * @URL: the base URL to use for the document
4616 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004617 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004618 *
4619 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004620 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004621 * This reuses the existing @reader xmlTextReader.
4622 *
4623 * Returns 0 in case of success and -1 in case of error
4624 */
4625int
4626xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4627 const char *URL, const char *encoding, int options)
4628{
4629 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004630
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004631 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004632 return (-1);
4633 if (buffer == NULL)
4634 return (-1);
4635
Daniel Veillard21924522004-02-19 16:37:07 +00004636 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004637 XML_CHAR_ENCODING_NONE);
4638 if (input == NULL) {
4639 return (-1);
4640 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004641 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004642}
4643
4644/**
4645 * xmlReaderNewFd:
4646 * @reader: an XML reader
4647 * @fd: an open file descriptor
4648 * @URL: the base URL to use for the document
4649 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004650 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004651 *
4652 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004653 * NOTE that the file descriptor will not be closed when the
4654 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004655 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004656 * This reuses the existing @reader xmlTextReader.
4657 *
4658 * Returns 0 in case of success and -1 in case of error
4659 */
4660int
4661xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4662 const char *URL, const char *encoding, int options)
4663{
4664 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004665
4666 if (fd < 0)
4667 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004668 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004669 return (-1);
4670
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004671 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4672 if (input == NULL)
4673 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004674 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004675 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004676}
4677
4678/**
4679 * xmlReaderNewIO:
4680 * @reader: an XML reader
4681 * @ioread: an I/O read function
4682 * @ioclose: an I/O close function
4683 * @ioctx: an I/O handler
4684 * @URL: the base URL to use for the document
4685 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004686 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004687 *
4688 * Setup an xmltextReader to parse an XML document from I/O functions
4689 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004690 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004691 * This reuses the existing @reader xmlTextReader.
4692 *
4693 * Returns 0 in case of success and -1 in case of error
4694 */
4695int
4696xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4697 xmlInputCloseCallback ioclose, void *ioctx,
4698 const char *URL, const char *encoding, int options)
4699{
4700 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004701
4702 if (ioread == NULL)
4703 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004704 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004705 return (-1);
4706
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004707 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4708 XML_CHAR_ENCODING_NONE);
4709 if (input == NULL)
4710 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004711 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004712}
Daniel Veillard26f70262003-01-16 22:45:08 +00004713/************************************************************************
4714 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004715 * Utilities *
4716 * *
4717 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004718#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004719/**
4720 * xmlBase64Decode:
4721 * @in: the input buffer
4722 * @inlen: the size of the input (in), the size read from it (out)
4723 * @to: the output buffer
4724 * @tolen: the size of the output (in), the size written to (out)
4725 *
4726 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004727 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004728 *
4729 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4730 * 2 if there wasn't enough space on the output or -1 in case of error.
4731 */
4732static int
4733xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4734 unsigned char *to, unsigned long *tolen) {
4735 unsigned long incur; /* current index in in[] */
4736 unsigned long inblk; /* last block index in in[] */
4737 unsigned long outcur; /* current index in out[] */
4738 unsigned long inmax; /* size of in[] */
4739 unsigned long outmax; /* size of out[] */
4740 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004741 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004742 int nbintmp; /* number of byte in intmp[] */
4743 int is_ignore; /* cur should be ignored */
4744 int is_end = 0; /* the end of the base64 was found */
4745 int retval = 1;
4746 int i;
4747
4748 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4749 return(-1);
4750
4751 incur = 0;
4752 inblk = 0;
4753 outcur = 0;
4754 inmax = *inlen;
4755 outmax = *tolen;
4756 nbintmp = 0;
4757
4758 while (1) {
4759 if (incur >= inmax)
4760 break;
4761 cur = in[incur++];
4762 is_ignore = 0;
4763 if ((cur >= 'A') && (cur <= 'Z'))
4764 cur = cur - 'A';
4765 else if ((cur >= 'a') && (cur <= 'z'))
4766 cur = cur - 'a' + 26;
4767 else if ((cur >= '0') && (cur <= '9'))
4768 cur = cur - '0' + 52;
4769 else if (cur == '+')
4770 cur = 62;
4771 else if (cur == '/')
4772 cur = 63;
4773 else if (cur == '.')
4774 cur = 0;
4775 else if (cur == '=') /*no op , end of the base64 stream */
4776 is_end = 1;
4777 else {
4778 is_ignore = 1;
4779 if (nbintmp == 0)
4780 inblk = incur;
4781 }
4782
4783 if (!is_ignore) {
4784 int nbouttmp = 3;
4785 int is_break = 0;
4786
4787 if (is_end) {
4788 if (nbintmp == 0)
4789 break;
4790 if ((nbintmp == 1) || (nbintmp == 2))
4791 nbouttmp = 1;
4792 else
4793 nbouttmp = 2;
4794 nbintmp = 3;
4795 is_break = 1;
4796 }
4797 intmp[nbintmp++] = cur;
4798 /*
4799 * if intmp is full, push the 4byte sequence as a 3 byte
4800 * sequence out
4801 */
4802 if (nbintmp == 4) {
4803 nbintmp = 0;
4804 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4805 outtmp[1] =
4806 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4807 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4808 if (outcur + 3 >= outmax) {
4809 retval = 2;
4810 break;
4811 }
4812
4813 for (i = 0; i < nbouttmp; i++)
4814 to[outcur++] = outtmp[i];
4815 inblk = incur;
4816 }
4817
4818 if (is_break) {
4819 retval = 0;
4820 break;
4821 }
4822 }
4823 }
4824
4825 *tolen = outcur;
4826 *inlen = inblk;
4827 return (retval);
4828}
4829
4830/*
4831 * Test routine for the xmlBase64Decode function
4832 */
4833#if 0
4834int main(int argc, char **argv) {
4835 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4836 char output[100];
4837 char output2[100];
4838 char output3[100];
4839 unsigned long inlen = strlen(input);
4840 unsigned long outlen = 100;
4841 int ret;
4842 unsigned long cons, tmp, tmp2, prod;
4843
4844 /*
4845 * Direct
4846 */
4847 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4848
4849 output[outlen] = 0;
4850 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4851
4852 /*
4853 * output chunking
4854 */
4855 cons = 0;
4856 prod = 0;
4857 while (cons < inlen) {
4858 tmp = 5;
4859 tmp2 = inlen - cons;
4860
4861 printf("%ld %ld\n", cons, prod);
4862 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4863 cons += tmp2;
4864 prod += tmp;
4865 printf("%ld %ld\n", cons, prod);
4866 }
4867 output2[outlen] = 0;
4868 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4869
4870 /*
4871 * input chunking
4872 */
4873 cons = 0;
4874 prod = 0;
4875 while (cons < inlen) {
4876 tmp = 100 - prod;
4877 tmp2 = inlen - cons;
4878 if (tmp2 > 5)
4879 tmp2 = 5;
4880
4881 printf("%ld %ld\n", cons, prod);
4882 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4883 cons += tmp2;
4884 prod += tmp;
4885 printf("%ld %ld\n", cons, prod);
4886 }
4887 output3[outlen] = 0;
4888 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4889 return(0);
4890
4891}
4892#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004893#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004894#endif /* LIBXML_READER_ENABLED */