blob: a7e1bf341104477ca3f146bf5993f4fbc5a78d04 [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 Veillard7704fb12003-01-03 16:19:51 +000015 * - provide an API to preserve part of the tree
16 * - Streaming XInclude support
Daniel Veillard067bae52003-01-05 01:27:54 +000017 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000018 * - setting(s) for NoBlanks
19 * - performances and tuning ...
20 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#define IN_LIBXML
22#include "libxml.h"
23
Daniel Veillard81273902003-09-30 00:43:48 +000024#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000026#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000027
28#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#include <libxml/xmlmemory.h>
36#include <libxml/xmlIO.h>
37#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000038#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000039#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000040#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000041#ifdef LIBXML_XINCLUDE_ENABLED
42#include <libxml/xinclude.h>
43#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000047
48/* #define DEBUG_CALLBACKS */
49/* #define DEBUG_READER */
50
51/**
52 * TODO:
53 *
54 * macro to flag unimplemented blocks
55 */
56#define TODO \
57 xmlGenericError(xmlGenericErrorContext, \
58 "Unimplemented block at %s:%d\n", \
59 __FILE__, __LINE__);
60
61#ifdef DEBUG_READER
62#define DUMP_READER xmlTextReaderDebug(reader);
63#else
64#define DUMP_READER
65#endif
66
Daniel Veillarda880b122003-04-21 21:36:41 +000067#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000068/************************************************************************
69 * *
70 * The parser: maps the Text Reader API on top of the existing *
71 * parsing routines building a tree *
72 * *
73 ************************************************************************/
74
75#define XML_TEXTREADER_INPUT 1
76#define XML_TEXTREADER_CTXT 2
77
78typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000079 XML_TEXTREADER_MODE_INITIAL = 0,
80 XML_TEXTREADER_MODE_INTERACTIVE = 1,
81 XML_TEXTREADER_MODE_ERROR = 2,
82 XML_TEXTREADER_MODE_EOF =3,
83 XML_TEXTREADER_MODE_CLOSED = 4,
84 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000085} xmlTextReaderMode;
86
87typedef enum {
88 XML_TEXTREADER_NONE = -1,
89 XML_TEXTREADER_START= 0,
90 XML_TEXTREADER_ELEMENT= 1,
91 XML_TEXTREADER_END= 2,
92 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000093 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000094 XML_TEXTREADER_DONE= 5,
95 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000096} xmlTextReaderState;
97
Daniel Veillardf4e55762003-04-15 23:32:22 +000098typedef enum {
99 XML_TEXTREADER_NOT_VALIDATE = 0,
100 XML_TEXTREADER_VALIDATE_DTD = 1,
101 XML_TEXTREADER_VALIDATE_RNG = 2
102} xmlTextReaderValidate;
103
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000104struct _xmlTextReader {
105 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000106 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000107 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000108 int allocs; /* what structure were deallocated */
109 xmlTextReaderState state;
110 xmlParserCtxtPtr ctxt; /* the parser context */
111 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
112 xmlParserInputBufferPtr input; /* the input */
113 startElementSAXFunc startElement;/* initial SAX callbacks */
114 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000115 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000117 charactersSAXFunc characters;
118 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000119 unsigned int base; /* base of the segment in the input */
120 unsigned int cur; /* current position in the input */
121 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000122 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000123 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000124 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000125 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000126 xmlBufferPtr buffer; /* used to return const xmlChar * */
127 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000128
129 /* entity stack when traversing entities content */
130 xmlNodePtr ent; /* Current Entity Ref Node */
131 int entNr; /* Depth of the entities stack */
132 int entMax; /* Max depth of the entities stack */
133 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000134
135 /* error handling */
136 xmlTextReaderErrorFunc errorFunc; /* callback function */
137 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000138
139#ifdef LIBXML_SCHEMAS_ENABLED
140 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000141 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
142 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
143 int rngValidErrors;/* The number of errors detected */
144 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
145#endif
146#ifdef LIBXML_XINCLUDE_ENABLED
147 /* Handling of XInclude processing */
148 int xinclude; /* is xinclude asked for */
149 const xmlChar * xinclude_name; /* the xinclude name from dict */
150 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
151 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000152#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000153#ifdef LIBXML_PATTERN_ENABLED
154 int patternNr; /* number of preserve patterns */
155 int patternMax; /* max preserve patterns */
156 xmlPatternPtr *patternTab; /* array of preserve patterns */
157#endif
158 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000159 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000160 /* Structured error handling */
161 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000162};
163
Daniel Veillarde8039df2003-10-27 11:25:13 +0000164#define NODE_IS_EMPTY 0x1
165#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000166#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000167
Daniel Veillarde72c5082003-09-19 12:44:05 +0000168/**
169 * CONSTSTR:
170 *
171 * Macro used to return an interned string
172 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000173#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
174#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
175
176static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
177static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000178
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000179/************************************************************************
180 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000181 * Our own version of the freeing routines as we recycle nodes *
182 * *
183 ************************************************************************/
184/**
185 * DICT_FREE:
186 * @str: a string
187 *
188 * Free a string if it is not owned by the "dict" dictionnary in the
189 * current scope
190 */
191#define DICT_FREE(str) \
192 if ((str) && ((!dict) || \
193 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
194 xmlFree((char *)(str));
195
196static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
197static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
198
199/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000200 * xmlFreeID:
201 * @not: A id
202 *
203 * Deallocate the memory used by an id definition
204 */
205static void
206xmlFreeID(xmlIDPtr id) {
207 xmlDictPtr dict = NULL;
208
209 if (id == NULL) return;
210
211 if (id->doc != NULL)
212 dict = id->doc->dict;
213
214 if (id->value != NULL)
215 DICT_FREE(id->value)
216 xmlFree(id);
217}
218
219/**
220 * xmlTextReaderRemoveID:
221 * @doc: the document
222 * @attr: the attribute
223 *
224 * Remove the given attribute from the ID table maintained internally.
225 *
226 * Returns -1 if the lookup failed and 0 otherwise
227 */
228static int
229xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
230 xmlIDTablePtr table;
231 xmlIDPtr id;
232 xmlChar *ID;
233
234 if (doc == NULL) return(-1);
235 if (attr == NULL) return(-1);
236 table = (xmlIDTablePtr) doc->ids;
237 if (table == NULL)
238 return(-1);
239
240 if (attr == NULL)
241 return(-1);
242 ID = xmlNodeListGetString(doc, attr->children, 1);
243 if (ID == NULL)
244 return(-1);
245 id = xmlHashLookup(table, ID);
246 xmlFree(ID);
247 if (id == NULL || id->attr != attr) {
248 return(-1);
249 }
250 id->name = attr->name;
251 id->attr = NULL;
252 return(0);
253}
254
255/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000256 * xmlTextReaderFreeProp:
257 * @reader: the xmlTextReaderPtr used
258 * @cur: the node
259 *
260 * Free a node.
261 */
262static void
263xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
264 xmlDictPtr dict;
265
266 dict = reader->ctxt->dict;
267 if (cur == NULL) return;
268
269 /* Check for ID removal -> leading to invalid references ! */
270 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
271 ((cur->parent->doc->intSubset != NULL) ||
272 (cur->parent->doc->extSubset != NULL))) {
273 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000274 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000275 }
276 if (cur->children != NULL)
277 xmlTextReaderFreeNodeList(reader, cur->children);
278
279 DICT_FREE(cur->name);
280 if ((reader != NULL) && (reader->ctxt != NULL) &&
281 (reader->ctxt->freeAttrsNr < 100)) {
282 cur->next = reader->ctxt->freeAttrs;
283 reader->ctxt->freeAttrs = cur;
284 reader->ctxt->freeAttrsNr++;
285 } else {
286 xmlFree(cur);
287 }
288}
289
290/**
291 * xmlTextReaderFreePropList:
292 * @reader: the xmlTextReaderPtr used
293 * @cur: the first property in the list
294 *
295 * Free a property and all its siblings, all the children are freed too.
296 */
297static void
298xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
299 xmlAttrPtr next;
300 if (cur == NULL) return;
301 while (cur != NULL) {
302 next = cur->next;
303 xmlTextReaderFreeProp(reader, cur);
304 cur = next;
305 }
306}
307
308/**
309 * xmlTextReaderFreeNodeList:
310 * @reader: the xmlTextReaderPtr used
311 * @cur: the first node in the list
312 *
313 * Free a node and all its siblings, this is a recursive behaviour, all
314 * the children are freed too.
315 */
316static void
317xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
318 xmlNodePtr next;
319 xmlDictPtr dict;
320
321 dict = reader->ctxt->dict;
322 if (cur == NULL) return;
323 if (cur->type == XML_NAMESPACE_DECL) {
324 xmlFreeNsList((xmlNsPtr) cur);
325 return;
326 }
327 if ((cur->type == XML_DOCUMENT_NODE) ||
328 (cur->type == XML_HTML_DOCUMENT_NODE)) {
329 xmlFreeDoc((xmlDocPtr) cur);
330 return;
331 }
332 while (cur != NULL) {
333 next = cur->next;
334 /* unroll to speed up freeing the document */
335 if (cur->type != XML_DTD_NODE) {
336
337 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000338 (cur->type != XML_ENTITY_REF_NODE)) {
339 if (cur->children->parent == cur)
340 xmlTextReaderFreeNodeList(reader, cur->children);
341 cur->children = NULL;
342 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000343 if (((cur->type == XML_ELEMENT_NODE) ||
344 (cur->type == XML_XINCLUDE_START) ||
345 (cur->type == XML_XINCLUDE_END)) &&
346 (cur->properties != NULL))
347 xmlTextReaderFreePropList(reader, cur->properties);
348 if ((cur->type != XML_ELEMENT_NODE) &&
349 (cur->type != XML_XINCLUDE_START) &&
350 (cur->type != XML_XINCLUDE_END) &&
351 (cur->type != XML_ENTITY_REF_NODE)) {
352 DICT_FREE(cur->content);
353 }
354 if (((cur->type == XML_ELEMENT_NODE) ||
355 (cur->type == XML_XINCLUDE_START) ||
356 (cur->type == XML_XINCLUDE_END)) &&
357 (cur->nsDef != NULL))
358 xmlFreeNsList(cur->nsDef);
359
360 /*
361 * we don't free element names here they are interned now
362 */
363 if ((cur->type != XML_TEXT_NODE) &&
364 (cur->type != XML_COMMENT_NODE))
365 DICT_FREE(cur->name);
366 if (((cur->type == XML_ELEMENT_NODE) ||
367 (cur->type == XML_TEXT_NODE)) &&
368 (reader != NULL) && (reader->ctxt != NULL) &&
369 (reader->ctxt->freeElemsNr < 100)) {
370 cur->next = reader->ctxt->freeElems;
371 reader->ctxt->freeElems = cur;
372 reader->ctxt->freeElemsNr++;
373 } else {
374 xmlFree(cur);
375 }
376 }
377 cur = next;
378 }
379}
380
381/**
382 * xmlTextReaderFreeNode:
383 * @reader: the xmlTextReaderPtr used
384 * @cur: the node
385 *
386 * Free a node, this is a recursive behaviour, all the children are freed too.
387 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
388 */
389static void
390xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
391 xmlDictPtr dict;
392
393 dict = reader->ctxt->dict;
394 if (cur->type == XML_DTD_NODE) {
395 xmlFreeDtd((xmlDtdPtr) cur);
396 return;
397 }
398 if (cur->type == XML_NAMESPACE_DECL) {
399 xmlFreeNs((xmlNsPtr) cur);
400 return;
401 }
402 if (cur->type == XML_ATTRIBUTE_NODE) {
403 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
404 return;
405 }
406
407 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000408 (cur->type != XML_ENTITY_REF_NODE)) {
409 if (cur->children->parent == cur)
410 xmlTextReaderFreeNodeList(reader, cur->children);
411 cur->children = NULL;
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);
436 if (((cur->type == XML_ELEMENT_NODE) ||
437 (cur->type == XML_TEXT_NODE)) &&
438 (reader != NULL) && (reader->ctxt != NULL) &&
439 (reader->ctxt->freeElemsNr < 100)) {
440 cur->next = reader->ctxt->freeElems;
441 reader->ctxt->freeElems = cur;
442 reader->ctxt->freeElemsNr++;
443 } else {
444 xmlFree(cur);
445 }
446}
447
448/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000449 * xmlTextReaderFreeIDTable:
450 * @table: An id table
451 *
452 * Deallocate the memory used by an ID hash table.
453 */
William M. Brack60f394e2003-11-16 06:25:42 +0000454static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000455xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
456 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
457}
458
459/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000460 * xmlTextReaderFreeDoc:
461 * @reader: the xmlTextReaderPtr used
462 * @cur: pointer to the document
463 *
464 * Free up all the structures used by a document, tree included.
465 */
466static void
467xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
468 xmlDtdPtr extSubset, intSubset;
469
470 if (cur == NULL) return;
471
472 /*
473 * Do this before freeing the children list to avoid ID lookups
474 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000475 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000476 cur->ids = NULL;
477 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
478 cur->refs = NULL;
479 extSubset = cur->extSubset;
480 intSubset = cur->intSubset;
481 if (intSubset == extSubset)
482 extSubset = NULL;
483 if (extSubset != NULL) {
484 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
485 cur->extSubset = NULL;
486 xmlFreeDtd(extSubset);
487 }
488 if (intSubset != NULL) {
489 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
490 cur->intSubset = NULL;
491 xmlFreeDtd(intSubset);
492 }
493
494 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
495
496 if (cur->version != NULL) xmlFree((char *) cur->version);
497 if (cur->name != NULL) xmlFree((char *) cur->name);
498 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
499 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
500 if (cur->URL != NULL) xmlFree((char *) cur->URL);
501 xmlFree(cur);
502}
503
504/************************************************************************
505 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000506 * The reader core parser *
507 * *
508 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000509#ifdef DEBUG_READER
510static void
511xmlTextReaderDebug(xmlTextReaderPtr reader) {
512 if ((reader == NULL) || (reader->ctxt == NULL)) {
513 fprintf(stderr, "xmlTextReader NULL\n");
514 return;
515 }
516 fprintf(stderr, "xmlTextReader: state %d depth %d ",
517 reader->state, reader->depth);
518 if (reader->node == NULL) {
519 fprintf(stderr, "node = NULL\n");
520 } else {
521 fprintf(stderr, "node %s\n", reader->node->name);
522 }
523 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
524 reader->base, reader->cur, reader->ctxt->nodeNr);
525 if (reader->input->buffer == NULL) {
526 fprintf(stderr, "buffer is NULL\n");
527 } else {
528#ifdef LIBXML_DEBUG_ENABLED
529 xmlDebugDumpString(stderr,
530 &reader->input->buffer->content[reader->cur]);
531#endif
532 fprintf(stderr, "\n");
533 }
534}
535#endif
536
537/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000538 * xmlTextReaderEntPush:
539 * @reader: the xmlTextReaderPtr used
540 * @value: the entity reference node
541 *
542 * Pushes a new entity reference node on top of the entities stack
543 *
544 * Returns 0 in case of error, the index in the stack otherwise
545 */
546static int
547xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
548{
549 if (reader->entMax <= 0) {
550 reader->entMax = 10;
551 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
552 sizeof(reader->entTab[0]));
553 if (reader->entTab == NULL) {
554 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
555 return (0);
556 }
557 }
558 if (reader->entNr >= reader->entMax) {
559 reader->entMax *= 2;
560 reader->entTab =
561 (xmlNodePtr *) xmlRealloc(reader->entTab,
562 reader->entMax *
563 sizeof(reader->entTab[0]));
564 if (reader->entTab == NULL) {
565 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
566 return (0);
567 }
568 }
569 reader->entTab[reader->entNr] = value;
570 reader->ent = value;
571 return (reader->entNr++);
572}
573
574/**
575 * xmlTextReaderEntPop:
576 * @reader: the xmlTextReaderPtr used
577 *
578 * Pops the top element entity from the entities stack
579 *
580 * Returns the entity just removed
581 */
582static xmlNodePtr
583xmlTextReaderEntPop(xmlTextReaderPtr reader)
584{
585 xmlNodePtr ret;
586
587 if (reader->entNr <= 0)
588 return (0);
589 reader->entNr--;
590 if (reader->entNr > 0)
591 reader->ent = reader->entTab[reader->entNr - 1];
592 else
593 reader->ent = NULL;
594 ret = reader->entTab[reader->entNr];
595 reader->entTab[reader->entNr] = 0;
596 return (ret);
597}
598
599/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000600 * xmlTextReaderStartElement:
601 * @ctx: the user data (XML parser context)
602 * @fullname: The element name, including namespace prefix
603 * @atts: An array of name/value attributes pairs, NULL terminated
604 *
605 * called when an opening tag has been processed.
606 */
607static void
608xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
609 const xmlChar **atts) {
610 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
611 xmlTextReaderPtr reader = ctxt->_private;
612
613#ifdef DEBUG_CALLBACKS
614 printf("xmlTextReaderStartElement(%s)\n", fullname);
615#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000616 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000617 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000618 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
619 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
620 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000621 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000622 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000623 if (reader != NULL)
624 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000625}
626
627/**
628 * xmlTextReaderEndElement:
629 * @ctx: the user data (XML parser context)
630 * @fullname: The element name, including namespace prefix
631 *
632 * called when an ending tag has been processed.
633 */
634static void
635xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
636 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
637 xmlTextReaderPtr reader = ctxt->_private;
638
639#ifdef DEBUG_CALLBACKS
640 printf("xmlTextReaderEndElement(%s)\n", fullname);
641#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000642 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000643 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000644 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000645}
646
647/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000648 * xmlTextReaderStartElementNs:
649 * @ctx: the user data (XML parser context)
650 * @localname: the local name of the element
651 * @prefix: the element namespace prefix if available
652 * @URI: the element namespace name if available
653 * @nb_namespaces: number of namespace definitions on that node
654 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
655 * @nb_attributes: the number of attributes on that node
656 * nb_defaulted: the number of defaulted attributes.
657 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
658 * attribute values.
659 *
660 * called when an opening tag has been processed.
661 */
662static void
663xmlTextReaderStartElementNs(void *ctx,
664 const xmlChar *localname,
665 const xmlChar *prefix,
666 const xmlChar *URI,
667 int nb_namespaces,
668 const xmlChar **namespaces,
669 int nb_attributes,
670 int nb_defaulted,
671 const xmlChar **attributes)
672{
673 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
674 xmlTextReaderPtr reader = ctxt->_private;
675
676#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000677 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000678#endif
679 if ((reader != NULL) && (reader->startElementNs != NULL)) {
680 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
681 namespaces, nb_attributes, nb_defaulted,
682 attributes);
683 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
684 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
685 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000686 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000687 }
688 if (reader != NULL)
689 reader->state = XML_TEXTREADER_ELEMENT;
690}
691
692/**
693 * xmlTextReaderEndElementNs:
694 * @ctx: the user data (XML parser context)
695 * @localname: the local name of the element
696 * @prefix: the element namespace prefix if available
697 * @URI: the element namespace name if available
698 *
699 * called when an ending tag has been processed.
700 */
701static void
702xmlTextReaderEndElementNs(void *ctx,
703 const xmlChar * localname,
704 const xmlChar * prefix,
705 const xmlChar * URI)
706{
707 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
708 xmlTextReaderPtr reader = ctxt->_private;
709
710#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000711 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000712#endif
713 if ((reader != NULL) && (reader->endElementNs != NULL)) {
714 reader->endElementNs(ctx, localname, prefix, URI);
715 }
716}
717
718
719/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000720 * xmlTextReaderCharacters:
721 * @ctx: the user data (XML parser context)
722 * @ch: a xmlChar string
723 * @len: the number of xmlChar
724 *
725 * receiving some chars from the parser.
726 */
727static void
728xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
729{
730 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
731 xmlTextReaderPtr reader = ctxt->_private;
732
733#ifdef DEBUG_CALLBACKS
734 printf("xmlTextReaderCharacters()\n");
735#endif
736 if ((reader != NULL) && (reader->characters != NULL)) {
737 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000738 }
739}
740
741/**
742 * xmlTextReaderCDataBlock:
743 * @ctx: the user data (XML parser context)
744 * @value: The pcdata content
745 * @len: the block length
746 *
747 * called when a pcdata block has been parsed
748 */
749static void
750xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
751{
752 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
753 xmlTextReaderPtr reader = ctxt->_private;
754
755#ifdef DEBUG_CALLBACKS
756 printf("xmlTextReaderCDataBlock()\n");
757#endif
758 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
759 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000760 }
761}
762
763/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000764 * xmlTextReaderPushData:
765 * @reader: the xmlTextReaderPtr used
766 *
767 * Push data down the progressive parser until a significant callback
768 * got raised.
769 *
770 * Returns -1 in case of failure, 0 otherwise
771 */
772static int
773xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000774 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000775 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000776 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000777
778 if ((reader->input == NULL) || (reader->input->buffer == NULL))
779 return(-1);
780
Daniel Veillardea7751d2002-12-20 00:16:24 +0000781 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000782 reader->state = XML_TEXTREADER_NONE;
783 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000784
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000785 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000786 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000787 /*
788 * Refill the buffer unless we are at the end of the stream
789 */
790 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
791 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000792 if ((val == 0) &&
793 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
794 if (inbuf->use == reader->cur) {
795 reader->mode = XML_TEXTREADER_MODE_EOF;
796 reader->state = oldstate;
797 if ((oldstate != XML_TEXTREADER_START) ||
798 (reader->ctxt->myDoc != NULL))
799 return(val);
800 }
801 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000802 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000803 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000804 if ((oldstate != XML_TEXTREADER_START) ||
805 (reader->ctxt->myDoc != NULL))
806 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000807 } else if (val == 0) {
808 /* mark the end of the stream and process the remains */
809 reader->mode = XML_TEXTREADER_MODE_EOF;
810 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000811 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000812
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000813 } else
814 break;
815 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000816 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000817 * parse by block of CHUNK_SIZE bytes, various tests show that
818 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000819 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000820 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 val = xmlParseChunk(reader->ctxt,
822 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000823 CHUNK_SIZE, 0);
824 reader->cur += CHUNK_SIZE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000825 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000826 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000827 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000828 s = inbuf->use - reader->cur;
829 val = xmlParseChunk(reader->ctxt,
830 (const char *) &inbuf->content[reader->cur],
831 s, 0);
832 reader->cur += s;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000833 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000834 return(-1);
835 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000836 }
837 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000838
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 /*
840 * Discard the consumed input when needed and possible
841 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000842 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000843 if ((reader->cur >= 4096) &&
844 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000845 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000846 if (val >= 0) {
847 reader->cur -= val;
848 }
849 }
850 }
851
852 /*
853 * At the end of the stream signal that the work is done to the Push
854 * parser.
855 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000856 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000857 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000858 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000859 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000860 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000861 s, 1);
862 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000863 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000864 if ((val != 0) && (reader->ctxt->wellFormed == 0))
865 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000866 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000867 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000868 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000869 return(0);
870}
871
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000872#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000873/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000874 * xmlTextReaderValidatePush:
875 * @reader: the xmlTextReaderPtr used
876 *
877 * Push the current node for validation
878 */
879static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000880xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000881 xmlNodePtr node = reader->node;
882
Daniel Veillardf4e55762003-04-15 23:32:22 +0000883 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
884 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
885 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
886 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
887 reader->ctxt->myDoc, node, node->name);
888 } else {
889 /* TODO use the BuildQName interface */
890 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000891
Daniel Veillardf4e55762003-04-15 23:32:22 +0000892 qname = xmlStrdup(node->ns->prefix);
893 qname = xmlStrcat(qname, BAD_CAST ":");
894 qname = xmlStrcat(qname, node->name);
895 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
896 reader->ctxt->myDoc, node, qname);
897 if (qname != NULL)
898 xmlFree(qname);
899 }
900#ifdef LIBXML_SCHEMAS_ENABLED
901 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
902 (reader->rngValidCtxt != NULL)) {
903 int ret;
904
905 if (reader->rngFullNode != NULL) return;
906 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
907 reader->ctxt->myDoc,
908 node);
909 if (ret == 0) {
910 /*
911 * this element requires a full tree
912 */
913 node = xmlTextReaderExpand(reader);
914 if (node == NULL) {
915printf("Expand failed !\n");
916 ret = -1;
917 } else {
918 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
919 reader->ctxt->myDoc,
920 node);
921 reader->rngFullNode = node;
922 }
923 }
924 if (ret != 1)
925 reader->rngValidErrors++;
926#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000927 }
928}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000929
930/**
931 * xmlTextReaderValidateCData:
932 * @reader: the xmlTextReaderPtr used
933 * @data: pointer to the CData
934 * @len: lenght of the CData block in bytes.
935 *
936 * Push some CData for validation
937 */
938static void
939xmlTextReaderValidateCData(xmlTextReaderPtr reader,
940 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000941 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
942 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
943 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
944 data, len);
945#ifdef LIBXML_SCHEMAS_ENABLED
946 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
947 (reader->rngValidCtxt != NULL)) {
948 int ret;
949
950 if (reader->rngFullNode != NULL) return;
951 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
952 if (ret != 1)
953 reader->rngValidErrors++;
954#endif
955 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000956}
957
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000958/**
959 * xmlTextReaderValidatePop:
960 * @reader: the xmlTextReaderPtr used
961 *
962 * Pop the current node from validation
963 */
964static void
965xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
966 xmlNodePtr node = reader->node;
967
Daniel Veillardf4e55762003-04-15 23:32:22 +0000968 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
969 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
970 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
971 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
972 reader->ctxt->myDoc, node, node->name);
973 } else {
974 /* TODO use the BuildQName interface */
975 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000976
Daniel Veillardf4e55762003-04-15 23:32:22 +0000977 qname = xmlStrdup(node->ns->prefix);
978 qname = xmlStrcat(qname, BAD_CAST ":");
979 qname = xmlStrcat(qname, node->name);
980 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
981 reader->ctxt->myDoc, node, qname);
982 if (qname != NULL)
983 xmlFree(qname);
984 }
985#ifdef LIBXML_SCHEMAS_ENABLED
986 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
987 (reader->rngValidCtxt != NULL)) {
988 int ret;
989
990 if (reader->rngFullNode != NULL) {
991 if (node == reader->rngFullNode)
992 reader->rngFullNode = NULL;
993 return;
994 }
995 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
996 reader->ctxt->myDoc,
997 node);
998 if (ret != 1)
999 reader->rngValidErrors++;
1000#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001001 }
1002}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001003
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001004/**
1005 * xmlTextReaderValidateEntity:
1006 * @reader: the xmlTextReaderPtr used
1007 *
1008 * Handle the validation when an entity reference is encountered and
1009 * entity substitution is not activated. As a result the parser interface
1010 * must walk through the entity and do the validation calls
1011 */
1012static void
1013xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1014 xmlNodePtr oldnode = reader->node;
1015 xmlNodePtr node = reader->node;
1016 xmlParserCtxtPtr ctxt = reader->ctxt;
1017
1018 do {
1019 if (node->type == XML_ENTITY_REF_NODE) {
1020 /*
1021 * Case where the underlying tree is not availble, lookup the entity
1022 * and walk it.
1023 */
1024 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1025 (ctxt->sax->getEntity != NULL)) {
1026 node->children = (xmlNodePtr)
1027 ctxt->sax->getEntity(ctxt, node->name);
1028 }
1029
1030 if ((node->children != NULL) &&
1031 (node->children->type == XML_ENTITY_DECL) &&
1032 (node->children->children != NULL)) {
1033 xmlTextReaderEntPush(reader, node);
1034 node = node->children->children;
1035 continue;
1036 } else {
1037 /*
1038 * The error has probably be raised already.
1039 */
1040 if (node == oldnode)
1041 break;
1042 node = node->next;
1043 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001044#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001045 } else if (node->type == XML_ELEMENT_NODE) {
1046 reader->node = node;
1047 xmlTextReaderValidatePush(reader);
1048 } else if ((node->type == XML_TEXT_NODE) ||
1049 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001050 xmlTextReaderValidateCData(reader, node->content,
1051 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001052#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001053 }
1054
1055 /*
1056 * go to next node
1057 */
1058 if (node->children != NULL) {
1059 node = node->children;
1060 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001061 } else if (node->type == XML_ELEMENT_NODE) {
1062 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001063 }
1064 if (node->next != NULL) {
1065 node = node->next;
1066 continue;
1067 }
1068 do {
1069 node = node->parent;
1070 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001071 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001072 if (reader->entNr == 0) {
1073 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001074 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001075 xmlUnlinkNode(tmp);
1076 xmlTextReaderFreeNode(reader, tmp);
1077 } else
1078 break;
1079 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001080 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001081 reader->node = node;
1082 xmlTextReaderValidatePop(reader);
1083 }
1084 if ((node->type == XML_ENTITY_DECL) &&
1085 (reader->ent != NULL) && (reader->ent->children == node)) {
1086 node = xmlTextReaderEntPop(reader);
1087 }
1088 if (node == oldnode)
1089 break;
1090 if (node->next != NULL) {
1091 node = node->next;
1092 break;
1093 }
1094 } while ((node != NULL) && (node != oldnode));
1095 } while ((node != NULL) && (node != oldnode));
1096 reader->node = oldnode;
1097}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001098#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001099
1100
1101/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001102 * xmlTextReaderGetSuccessor:
1103 * @cur: the current node
1104 *
1105 * Get the successor of a node if available.
1106 *
1107 * Returns the successor node or NULL
1108 */
1109static xmlNodePtr
1110xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1111 if (cur == NULL) return(NULL) ; /* ERROR */
1112 if (cur->next != NULL) return(cur->next) ;
1113 do {
1114 cur = cur->parent;
1115 if (cur == NULL) return(NULL);
1116 if (cur->next != NULL) return(cur->next);
1117 } while (cur != NULL);
1118 return(cur);
1119}
1120
1121/**
1122 * xmlTextReaderDoExpand:
1123 * @reader: the xmlTextReaderPtr used
1124 *
1125 * Makes sure that the current node is fully read as well as all its
1126 * descendant. It means the full DOM subtree must be available at the
1127 * end of the call.
1128 *
1129 * Returns 1 if the node was expanded successfully, 0 if there is no more
1130 * nodes to read, or -1 in case of error
1131 */
1132static int
1133xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1134 int val;
1135
1136 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1137 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001138 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001139 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1140
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001141 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1142 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001143 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001144 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001145 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1146 return(1);
1147 val = xmlTextReaderPushData(reader);
1148 if (val < 0)
1149 return(-1);
1150 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1151 return(1);
1152}
1153
1154/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001155 * xmlTextReaderRead:
1156 * @reader: the xmlTextReaderPtr used
1157 *
1158 * Moves the position of the current instance to the next node in
1159 * the stream, exposing its properties.
1160 *
1161 * Returns 1 if the node was read successfully, 0 if there is no more
1162 * nodes to read, or -1 in case of error
1163 */
1164int
1165xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001166 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001167 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001168 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001169
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001170
1171 if (reader == NULL)
1172 return(-1);
1173 if (reader->doc != NULL)
1174 return(xmlTextReaderReadTree(reader));
1175 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001176 return(-1);
1177 if (reader->ctxt->wellFormed != 1)
1178 return(-1);
1179
1180#ifdef DEBUG_READER
1181 fprintf(stderr, "\nREAD ");
1182 DUMP_READER
1183#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001184 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001185 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1186 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001187 /*
1188 * Initial state
1189 */
1190 do {
1191 val = xmlTextReaderPushData(reader);
1192 if (val < 0)
1193 return(-1);
1194 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001195 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1196 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001197 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001198 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001199 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001200 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001201 if (reader->node == NULL)
1202 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001203 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001204 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001205 if (reader->ctxt->myDoc != NULL) {
1206 reader->node = reader->ctxt->myDoc->children;
1207 }
1208 if (reader->node == NULL)
1209 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001210 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001212 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001213 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001214 }
1215 oldstate = reader->state;
1216 olddepth = reader->ctxt->nodeNr;
1217 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001218
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001219get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001220 /*
1221 * If we are not backtracking on ancestors or examined nodes,
1222 * that the parser didn't finished or that we arent at the end
1223 * of stream, continue processing.
1224 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001225 while ((reader->node->next == NULL) &&
1226 (reader->ctxt->nodeNr == olddepth) &&
1227 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001228 (reader->node->children == NULL) ||
1229 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001230 ((reader->node->children != NULL) &&
1231 (reader->node->children->type == XML_TEXT_NODE) &&
1232 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001233 (reader->node->type == XML_DTD_NODE) ||
1234 (reader->node->type == XML_DOCUMENT_NODE) ||
1235 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001236 ((reader->ctxt->node == NULL) ||
1237 (reader->ctxt->node == reader->node) ||
1238 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001239 (reader->ctxt->instate != XML_PARSER_EOF)) {
1240 val = xmlTextReaderPushData(reader);
1241 if (val < 0)
1242 return(-1);
1243 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001244 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001245 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001246 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001247 if ((reader->node->children != NULL) &&
1248 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001249 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001250 (reader->node->type != XML_DTD_NODE)) {
1251 reader->node = reader->node->children;
1252 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001253 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001254 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001255 }
1256 }
1257 if (reader->node->next != NULL) {
1258 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001259 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001260 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001261 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1262#ifdef LIBXML_XINCLUDE_ENABLED
1263 && (reader->in_xinclude <= 0)
1264#endif
1265 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001266 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001267 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001268 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001269#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001270 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001271 (reader->node->type == XML_ELEMENT_NODE))
1272 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001273#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001274 if ((reader->preserves > 0) &&
1275 (reader->node->extra & NODE_IS_SPRESERVED))
1276 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001277 reader->node = reader->node->next;
1278 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001279
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001280 /*
1281 * Cleanup of the old node
1282 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001283 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001284#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001285 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001286#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001287 (reader->entNr == 0) &&
1288 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001289 (reader->node->prev->type != XML_DTD_NODE) &&
1290 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001291 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001292 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001293 xmlUnlinkNode(tmp);
1294 xmlTextReaderFreeNode(reader, tmp);
1295 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001296 }
1297
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001298 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001299 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001300 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001301 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001302 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001303 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001304 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001305 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001306 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001307#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001308 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001309 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001310#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001311 if ((reader->preserves > 0) &&
1312 (reader->node->extra & NODE_IS_SPRESERVED))
1313 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001314 reader->node = reader->node->parent;
1315 if ((reader->node == NULL) ||
1316 (reader->node->type == XML_DOCUMENT_NODE) ||
1317#ifdef LIBXML_DOCB_ENABLED
1318 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1319#endif
1320 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001321 if (reader->mode != XML_TEXTREADER_DONE) {
1322 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1323 reader->mode = XML_TEXTREADER_DONE;
1324 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001325 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001326 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001327
1328 /*
1329 * Cleanup of the old node
1330 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001331 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001332#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001333 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001334#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001335 (reader->entNr == 0) &&
1336 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001337 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001338 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001339 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001340 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001341 }
1342
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001343 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001345 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001346#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001347 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001348#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001349 (reader->entNr == 0) &&
1350 (reader->node->last != NULL) &&
1351 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1352 xmlNodePtr tmp = reader->node->last;
1353 xmlUnlinkNode(tmp);
1354 xmlTextReaderFreeNode(reader, tmp);
1355 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001356 reader->depth--;
1357 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001358
1359node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001360 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001361
1362 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001363 * If we are in the middle of a piece of CDATA make sure it's finished
1364 */
1365 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001366 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001367 ((reader->node->type == XML_TEXT_NODE) ||
1368 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1369 xmlTextReaderExpand(reader);
1370 }
1371
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001372#ifdef LIBXML_XINCLUDE_ENABLED
1373 /*
1374 * Handle XInclude if asked for
1375 */
1376 if ((reader->xinclude) && (reader->node != NULL) &&
1377 (reader->node->type == XML_ELEMENT_NODE) &&
1378 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001379 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1380 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001381 if (reader->xincctxt == NULL) {
1382 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001383 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001384 }
1385 /*
1386 * expand that node and process it
1387 */
1388 xmlTextReaderExpand(reader);
1389 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1390 }
1391 if (reader->node->type == XML_XINCLUDE_START) {
1392 reader->in_xinclude++;
1393 goto get_next_node;
1394 }
1395 if (reader->node->type == XML_XINCLUDE_END) {
1396 reader->in_xinclude--;
1397 goto get_next_node;
1398 }
1399#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001400 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001401 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001402 */
1403 if ((reader->node != NULL) &&
1404 (reader->node->type == XML_ENTITY_REF_NODE) &&
1405 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1406 /*
1407 * Case where the underlying tree is not availble, lookup the entity
1408 * and walk it.
1409 */
1410 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1411 (reader->ctxt->sax->getEntity != NULL)) {
1412 reader->node->children = (xmlNodePtr)
1413 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1414 }
1415
1416 if ((reader->node->children != NULL) &&
1417 (reader->node->children->type == XML_ENTITY_DECL) &&
1418 (reader->node->children->children != NULL)) {
1419 xmlTextReaderEntPush(reader, reader->node);
1420 reader->node = reader->node->children->children;
1421 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001422#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001423 } else if ((reader->node != NULL) &&
1424 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001425 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001426 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001427#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001428 }
1429 if ((reader->node != NULL) &&
1430 (reader->node->type == XML_ENTITY_DECL) &&
1431 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1432 reader->node = xmlTextReaderEntPop(reader);
1433 reader->depth++;
1434 goto get_next_node;
1435 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001436#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001437 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001438 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001439
1440 if ((node->type == XML_ELEMENT_NODE) &&
1441 ((reader->state != XML_TEXTREADER_END) &&
1442 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1443 xmlTextReaderValidatePush(reader);
1444 } else if ((node->type == XML_TEXT_NODE) ||
1445 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001446 xmlTextReaderValidateCData(reader, node->content,
1447 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001448 }
1449 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001450#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001451#ifdef LIBXML_PATTERN_ENABLED
1452 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1453 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1454 int i;
1455 for (i = 0;i < reader->patternNr;i++) {
1456 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1457 xmlTextReaderPreserve(reader);
1458 break;
1459 }
1460 }
1461 }
1462#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001463 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001464node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001465 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001466 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001467}
1468
Daniel Veillard67df8092002-12-16 22:04:11 +00001469/**
1470 * xmlTextReaderReadState:
1471 * @reader: the xmlTextReaderPtr used
1472 *
1473 * Gets the read state of the reader.
1474 *
1475 * Returns the state value, or -1 in case of error
1476 */
1477int
1478xmlTextReaderReadState(xmlTextReaderPtr reader) {
1479 if (reader == NULL)
1480 return(-1);
1481 return(reader->mode);
1482}
1483
1484/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001485 * xmlTextReaderExpand:
1486 * @reader: the xmlTextReaderPtr used
1487 *
1488 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001489 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001490 *
1491 * Returns a node pointer valid until the next xmlTextReaderRead() call
1492 * or NULL in case of error.
1493 */
1494xmlNodePtr
1495xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001496 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001497 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001498 if (reader->doc != NULL)
1499 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001500 if (reader->ctxt == NULL)
1501 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001502 if (xmlTextReaderDoExpand(reader) < 0)
1503 return(NULL);
1504 return(reader->node);
1505}
1506
1507/**
1508 * xmlTextReaderNext:
1509 * @reader: the xmlTextReaderPtr used
1510 *
1511 * Skip to the node following the current one in document order while
1512 * avoiding the subtree if any.
1513 *
1514 * Returns 1 if the node was read successfully, 0 if there is no more
1515 * nodes to read, or -1 in case of error
1516 */
1517int
1518xmlTextReaderNext(xmlTextReaderPtr reader) {
1519 int ret;
1520 xmlNodePtr cur;
1521
1522 if (reader == NULL)
1523 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001524 if (reader->doc != NULL)
1525 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001526 cur = reader->node;
1527 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1528 return(xmlTextReaderRead(reader));
1529 if (reader->state == XML_TEXTREADER_END)
1530 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001531 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001532 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001533 do {
1534 ret = xmlTextReaderRead(reader);
1535 if (ret != 1)
1536 return(ret);
1537 } while (reader->node != cur);
1538 return(xmlTextReaderRead(reader));
1539}
1540
1541/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001542 * xmlTextReaderReadInnerXml:
1543 * @reader: the xmlTextReaderPtr used
1544 *
1545 * Reads the contents of the current node, including child nodes and markup.
1546 *
1547 * Returns a string containing the XML content, or NULL if the current node
1548 * is neither an element nor attribute, or has no child nodes. The
1549 * string must be deallocated by the caller.
1550 */
1551xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001552xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001553 TODO
1554 return(NULL);
1555}
1556
1557/**
1558 * xmlTextReaderReadOuterXml:
1559 * @reader: the xmlTextReaderPtr used
1560 *
1561 * Reads the contents of the current node, including child nodes and markup.
1562 *
1563 * Returns a string containing the XML content, or NULL if the current node
1564 * is neither an element nor attribute, or has no child nodes. The
1565 * string must be deallocated by the caller.
1566 */
1567xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001568xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001569 TODO
1570 return(NULL);
1571}
1572
1573/**
1574 * xmlTextReaderReadString:
1575 * @reader: the xmlTextReaderPtr used
1576 *
1577 * Reads the contents of an element or a text node as a string.
1578 *
1579 * Returns a string containing the contents of the Element or Text node,
1580 * or NULL if the reader is positioned on any other type of node.
1581 * The string must be deallocated by the caller.
1582 */
1583xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001584xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001585 TODO
1586 return(NULL);
1587}
1588
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001589#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001590/**
1591 * xmlTextReaderReadBase64:
1592 * @reader: the xmlTextReaderPtr used
1593 * @array: a byte array to store the content.
1594 * @offset: the zero-based index into array where the method should
1595 * begin to write.
1596 * @len: the number of bytes to write.
1597 *
1598 * Reads and decodes the Base64 encoded contents of an element and
1599 * stores the result in a byte buffer.
1600 *
1601 * Returns the number of bytes written to array, or zero if the current
1602 * instance is not positioned on an element or -1 in case of error.
1603 */
1604int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001605xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1606 unsigned char *array ATTRIBUTE_UNUSED,
1607 int offset ATTRIBUTE_UNUSED,
1608 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001609 if ((reader == NULL) || (reader->ctxt == NULL))
1610 return(-1);
1611 if (reader->ctxt->wellFormed != 1)
1612 return(-1);
1613
1614 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1615 return(0);
1616 TODO
1617 return(0);
1618}
1619
1620/**
1621 * xmlTextReaderReadBinHex:
1622 * @reader: the xmlTextReaderPtr used
1623 * @array: a byte array to store the content.
1624 * @offset: the zero-based index into array where the method should
1625 * begin to write.
1626 * @len: the number of bytes to write.
1627 *
1628 * Reads and decodes the BinHex encoded contents of an element and
1629 * stores the result in a byte buffer.
1630 *
1631 * Returns the number of bytes written to array, or zero if the current
1632 * instance is not positioned on an element or -1 in case of error.
1633 */
1634int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001635xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1636 unsigned char *array ATTRIBUTE_UNUSED,
1637 int offset ATTRIBUTE_UNUSED,
1638 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001639 if ((reader == NULL) || (reader->ctxt == NULL))
1640 return(-1);
1641 if (reader->ctxt->wellFormed != 1)
1642 return(-1);
1643
1644 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1645 return(0);
1646 TODO
1647 return(0);
1648}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001649#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001650
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001651/************************************************************************
1652 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001653 * Operating on a preparsed tree *
1654 * *
1655 ************************************************************************/
1656static int
1657xmlTextReaderNextTree(xmlTextReaderPtr reader)
1658{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001659 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001660 return(-1);
1661
1662 if (reader->state == XML_TEXTREADER_END)
1663 return(0);
1664
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001665 if (reader->node == NULL) {
1666 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001667 reader->state = XML_TEXTREADER_END;
1668 return(0);
1669 }
1670
1671 reader->node = reader->doc->children;
1672 reader->state = XML_TEXTREADER_START;
1673 return(1);
1674 }
1675
1676 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1677 if (reader->node->children != 0) {
1678 reader->node = reader->node->children;
1679 reader->depth++;
1680 reader->state = XML_TEXTREADER_START;
1681 return(1);
1682 }
1683
1684 if ((reader->node->type == XML_ELEMENT_NODE) ||
1685 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1686 reader->state = XML_TEXTREADER_BACKTRACK;
1687 return(1);
1688 }
1689 }
1690
1691 if (reader->node->next != 0) {
1692 reader->node = reader->node->next;
1693 reader->state = XML_TEXTREADER_START;
1694 return(1);
1695 }
1696
1697 if (reader->node->parent != 0) {
1698 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1699 reader->state = XML_TEXTREADER_END;
1700 return(0);
1701 }
1702
1703 reader->node = reader->node->parent;
1704 reader->depth--;
1705 reader->state = XML_TEXTREADER_BACKTRACK;
1706 return(1);
1707 }
1708
1709 reader->state = XML_TEXTREADER_END;
1710
1711 return(1);
1712}
1713
1714/**
1715 * xmlTextReaderReadTree:
1716 * @reader: the xmlTextReaderPtr used
1717 *
1718 * Moves the position of the current instance to the next node in
1719 * the stream, exposing its properties.
1720 *
1721 * Returns 1 if the node was read successfully, 0 if there is no more
1722 * nodes to read, or -1 in case of error
1723 */
1724static int
1725xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1726 if (reader->state == XML_TEXTREADER_END)
1727 return(0);
1728
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001729next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001730 if (reader->node == NULL) {
1731 if (reader->doc->children == NULL) {
1732 reader->state = XML_TEXTREADER_END;
1733 return(0);
1734 }
1735
1736 reader->node = reader->doc->children;
1737 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001738 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001739 }
1740
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001741 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1742 (reader->node->type != XML_DTD_NODE) &&
1743 (reader->node->type != XML_XINCLUDE_START) &&
1744 (reader->node->type != XML_ENTITY_REF_NODE)) {
1745 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001746 reader->node = reader->node->children;
1747 reader->depth++;
1748 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001749 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001750 }
1751
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001752 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001753 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001754 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001755 }
1756 }
1757
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001758 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001759 reader->node = reader->node->next;
1760 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001761 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001762 }
1763
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001764 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001765 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1766 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1767 reader->state = XML_TEXTREADER_END;
1768 return(0);
1769 }
1770
1771 reader->node = reader->node->parent;
1772 reader->depth--;
1773 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001774 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001775 }
1776
1777 reader->state = XML_TEXTREADER_END;
1778
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001779found_node:
1780 if ((reader->node->type == XML_XINCLUDE_START) ||
1781 (reader->node->type == XML_XINCLUDE_END))
1782 goto next_node;
1783
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001784 return(1);
1785}
1786
1787/**
William M. Brackb1d53162003-11-18 06:54:40 +00001788 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001789 * @reader: the xmlTextReaderPtr used
1790 *
1791 * Skip to the node following the current one in document order while
1792 * avoiding the subtree if any.
1793 * Currently implemented only for Readers built on a document
1794 *
1795 * Returns 1 if the node was read successfully, 0 if there is no more
1796 * nodes to read, or -1 in case of error
1797 */
1798int
1799xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1800 if (reader == NULL)
1801 return(-1);
1802 if (reader->doc == NULL) {
1803 TODO
1804 return(-1);
1805 }
1806
1807 if (reader->state == XML_TEXTREADER_END)
1808 return(0);
1809
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001810 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001811 return(xmlTextReaderNextTree(reader));
1812
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001813 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001814 reader->node = reader->node->next;
1815 reader->state = XML_TEXTREADER_START;
1816 return(1);
1817 }
1818
1819 return(0);
1820}
1821
1822/************************************************************************
1823 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001824 * Constructor and destructors *
1825 * *
1826 ************************************************************************/
1827/**
1828 * xmlNewTextReader:
1829 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001830 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001831 *
1832 * Create an xmlTextReader structure fed with @input
1833 *
1834 * Returns the new xmlTextReaderPtr or NULL in case of error
1835 */
1836xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001837xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001838 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001839
1840 if (input == NULL)
1841 return(NULL);
1842 ret = xmlMalloc(sizeof(xmlTextReader));
1843 if (ret == NULL) {
1844 xmlGenericError(xmlGenericErrorContext,
1845 "xmlNewTextReader : malloc failed\n");
1846 return(NULL);
1847 }
1848 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001849 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001850 ret->entTab = NULL;
1851 ret->entMax = 0;
1852 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001853 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001854 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001855 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1856 if (ret->sax == NULL) {
1857 xmlFree(ret);
1858 xmlGenericError(xmlGenericErrorContext,
1859 "xmlNewTextReader : malloc failed\n");
1860 return(NULL);
1861 }
Daniel Veillard81273902003-09-30 00:43:48 +00001862 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001863 ret->startElement = ret->sax->startElement;
1864 ret->sax->startElement = xmlTextReaderStartElement;
1865 ret->endElement = ret->sax->endElement;
1866 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001867#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001868 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001869#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001870 ret->startElementNs = ret->sax->startElementNs;
1871 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1872 ret->endElementNs = ret->sax->endElementNs;
1873 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001874#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001875 } else {
1876 ret->startElementNs = NULL;
1877 ret->endElementNs = NULL;
1878 }
Daniel Veillard81273902003-09-30 00:43:48 +00001879#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001880 ret->characters = ret->sax->characters;
1881 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001882 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001883 ret->cdataBlock = ret->sax->cdataBlock;
1884 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001885
Daniel Veillard67df8092002-12-16 22:04:11 +00001886 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001887 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001888 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001889 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001890 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001891 }
1892 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001893 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001894 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001895 ret->base = 0;
1896 ret->cur = 4;
1897 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001898 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001899 ret->base = 0;
1900 ret->cur = 0;
1901 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001902 if (ret->ctxt == NULL) {
1903 xmlGenericError(xmlGenericErrorContext,
1904 "xmlNewTextReader : malloc failed\n");
1905 xmlFree(ret->sax);
1906 xmlFree(ret);
1907 return(NULL);
1908 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001909 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001910 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001911 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001912 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001913 /*
1914 * use the parser dictionnary to allocate all elements and attributes names
1915 */
1916 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001917 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001918#ifdef LIBXML_XINCLUDE_ENABLED
1919 ret->xinclude = 0;
1920#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001921#ifdef LIBXML_PATTERN_ENABLED
1922 ret->patternMax = 0;
1923 ret->patternTab = NULL;
1924#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001925 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001926}
1927
1928/**
1929 * xmlNewTextReaderFilename:
1930 * @URI: the URI of the resource to process
1931 *
1932 * Create an xmlTextReader structure fed with the resource at @URI
1933 *
1934 * Returns the new xmlTextReaderPtr or NULL in case of error
1935 */
1936xmlTextReaderPtr
1937xmlNewTextReaderFilename(const char *URI) {
1938 xmlParserInputBufferPtr input;
1939 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001940 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001941
1942 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1943 if (input == NULL)
1944 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001945 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001946 if (ret == NULL) {
1947 xmlFreeParserInputBuffer(input);
1948 return(NULL);
1949 }
1950 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001951 if (ret->ctxt->directory == NULL)
1952 directory = xmlParserGetDirectory(URI);
1953 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1954 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1955 if (directory != NULL)
1956 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001957 return(ret);
1958}
1959
1960/**
1961 * xmlFreeTextReader:
1962 * @reader: the xmlTextReaderPtr
1963 *
1964 * Deallocate all the resources associated to the reader
1965 */
1966void
1967xmlFreeTextReader(xmlTextReaderPtr reader) {
1968 if (reader == NULL)
1969 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001970#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001971 if (reader->rngSchemas != NULL) {
1972 xmlRelaxNGFree(reader->rngSchemas);
1973 reader->rngSchemas = NULL;
1974 }
1975 if (reader->rngValidCtxt != NULL) {
1976 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1977 reader->rngValidCtxt = NULL;
1978 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001979#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001980#ifdef LIBXML_XINCLUDE_ENABLED
1981 if (reader->xincctxt != NULL)
1982 xmlXIncludeFreeContext(reader->xincctxt);
1983#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001984#ifdef LIBXML_PATTERN_ENABLED
1985 if (reader->patternTab != NULL) {
1986 int i;
1987 for (i = 0;i < reader->patternNr;i++) {
1988 if (reader->patternTab[i] != NULL)
1989 xmlFreePattern(reader->patternTab[i]);
1990 }
1991 xmlFree(reader->patternTab);
1992 }
1993#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001994 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001995 if (reader->dict == reader->ctxt->dict)
1996 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001997 if (reader->ctxt->myDoc != NULL) {
1998 if (reader->preserve == 0)
1999 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2000 reader->ctxt->myDoc = NULL;
2001 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002002 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2003 (reader->ctxt->vctxt.vstateMax > 0)){
2004 xmlFree(reader->ctxt->vctxt.vstateTab);
2005 reader->ctxt->vctxt.vstateTab = 0;
2006 reader->ctxt->vctxt.vstateMax = 0;
2007 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002008 if (reader->allocs & XML_TEXTREADER_CTXT)
2009 xmlFreeParserCtxt(reader->ctxt);
2010 }
2011 if (reader->sax != NULL)
2012 xmlFree(reader->sax);
2013 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2014 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002015 if (reader->faketext != NULL) {
2016 xmlFreeNode(reader->faketext);
2017 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002018 if (reader->buffer != NULL)
2019 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002020 if (reader->entTab != NULL)
2021 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002022 if (reader->dict != NULL)
2023 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002024 xmlFree(reader);
2025}
2026
2027/************************************************************************
2028 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002029 * Methods for XmlTextReader *
2030 * *
2031 ************************************************************************/
2032/**
2033 * xmlTextReaderClose:
2034 * @reader: the xmlTextReaderPtr used
2035 *
2036 * This method releases any resources allocated by the current instance
2037 * changes the state to Closed and close any underlying input.
2038 *
2039 * Returns 0 or -1 in case of error
2040 */
2041int
2042xmlTextReaderClose(xmlTextReaderPtr reader) {
2043 if (reader == NULL)
2044 return(-1);
2045 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002046 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002047 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2048 if (reader->ctxt != NULL) {
2049 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002050 if (reader->preserve == 0)
2051 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002052 reader->ctxt->myDoc = NULL;
2053 }
2054 if (reader->allocs & XML_TEXTREADER_CTXT) {
2055 xmlFreeParserCtxt(reader->ctxt);
2056 reader->allocs -= XML_TEXTREADER_CTXT;
2057 }
2058 }
2059 if (reader->sax != NULL) {
2060 xmlFree(reader->sax);
2061 reader->sax = NULL;
2062 }
2063 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2064 xmlFreeParserInputBuffer(reader->input);
2065 reader->allocs -= XML_TEXTREADER_INPUT;
2066 }
2067 return(0);
2068}
2069
2070/**
2071 * xmlTextReaderGetAttributeNo:
2072 * @reader: the xmlTextReaderPtr used
2073 * @no: the zero-based index of the attribute relative to the containing element
2074 *
2075 * Provides the value of the attribute with the specified index relative
2076 * to the containing element.
2077 *
2078 * Returns a string containing the value of the specified attribute, or NULL
2079 * in case of error. The string must be deallocated by the caller.
2080 */
2081xmlChar *
2082xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2083 xmlChar *ret;
2084 int i;
2085 xmlAttrPtr cur;
2086 xmlNsPtr ns;
2087
2088 if (reader == NULL)
2089 return(NULL);
2090 if (reader->node == NULL)
2091 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002092 if (reader->curnode != NULL)
2093 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002094 /* TODO: handle the xmlDecl */
2095 if (reader->node->type != XML_ELEMENT_NODE)
2096 return(NULL);
2097
2098 ns = reader->node->nsDef;
2099 for (i = 0;(i < no) && (ns != NULL);i++) {
2100 ns = ns->next;
2101 }
2102 if (ns != NULL)
2103 return(xmlStrdup(ns->href));
2104
2105 cur = reader->node->properties;
2106 if (cur == NULL)
2107 return(NULL);
2108 for (;i < no;i++) {
2109 cur = cur->next;
2110 if (cur == NULL)
2111 return(NULL);
2112 }
2113 /* TODO walk the DTD if present */
2114
2115 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2116 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2117 return(ret);
2118}
2119
2120/**
2121 * xmlTextReaderGetAttribute:
2122 * @reader: the xmlTextReaderPtr used
2123 * @name: the qualified name of the attribute.
2124 *
2125 * Provides the value of the attribute with the specified qualified name.
2126 *
2127 * Returns a string containing the value of the specified attribute, or NULL
2128 * in case of error. The string must be deallocated by the caller.
2129 */
2130xmlChar *
2131xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2132 xmlChar *prefix = NULL;
2133 xmlChar *localname;
2134 xmlNsPtr ns;
2135 xmlChar *ret = NULL;
2136
2137 if ((reader == NULL) || (name == NULL))
2138 return(NULL);
2139 if (reader->node == NULL)
2140 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002141 if (reader->curnode != NULL)
2142 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002143
2144 /* TODO: handle the xmlDecl */
2145 if (reader->node->type != XML_ELEMENT_NODE)
2146 return(NULL);
2147
2148 localname = xmlSplitQName2(name, &prefix);
2149 if (localname == NULL)
2150 return(xmlGetProp(reader->node, name));
2151
2152 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2153 if (ns != NULL)
2154 ret = xmlGetNsProp(reader->node, localname, ns->href);
2155
2156 if (localname != NULL)
2157 xmlFree(localname);
2158 if (prefix != NULL)
2159 xmlFree(prefix);
2160 return(ret);
2161}
2162
2163
2164/**
2165 * xmlTextReaderGetAttributeNs:
2166 * @reader: the xmlTextReaderPtr used
2167 * @localName: the local name of the attribute.
2168 * @namespaceURI: the namespace URI of the attribute.
2169 *
2170 * Provides the value of the specified attribute
2171 *
2172 * Returns a string containing the value of the specified attribute, or NULL
2173 * in case of error. The string must be deallocated by the caller.
2174 */
2175xmlChar *
2176xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2177 const xmlChar *namespaceURI) {
2178 if ((reader == NULL) || (localName == NULL))
2179 return(NULL);
2180 if (reader->node == NULL)
2181 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002182 if (reader->curnode != NULL)
2183 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002184
2185 /* TODO: handle the xmlDecl */
2186 if (reader->node->type != XML_ELEMENT_NODE)
2187 return(NULL);
2188
2189 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2190}
2191
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002192/**
2193 * xmlTextReaderGetRemainder:
2194 * @reader: the xmlTextReaderPtr used
2195 *
2196 * Method to get the remainder of the buffered XML. this method stops the
2197 * parser, set its state to End Of File and return the input stream with
2198 * what is left that the parser did not use.
2199 *
2200 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2201 * in case of error.
2202 */
2203xmlParserInputBufferPtr
2204xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2205 xmlParserInputBufferPtr ret = NULL;
2206
2207 if (reader == NULL)
2208 return(NULL);
2209 if (reader->node == NULL)
2210 return(NULL);
2211
2212 reader->node = NULL;
2213 reader->curnode = NULL;
2214 reader->mode = XML_TEXTREADER_MODE_EOF;
2215 if (reader->ctxt != NULL) {
2216 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002217 if (reader->preserve == 0)
2218 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002219 reader->ctxt->myDoc = NULL;
2220 }
2221 if (reader->allocs & XML_TEXTREADER_CTXT) {
2222 xmlFreeParserCtxt(reader->ctxt);
2223 reader->allocs -= XML_TEXTREADER_CTXT;
2224 }
2225 }
2226 if (reader->sax != NULL) {
2227 xmlFree(reader->sax);
2228 reader->sax = NULL;
2229 }
2230 if (reader->allocs & XML_TEXTREADER_INPUT) {
2231 ret = reader->input;
2232 reader->allocs -= XML_TEXTREADER_INPUT;
2233 } else {
2234 /*
2235 * Hum, one may need to duplicate the data structure because
2236 * without reference counting the input may be freed twice:
2237 * - by the layer which allocated it.
2238 * - by the layer to which would have been returned to.
2239 */
2240 TODO
2241 return(NULL);
2242 }
2243 return(ret);
2244}
2245
2246/**
2247 * xmlTextReaderLookupNamespace:
2248 * @reader: the xmlTextReaderPtr used
2249 * @prefix: the prefix whose namespace URI is to be resolved. To return
2250 * the default namespace, specify NULL
2251 *
2252 * Resolves a namespace prefix in the scope of the current element.
2253 *
2254 * Returns a string containing the namespace URI to which the prefix maps
2255 * or NULL in case of error. The string must be deallocated by the caller.
2256 */
2257xmlChar *
2258xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2259 xmlNsPtr ns;
2260
2261 if (reader == NULL)
2262 return(NULL);
2263 if (reader->node == NULL)
2264 return(NULL);
2265
2266 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2267 if (ns == NULL)
2268 return(NULL);
2269 return(xmlStrdup(ns->href));
2270}
2271
2272/**
2273 * xmlTextReaderMoveToAttributeNo:
2274 * @reader: the xmlTextReaderPtr used
2275 * @no: the zero-based index of the attribute relative to the containing
2276 * element.
2277 *
2278 * Moves the position of the current instance to the attribute with
2279 * the specified index relative to the containing element.
2280 *
2281 * Returns 1 in case of success, -1 in case of error, 0 if not found
2282 */
2283int
2284xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2285 int i;
2286 xmlAttrPtr cur;
2287 xmlNsPtr ns;
2288
2289 if (reader == NULL)
2290 return(-1);
2291 if (reader->node == NULL)
2292 return(-1);
2293 /* TODO: handle the xmlDecl */
2294 if (reader->node->type != XML_ELEMENT_NODE)
2295 return(-1);
2296
2297 reader->curnode = NULL;
2298
2299 ns = reader->node->nsDef;
2300 for (i = 0;(i < no) && (ns != NULL);i++) {
2301 ns = ns->next;
2302 }
2303 if (ns != NULL) {
2304 reader->curnode = (xmlNodePtr) ns;
2305 return(1);
2306 }
2307
2308 cur = reader->node->properties;
2309 if (cur == NULL)
2310 return(0);
2311 for (;i < no;i++) {
2312 cur = cur->next;
2313 if (cur == NULL)
2314 return(0);
2315 }
2316 /* TODO walk the DTD if present */
2317
2318 reader->curnode = (xmlNodePtr) cur;
2319 return(1);
2320}
2321
2322/**
2323 * xmlTextReaderMoveToAttribute:
2324 * @reader: the xmlTextReaderPtr used
2325 * @name: the qualified name of the attribute.
2326 *
2327 * Moves the position of the current instance to the attribute with
2328 * the specified qualified name.
2329 *
2330 * Returns 1 in case of success, -1 in case of error, 0 if not found
2331 */
2332int
2333xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2334 xmlChar *prefix = NULL;
2335 xmlChar *localname;
2336 xmlNsPtr ns;
2337 xmlAttrPtr prop;
2338
2339 if ((reader == NULL) || (name == NULL))
2340 return(-1);
2341 if (reader->node == NULL)
2342 return(-1);
2343
2344 /* TODO: handle the xmlDecl */
2345 if (reader->node->type != XML_ELEMENT_NODE)
2346 return(0);
2347
2348 localname = xmlSplitQName2(name, &prefix);
2349 if (localname == NULL) {
2350 /*
2351 * Namespace default decl
2352 */
2353 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2354 ns = reader->node->nsDef;
2355 while (ns != NULL) {
2356 if (ns->prefix == NULL) {
2357 reader->curnode = (xmlNodePtr) ns;
2358 return(1);
2359 }
2360 ns = ns->next;
2361 }
2362 return(0);
2363 }
2364
2365 prop = reader->node->properties;
2366 while (prop != NULL) {
2367 /*
2368 * One need to have
2369 * - same attribute names
2370 * - and the attribute carrying that namespace
2371 */
2372 if ((xmlStrEqual(prop->name, name)) &&
2373 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2374 reader->curnode = (xmlNodePtr) prop;
2375 return(1);
2376 }
2377 prop = prop->next;
2378 }
2379 return(0);
2380 }
2381
2382 /*
2383 * Namespace default decl
2384 */
2385 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2386 ns = reader->node->nsDef;
2387 while (ns != NULL) {
2388 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2389 reader->curnode = (xmlNodePtr) ns;
2390 goto found;
2391 }
2392 ns = ns->next;
2393 }
2394 goto not_found;
2395 }
2396 prop = reader->node->properties;
2397 while (prop != NULL) {
2398 /*
2399 * One need to have
2400 * - same attribute names
2401 * - and the attribute carrying that namespace
2402 */
2403 if ((xmlStrEqual(prop->name, localname)) &&
2404 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2405 reader->curnode = (xmlNodePtr) prop;
2406 goto found;
2407 }
2408 prop = prop->next;
2409 }
2410not_found:
2411 if (localname != NULL)
2412 xmlFree(localname);
2413 if (prefix != NULL)
2414 xmlFree(prefix);
2415 return(0);
2416
2417found:
2418 if (localname != NULL)
2419 xmlFree(localname);
2420 if (prefix != NULL)
2421 xmlFree(prefix);
2422 return(1);
2423}
2424
2425/**
2426 * xmlTextReaderMoveToAttributeNs:
2427 * @reader: the xmlTextReaderPtr used
2428 * @localName: the local name of the attribute.
2429 * @namespaceURI: the namespace URI of the attribute.
2430 *
2431 * Moves the position of the current instance to the attribute with the
2432 * specified local name and namespace URI.
2433 *
2434 * Returns 1 in case of success, -1 in case of error, 0 if not found
2435 */
2436int
2437xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2438 const xmlChar *localName, const xmlChar *namespaceURI) {
2439 xmlAttrPtr prop;
2440 xmlNodePtr node;
2441
2442 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2443 return(-1);
2444 if (reader->node == NULL)
2445 return(-1);
2446 if (reader->node->type != XML_ELEMENT_NODE)
2447 return(0);
2448 node = reader->node;
2449
2450 /*
2451 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2452 * namespace name associated to "xmlns"
2453 */
2454 prop = node->properties;
2455 while (prop != NULL) {
2456 /*
2457 * One need to have
2458 * - same attribute names
2459 * - and the attribute carrying that namespace
2460 */
2461 if (xmlStrEqual(prop->name, localName) &&
2462 ((prop->ns != NULL) &&
2463 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2464 reader->curnode = (xmlNodePtr) prop;
2465 return(1);
2466 }
2467 prop = prop->next;
2468 }
2469 return(0);
2470}
2471
2472/**
2473 * xmlTextReaderMoveToFirstAttribute:
2474 * @reader: the xmlTextReaderPtr used
2475 *
2476 * Moves the position of the current instance to the first attribute
2477 * associated with the current node.
2478 *
2479 * Returns 1 in case of success, -1 in case of error, 0 if not found
2480 */
2481int
2482xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2483 if (reader == NULL)
2484 return(-1);
2485 if (reader->node == NULL)
2486 return(-1);
2487 if (reader->node->type != XML_ELEMENT_NODE)
2488 return(0);
2489
2490 if (reader->node->nsDef != NULL) {
2491 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2492 return(1);
2493 }
2494 if (reader->node->properties != NULL) {
2495 reader->curnode = (xmlNodePtr) reader->node->properties;
2496 return(1);
2497 }
2498 return(0);
2499}
2500
2501/**
2502 * xmlTextReaderMoveToNextAttribute:
2503 * @reader: the xmlTextReaderPtr used
2504 *
2505 * Moves the position of the current instance to the next attribute
2506 * associated with the current node.
2507 *
2508 * Returns 1 in case of success, -1 in case of error, 0 if not found
2509 */
2510int
2511xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2512 if (reader == NULL)
2513 return(-1);
2514 if (reader->node == NULL)
2515 return(-1);
2516 if (reader->node->type != XML_ELEMENT_NODE)
2517 return(0);
2518 if (reader->curnode == NULL)
2519 return(xmlTextReaderMoveToFirstAttribute(reader));
2520
2521 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2522 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2523 if (ns->next != NULL) {
2524 reader->curnode = (xmlNodePtr) ns->next;
2525 return(1);
2526 }
2527 if (reader->node->properties != NULL) {
2528 reader->curnode = (xmlNodePtr) reader->node->properties;
2529 return(1);
2530 }
2531 return(0);
2532 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2533 (reader->curnode->next != NULL)) {
2534 reader->curnode = reader->curnode->next;
2535 return(1);
2536 }
2537 return(0);
2538}
2539
2540/**
2541 * xmlTextReaderMoveToElement:
2542 * @reader: the xmlTextReaderPtr used
2543 *
2544 * Moves the position of the current instance to the node that
2545 * contains the current Attribute node.
2546 *
2547 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2548 */
2549int
2550xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2551 if (reader == NULL)
2552 return(-1);
2553 if (reader->node == NULL)
2554 return(-1);
2555 if (reader->node->type != XML_ELEMENT_NODE)
2556 return(0);
2557 if (reader->curnode != NULL) {
2558 reader->curnode = NULL;
2559 return(1);
2560 }
2561 return(0);
2562}
2563
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002564/**
2565 * xmlTextReaderReadAttributeValue:
2566 * @reader: the xmlTextReaderPtr used
2567 *
2568 * Parses an attribute value into one or more Text and EntityReference nodes.
2569 *
2570 * Returns 1 in case of success, 0 if the reader was not positionned on an
2571 * ttribute node or all the attribute values have been read, or -1
2572 * in case of error.
2573 */
2574int
2575xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2576 if (reader == NULL)
2577 return(-1);
2578 if (reader->node == NULL)
2579 return(-1);
2580 if (reader->curnode == NULL)
2581 return(0);
2582 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2583 if (reader->curnode->children == NULL)
2584 return(0);
2585 reader->curnode = reader->curnode->children;
2586 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2587 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2588
2589 if (reader->faketext == NULL) {
2590 reader->faketext = xmlNewDocText(reader->node->doc,
2591 ns->href);
2592 } else {
2593 if (reader->faketext->content != NULL)
2594 xmlFree(reader->faketext->content);
2595 reader->faketext->content = xmlStrdup(ns->href);
2596 }
2597 reader->curnode = reader->faketext;
2598 } else {
2599 if (reader->curnode->next == NULL)
2600 return(0);
2601 reader->curnode = reader->curnode->next;
2602 }
2603 return(1);
2604}
2605
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002606/************************************************************************
2607 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002608 * Acces API to the current node *
2609 * *
2610 ************************************************************************/
2611/**
2612 * xmlTextReaderAttributeCount:
2613 * @reader: the xmlTextReaderPtr used
2614 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002615 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002616 *
2617 * Returns 0 i no attributes, -1 in case of error or the attribute count
2618 */
2619int
2620xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2621 int ret;
2622 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002623 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002624 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002625
2626 if (reader == NULL)
2627 return(-1);
2628 if (reader->node == NULL)
2629 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002630
2631 if (reader->curnode != NULL)
2632 node = reader->curnode;
2633 else
2634 node = reader->node;
2635
2636 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002637 return(0);
2638 if ((reader->state == XML_TEXTREADER_END) ||
2639 (reader->state == XML_TEXTREADER_BACKTRACK))
2640 return(0);
2641 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002642 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002643 while (attr != NULL) {
2644 ret++;
2645 attr = attr->next;
2646 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002647 ns = node->nsDef;
2648 while (ns != NULL) {
2649 ret++;
2650 ns = ns->next;
2651 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002652 return(ret);
2653}
2654
2655/**
2656 * xmlTextReaderNodeType:
2657 * @reader: the xmlTextReaderPtr used
2658 *
2659 * Get the node type of the current node
2660 * Reference:
2661 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2662 *
2663 * Returns the xmlNodeType of the current node or -1 in case of error
2664 */
2665int
2666xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002667 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002668
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002669 if (reader == NULL)
2670 return(-1);
2671 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002672 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002673 if (reader->curnode != NULL)
2674 node = reader->curnode;
2675 else
2676 node = reader->node;
2677 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002678 case XML_ELEMENT_NODE:
2679 if ((reader->state == XML_TEXTREADER_END) ||
2680 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002681 return(XML_READER_TYPE_END_ELEMENT);
2682 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002683 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002684 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002685 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002686 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002687 if (xmlIsBlankNode(reader->node)) {
2688 if (xmlNodeGetSpacePreserve(reader->node))
2689 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2690 else
2691 return(XML_READER_TYPE_WHITESPACE);
2692 } else {
2693 return(XML_READER_TYPE_TEXT);
2694 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002695 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002696 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002697 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002698 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002699 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002700 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002701 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002702 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002703 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002704 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002705 case XML_DOCUMENT_NODE:
2706 case XML_HTML_DOCUMENT_NODE:
2707#ifdef LIBXML_DOCB_ENABLED
2708 case XML_DOCB_DOCUMENT_NODE:
2709#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002710 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002711 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002712 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002713 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002714 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002715 case XML_DOCUMENT_TYPE_NODE:
2716 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002717 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002718
2719 case XML_ELEMENT_DECL:
2720 case XML_ATTRIBUTE_DECL:
2721 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002722 case XML_XINCLUDE_START:
2723 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002724 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002725 }
2726 return(-1);
2727}
2728
2729/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002730 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002731 * @reader: the xmlTextReaderPtr used
2732 *
2733 * Check if the current node is empty
2734 *
2735 * Returns 1 if empty, 0 if not and -1 in case of error
2736 */
2737int
2738xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2739 if ((reader == NULL) || (reader->node == NULL))
2740 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002741 if (reader->node->type != XML_ELEMENT_NODE)
2742 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002743 if (reader->curnode != NULL)
2744 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002745 if (reader->node->children != NULL)
2746 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002747 if (reader->state == XML_TEXTREADER_END)
2748 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002749 if (reader->doc != NULL)
2750 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002751#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002752 if (reader->in_xinclude > 0)
2753 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002754#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002755 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002756}
2757
2758/**
2759 * xmlTextReaderLocalName:
2760 * @reader: the xmlTextReaderPtr used
2761 *
2762 * The local name of the node.
2763 *
2764 * Returns the local name or NULL if not available
2765 */
2766xmlChar *
2767xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002768 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002769 if ((reader == NULL) || (reader->node == NULL))
2770 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002771 if (reader->curnode != NULL)
2772 node = reader->curnode;
2773 else
2774 node = reader->node;
2775 if (node->type == XML_NAMESPACE_DECL) {
2776 xmlNsPtr ns = (xmlNsPtr) node;
2777 if (ns->prefix == NULL)
2778 return(xmlStrdup(BAD_CAST "xmlns"));
2779 else
2780 return(xmlStrdup(ns->prefix));
2781 }
2782 if ((node->type != XML_ELEMENT_NODE) &&
2783 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002784 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002785 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002786}
2787
2788/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002789 * xmlTextReaderConstLocalName:
2790 * @reader: the xmlTextReaderPtr used
2791 *
2792 * The local name of the node.
2793 *
2794 * Returns the local name or NULL if not available, the
2795 * string will be deallocated with the reader.
2796 */
2797const xmlChar *
2798xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2799 xmlNodePtr node;
2800 if ((reader == NULL) || (reader->node == NULL))
2801 return(NULL);
2802 if (reader->curnode != NULL)
2803 node = reader->curnode;
2804 else
2805 node = reader->node;
2806 if (node->type == XML_NAMESPACE_DECL) {
2807 xmlNsPtr ns = (xmlNsPtr) node;
2808 if (ns->prefix == NULL)
2809 return(CONSTSTR(BAD_CAST "xmlns"));
2810 else
2811 return(ns->prefix);
2812 }
2813 if ((node->type != XML_ELEMENT_NODE) &&
2814 (node->type != XML_ATTRIBUTE_NODE))
2815 return(xmlTextReaderConstName(reader));
2816 return(node->name);
2817}
2818
2819/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002820 * xmlTextReaderName:
2821 * @reader: the xmlTextReaderPtr used
2822 *
2823 * The qualified name of the node, equal to Prefix :LocalName.
2824 *
2825 * Returns the local name or NULL if not available
2826 */
2827xmlChar *
2828xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002829 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002830 xmlChar *ret;
2831
2832 if ((reader == NULL) || (reader->node == NULL))
2833 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002834 if (reader->curnode != NULL)
2835 node = reader->curnode;
2836 else
2837 node = reader->node;
2838 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002839 case XML_ELEMENT_NODE:
2840 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002841 if ((node->ns == NULL) ||
2842 (node->ns->prefix == NULL))
2843 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002844
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002845 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002846 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002847 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002848 return(ret);
2849 case XML_TEXT_NODE:
2850 return(xmlStrdup(BAD_CAST "#text"));
2851 case XML_CDATA_SECTION_NODE:
2852 return(xmlStrdup(BAD_CAST "#cdata-section"));
2853 case XML_ENTITY_NODE:
2854 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002855 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002856 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002857 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002858 case XML_COMMENT_NODE:
2859 return(xmlStrdup(BAD_CAST "#comment"));
2860 case XML_DOCUMENT_NODE:
2861 case XML_HTML_DOCUMENT_NODE:
2862#ifdef LIBXML_DOCB_ENABLED
2863 case XML_DOCB_DOCUMENT_NODE:
2864#endif
2865 return(xmlStrdup(BAD_CAST "#document"));
2866 case XML_DOCUMENT_FRAG_NODE:
2867 return(xmlStrdup(BAD_CAST "#document-fragment"));
2868 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002869 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002870 case XML_DOCUMENT_TYPE_NODE:
2871 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002872 return(xmlStrdup(node->name));
2873 case XML_NAMESPACE_DECL: {
2874 xmlNsPtr ns = (xmlNsPtr) node;
2875
2876 ret = xmlStrdup(BAD_CAST "xmlns");
2877 if (ns->prefix == NULL)
2878 return(ret);
2879 ret = xmlStrcat(ret, BAD_CAST ":");
2880 ret = xmlStrcat(ret, ns->prefix);
2881 return(ret);
2882 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002883
2884 case XML_ELEMENT_DECL:
2885 case XML_ATTRIBUTE_DECL:
2886 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002887 case XML_XINCLUDE_START:
2888 case XML_XINCLUDE_END:
2889 return(NULL);
2890 }
2891 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002892}
2893
2894/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002895 * xmlTextReaderConstName:
2896 * @reader: the xmlTextReaderPtr used
2897 *
2898 * The qualified name of the node, equal to Prefix :LocalName.
2899 *
2900 * Returns the local name or NULL if not available, the string is
2901 * deallocated with the reader.
2902 */
2903const xmlChar *
2904xmlTextReaderConstName(xmlTextReaderPtr reader) {
2905 xmlNodePtr node;
2906
2907 if ((reader == NULL) || (reader->node == NULL))
2908 return(NULL);
2909 if (reader->curnode != NULL)
2910 node = reader->curnode;
2911 else
2912 node = reader->node;
2913 switch (node->type) {
2914 case XML_ELEMENT_NODE:
2915 case XML_ATTRIBUTE_NODE:
2916 if ((node->ns == NULL) ||
2917 (node->ns->prefix == NULL))
2918 return(node->name);
2919 return(CONSTQSTR(node->ns->prefix, node->name));
2920 case XML_TEXT_NODE:
2921 return(CONSTSTR(BAD_CAST "#text"));
2922 case XML_CDATA_SECTION_NODE:
2923 return(CONSTSTR(BAD_CAST "#cdata-section"));
2924 case XML_ENTITY_NODE:
2925 case XML_ENTITY_REF_NODE:
2926 return(CONSTSTR(node->name));
2927 case XML_PI_NODE:
2928 return(CONSTSTR(node->name));
2929 case XML_COMMENT_NODE:
2930 return(CONSTSTR(BAD_CAST "#comment"));
2931 case XML_DOCUMENT_NODE:
2932 case XML_HTML_DOCUMENT_NODE:
2933#ifdef LIBXML_DOCB_ENABLED
2934 case XML_DOCB_DOCUMENT_NODE:
2935#endif
2936 return(CONSTSTR(BAD_CAST "#document"));
2937 case XML_DOCUMENT_FRAG_NODE:
2938 return(CONSTSTR(BAD_CAST "#document-fragment"));
2939 case XML_NOTATION_NODE:
2940 return(CONSTSTR(node->name));
2941 case XML_DOCUMENT_TYPE_NODE:
2942 case XML_DTD_NODE:
2943 return(CONSTSTR(node->name));
2944 case XML_NAMESPACE_DECL: {
2945 xmlNsPtr ns = (xmlNsPtr) node;
2946
2947 if (ns->prefix == NULL)
2948 return(CONSTSTR(BAD_CAST "xmlns"));
2949 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2950 }
2951
2952 case XML_ELEMENT_DECL:
2953 case XML_ATTRIBUTE_DECL:
2954 case XML_ENTITY_DECL:
2955 case XML_XINCLUDE_START:
2956 case XML_XINCLUDE_END:
2957 return(NULL);
2958 }
2959 return(NULL);
2960}
2961
2962/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002963 * xmlTextReaderPrefix:
2964 * @reader: the xmlTextReaderPtr used
2965 *
2966 * A shorthand reference to the namespace associated with the node.
2967 *
2968 * Returns the prefix or NULL if not available
2969 */
2970xmlChar *
2971xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002972 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002973 if ((reader == NULL) || (reader->node == NULL))
2974 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002975 if (reader->curnode != NULL)
2976 node = reader->curnode;
2977 else
2978 node = reader->node;
2979 if (node->type == XML_NAMESPACE_DECL) {
2980 xmlNsPtr ns = (xmlNsPtr) node;
2981 if (ns->prefix == NULL)
2982 return(NULL);
2983 return(xmlStrdup(BAD_CAST "xmlns"));
2984 }
2985 if ((node->type != XML_ELEMENT_NODE) &&
2986 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002987 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002988 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002989 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002990 return(NULL);
2991}
2992
2993/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002994 * xmlTextReaderConstPrefix:
2995 * @reader: the xmlTextReaderPtr used
2996 *
2997 * A shorthand reference to the namespace associated with the node.
2998 *
2999 * Returns the prefix or NULL if not available, the string is deallocated
3000 * with the reader.
3001 */
3002const xmlChar *
3003xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3004 xmlNodePtr node;
3005 if ((reader == NULL) || (reader->node == NULL))
3006 return(NULL);
3007 if (reader->curnode != NULL)
3008 node = reader->curnode;
3009 else
3010 node = reader->node;
3011 if (node->type == XML_NAMESPACE_DECL) {
3012 xmlNsPtr ns = (xmlNsPtr) node;
3013 if (ns->prefix == NULL)
3014 return(NULL);
3015 return(CONSTSTR(BAD_CAST "xmlns"));
3016 }
3017 if ((node->type != XML_ELEMENT_NODE) &&
3018 (node->type != XML_ATTRIBUTE_NODE))
3019 return(NULL);
3020 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3021 return(CONSTSTR(node->ns->prefix));
3022 return(NULL);
3023}
3024
3025/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003026 * xmlTextReaderNamespaceUri:
3027 * @reader: the xmlTextReaderPtr used
3028 *
3029 * The URI defining the namespace associated with the node.
3030 *
3031 * Returns the namespace URI or NULL if not available
3032 */
3033xmlChar *
3034xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003035 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003036 if ((reader == NULL) || (reader->node == NULL))
3037 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003038 if (reader->curnode != NULL)
3039 node = reader->curnode;
3040 else
3041 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003042 if (node->type == XML_NAMESPACE_DECL)
3043 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003044 if ((node->type != XML_ELEMENT_NODE) &&
3045 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003047 if (node->ns != NULL)
3048 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003049 return(NULL);
3050}
3051
3052/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003053 * xmlTextReaderConstNamespaceUri:
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, the string
3059 * will be deallocated with the reader
3060 */
3061const xmlChar *
3062xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3063 xmlNodePtr node;
3064 if ((reader == NULL) || (reader->node == NULL))
3065 return(NULL);
3066 if (reader->curnode != NULL)
3067 node = reader->curnode;
3068 else
3069 node = reader->node;
3070 if (node->type == XML_NAMESPACE_DECL)
3071 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3072 if ((node->type != XML_ELEMENT_NODE) &&
3073 (node->type != XML_ATTRIBUTE_NODE))
3074 return(NULL);
3075 if (node->ns != NULL)
3076 return(CONSTSTR(node->ns->href));
3077 return(NULL);
3078}
3079
3080/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003081 * xmlTextReaderBaseUri:
3082 * @reader: the xmlTextReaderPtr used
3083 *
3084 * The base URI of the node.
3085 *
3086 * Returns the base URI or NULL if not available
3087 */
3088xmlChar *
3089xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3090 if ((reader == NULL) || (reader->node == NULL))
3091 return(NULL);
3092 return(xmlNodeGetBase(NULL, reader->node));
3093}
3094
3095/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003096 * xmlTextReaderConstBaseUri:
3097 * @reader: the xmlTextReaderPtr used
3098 *
3099 * The base URI of the node.
3100 *
3101 * Returns the base URI or NULL if not available, the string
3102 * will be deallocated with the reader
3103 */
3104const xmlChar *
3105xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3106 xmlChar *tmp;
3107 const xmlChar *ret;
3108
3109 if ((reader == NULL) || (reader->node == NULL))
3110 return(NULL);
3111 tmp = xmlNodeGetBase(NULL, reader->node);
3112 if (tmp == NULL)
3113 return(NULL);
3114 ret = CONSTSTR(tmp);
3115 xmlFree(tmp);
3116 return(ret);
3117}
3118
3119/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003120 * xmlTextReaderDepth:
3121 * @reader: the xmlTextReaderPtr used
3122 *
3123 * The depth of the node in the tree.
3124 *
3125 * Returns the depth or -1 in case of error
3126 */
3127int
3128xmlTextReaderDepth(xmlTextReaderPtr reader) {
3129 if (reader == NULL)
3130 return(-1);
3131 if (reader->node == NULL)
3132 return(0);
3133
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003134 if (reader->curnode != NULL) {
3135 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3136 (reader->curnode->type == XML_NAMESPACE_DECL))
3137 return(reader->depth + 1);
3138 return(reader->depth + 2);
3139 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003140 return(reader->depth);
3141}
3142
3143/**
3144 * xmlTextReaderHasAttributes:
3145 * @reader: the xmlTextReaderPtr used
3146 *
3147 * Whether the node has attributes.
3148 *
3149 * Returns 1 if true, 0 if false, and -1 in case or error
3150 */
3151int
3152xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003153 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003154 if (reader == NULL)
3155 return(-1);
3156 if (reader->node == NULL)
3157 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003158 if (reader->curnode != NULL)
3159 node = reader->curnode;
3160 else
3161 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003162
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003163 if ((node->type == XML_ELEMENT_NODE) &&
3164 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003165 return(1);
3166 /* TODO: handle the xmlDecl */
3167 return(0);
3168}
3169
3170/**
3171 * xmlTextReaderHasValue:
3172 * @reader: the xmlTextReaderPtr used
3173 *
3174 * Whether the node can have a text value.
3175 *
3176 * Returns 1 if true, 0 if false, and -1 in case or error
3177 */
3178int
3179xmlTextReaderHasValue(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 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003191 case XML_ATTRIBUTE_NODE:
3192 case XML_TEXT_NODE:
3193 case XML_CDATA_SECTION_NODE:
3194 case XML_PI_NODE:
3195 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003196 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003197 return(1);
3198 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003199 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003200 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003201 return(0);
3202}
3203
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003204/**
3205 * xmlTextReaderValue:
3206 * @reader: the xmlTextReaderPtr used
3207 *
3208 * Provides the text value of the node if present
3209 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003210 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003211 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003212 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003213xmlChar *
3214xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003215 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003216 if (reader == NULL)
3217 return(NULL);
3218 if (reader->node == NULL)
3219 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003220 if (reader->curnode != NULL)
3221 node = reader->curnode;
3222 else
3223 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003224
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003225 switch (node->type) {
3226 case XML_NAMESPACE_DECL:
3227 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003228 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003229 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003230
3231 if (attr->parent != NULL)
3232 return (xmlNodeListGetString
3233 (attr->parent->doc, attr->children, 1));
3234 else
3235 return (xmlNodeListGetString(NULL, attr->children, 1));
3236 break;
3237 }
3238 case XML_TEXT_NODE:
3239 case XML_CDATA_SECTION_NODE:
3240 case XML_PI_NODE:
3241 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003242 if (node->content != NULL)
3243 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003244 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003245 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003246 }
3247 return(NULL);
3248}
3249
3250/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003251 * xmlTextReaderConstValue:
3252 * @reader: the xmlTextReaderPtr used
3253 *
3254 * Provides the text value of the node if present
3255 *
3256 * Returns the string or NULL if not available. The result will be
3257 * deallocated on the next Read() operation.
3258 */
3259const xmlChar *
3260xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3261 xmlNodePtr node;
3262 if (reader == NULL)
3263 return(NULL);
3264 if (reader->node == NULL)
3265 return(NULL);
3266 if (reader->curnode != NULL)
3267 node = reader->curnode;
3268 else
3269 node = reader->node;
3270
3271 switch (node->type) {
3272 case XML_NAMESPACE_DECL:
3273 return(((xmlNsPtr) node)->href);
3274 case XML_ATTRIBUTE_NODE:{
3275 xmlAttrPtr attr = (xmlAttrPtr) node;
3276
3277 if ((attr->children != NULL) &&
3278 (attr->children->type == XML_TEXT_NODE) &&
3279 (attr->children->next == NULL))
3280 return(attr->children->content);
3281 else {
3282 reader->buffer->use = 0;
3283 xmlNodeBufGetContent(reader->buffer, node);
3284 return(reader->buffer->content);
3285 }
3286 break;
3287 }
3288 case XML_TEXT_NODE:
3289 case XML_CDATA_SECTION_NODE:
3290 case XML_PI_NODE:
3291 case XML_COMMENT_NODE:
3292 return(node->content);
3293 default:
3294 break;
3295 }
3296 return(NULL);
3297}
3298
3299/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003300 * xmlTextReaderIsDefault:
3301 * @reader: the xmlTextReaderPtr used
3302 *
3303 * Whether an Attribute node was generated from the default value
3304 * defined in the DTD or schema.
3305 *
3306 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3307 */
3308int
3309xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3310 if (reader == NULL)
3311 return(-1);
3312 return(0);
3313}
3314
3315/**
3316 * xmlTextReaderQuoteChar:
3317 * @reader: the xmlTextReaderPtr used
3318 *
3319 * The quotation mark character used to enclose the value of an attribute.
3320 *
3321 * Returns " or ' and -1 in case of error
3322 */
3323int
3324xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3325 if (reader == NULL)
3326 return(-1);
3327 /* TODO maybe lookup the attribute value for " first */
3328 return((int) '"');
3329}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003330
3331/**
3332 * xmlTextReaderXmlLang:
3333 * @reader: the xmlTextReaderPtr used
3334 *
3335 * The xml:lang scope within which the node resides.
3336 *
3337 * Returns the xml:lang value or NULL if none exists.
3338 */
3339xmlChar *
3340xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3341 if (reader == NULL)
3342 return(NULL);
3343 if (reader->node == NULL)
3344 return(NULL);
3345 return(xmlNodeGetLang(reader->node));
3346}
3347
Daniel Veillard67df8092002-12-16 22:04:11 +00003348/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003349 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003350 * @reader: the xmlTextReaderPtr used
3351 *
3352 * The xml:lang scope within which the node resides.
3353 *
3354 * Returns the xml:lang value or NULL if none exists.
3355 */
3356const xmlChar *
3357xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3358 xmlChar *tmp;
3359 const xmlChar *ret;
3360
3361 if (reader == NULL)
3362 return(NULL);
3363 if (reader->node == NULL)
3364 return(NULL);
3365 tmp = xmlNodeGetLang(reader->node);
3366 if (tmp == NULL)
3367 return(NULL);
3368 ret = CONSTSTR(tmp);
3369 xmlFree(tmp);
3370 return(ret);
3371}
3372
3373/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003374 * xmlTextReaderConstString:
3375 * @reader: the xmlTextReaderPtr used
3376 * @str: the string to intern.
3377 *
3378 * Get an interned string from the reader, allows for example to
3379 * speedup string name comparisons
3380 *
3381 * Returns an interned copy of the string or NULL in case of error. The
3382 * string will be deallocated with the reader.
3383 */
3384const xmlChar *
3385xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3386 if (reader == NULL)
3387 return(NULL);
3388 return(CONSTSTR(str));
3389}
3390
3391/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003392 * xmlTextReaderNormalization:
3393 * @reader: the xmlTextReaderPtr used
3394 *
3395 * The value indicating whether to normalize white space and attribute values.
3396 * Since attribute value and end of line normalizations are a MUST in the XML
3397 * specification only the value true is accepted. The broken bahaviour of
3398 * accepting out of range character entities like &#0; is of course not
3399 * supported either.
3400 *
3401 * Returns 1 or -1 in case of error.
3402 */
3403int
3404xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3405 if (reader == NULL)
3406 return(-1);
3407 return(1);
3408}
3409
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003410/************************************************************************
3411 * *
3412 * Extensions to the base APIs *
3413 * *
3414 ************************************************************************/
3415
3416/**
3417 * xmlTextReaderSetParserProp:
3418 * @reader: the xmlTextReaderPtr used
3419 * @prop: the xmlParserProperties to set
3420 * @value: usually 0 or 1 to (de)activate it
3421 *
3422 * Change the parser processing behaviour by changing some of its internal
3423 * properties. Note that some properties can only be changed before any
3424 * read has been done.
3425 *
3426 * Returns 0 if the call was successful, or -1 in case of error
3427 */
3428int
3429xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3430 xmlParserProperties p = (xmlParserProperties) prop;
3431 xmlParserCtxtPtr ctxt;
3432
3433 if ((reader == NULL) || (reader->ctxt == NULL))
3434 return(-1);
3435 ctxt = reader->ctxt;
3436
3437 switch (p) {
3438 case XML_PARSER_LOADDTD:
3439 if (value != 0) {
3440 if (ctxt->loadsubset == 0) {
3441 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3442 return(-1);
3443 ctxt->loadsubset = XML_DETECT_IDS;
3444 }
3445 } else {
3446 ctxt->loadsubset = 0;
3447 }
3448 return(0);
3449 case XML_PARSER_DEFAULTATTRS:
3450 if (value != 0) {
3451 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3452 } else {
3453 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3454 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3455 }
3456 return(0);
3457 case XML_PARSER_VALIDATE:
3458 if (value != 0) {
3459 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003460 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003461 } else {
3462 ctxt->validate = 0;
3463 }
3464 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003465 case XML_PARSER_SUBST_ENTITIES:
3466 if (value != 0) {
3467 ctxt->replaceEntities = 1;
3468 } else {
3469 ctxt->replaceEntities = 0;
3470 }
3471 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003472 }
3473 return(-1);
3474}
3475
3476/**
3477 * xmlTextReaderGetParserProp:
3478 * @reader: the xmlTextReaderPtr used
3479 * @prop: the xmlParserProperties to get
3480 *
3481 * Read the parser internal property.
3482 *
3483 * Returns the value, usually 0 or 1, or -1 in case of error.
3484 */
3485int
3486xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3487 xmlParserProperties p = (xmlParserProperties) prop;
3488 xmlParserCtxtPtr ctxt;
3489
3490 if ((reader == NULL) || (reader->ctxt == NULL))
3491 return(-1);
3492 ctxt = reader->ctxt;
3493
3494 switch (p) {
3495 case XML_PARSER_LOADDTD:
3496 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3497 return(1);
3498 return(0);
3499 case XML_PARSER_DEFAULTATTRS:
3500 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3501 return(1);
3502 return(0);
3503 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003504 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003505 case XML_PARSER_SUBST_ENTITIES:
3506 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003507 }
3508 return(-1);
3509}
3510
Daniel Veillarde18fc182002-12-28 22:56:33 +00003511/**
3512 * xmlTextReaderCurrentNode:
3513 * @reader: the xmlTextReaderPtr used
3514 *
3515 * Hacking interface allowing to get the xmlNodePtr correponding to the
3516 * current node being accessed by the xmlTextReader. This is dangerous
3517 * because the underlying node may be destroyed on the next Reads.
3518 *
3519 * Returns the xmlNodePtr or NULL in case of error.
3520 */
3521xmlNodePtr
3522xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3523 if (reader == NULL)
3524 return(NULL);
3525
3526 if (reader->curnode != NULL)
3527 return(reader->curnode);
3528 return(reader->node);
3529}
3530
3531/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003532 * xmlTextReaderPreserve:
3533 * @reader: the xmlTextReaderPtr used
3534 *
3535 *
3536 * current node being accessed by the xmlTextReader. This is dangerous
3537 * because the underlying node may be destroyed on the next Reads.
3538 *
3539 * Returns the xmlNodePtr or NULL in case of error.
3540 */
3541xmlNodePtr
3542xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3543 xmlNodePtr cur, parent;
3544
3545 if (reader == NULL)
3546 return(NULL);
3547
3548 if (reader->curnode != NULL)
3549 cur = reader->curnode;
3550 else
3551 cur = reader->node;
3552 if (cur == NULL)
3553 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003554
3555 if (cur->type != XML_DOCUMENT_NODE) {
3556 cur->extra |= NODE_IS_PRESERVED;
3557 cur->extra |= NODE_IS_SPRESERVED;
3558 }
3559 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003560
3561 parent = cur->parent;;
3562 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003563 if (parent->type == XML_ELEMENT_NODE)
3564 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003565 parent = parent->parent;
3566 }
3567 return(cur);
3568}
3569
Daniel Veillard1e906612003-12-05 14:57:46 +00003570#ifdef LIBXML_PATTERN_ENABLED
3571/**
3572 * xmlTextReaderPreservePattern:
3573 * @reader: the xmlTextReaderPtr used
3574 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003575 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003576 *
3577 * This tells the XML Reader to preserve all nodes matched by the
3578 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3579 * keep an handle on the resulting document once parsing has finished
3580 *
3581 * Returns a positive number in case of success and -1 in case of error
3582 */
3583int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003584xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3585 const xmlChar **namespaces)
3586{
Daniel Veillard1e906612003-12-05 14:57:46 +00003587 xmlPatternPtr comp;
3588
3589 if ((reader == NULL) || (pattern == NULL))
3590 return(-1);
3591
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003592 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003593 if (comp == NULL)
3594 return(-1);
3595
3596 if (reader->patternMax <= 0) {
3597 reader->patternMax = 4;
3598 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3599 sizeof(reader->patternTab[0]));
3600 if (reader->patternTab == NULL) {
3601 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3602 return (-1);
3603 }
3604 }
3605 if (reader->patternNr >= reader->patternMax) {
3606 xmlPatternPtr *tmp;
3607 reader->patternMax *= 2;
3608 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3609 reader->patternMax *
3610 sizeof(reader->patternTab[0]));
3611 if (tmp == NULL) {
3612 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3613 reader->patternMax /= 2;
3614 return (-1);
3615 }
3616 reader->patternTab = tmp;
3617 }
3618 reader->patternTab[reader->patternNr] = comp;
3619 return(reader->patternNr++);
3620}
3621#endif
3622
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003623/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003624 * xmlTextReaderCurrentDoc:
3625 * @reader: the xmlTextReaderPtr used
3626 *
3627 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003628 * current document being accessed by the xmlTextReader.
3629 * NOTE: as a result of this call, the reader will not destroy the
3630 * associated XML document and calling xmlFreeDoc() on the result
3631 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003632 *
3633 * Returns the xmlDocPtr or NULL in case of error.
3634 */
3635xmlDocPtr
3636xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003637 if (reader == NULL)
3638 return(NULL);
3639 if (reader->doc != NULL)
3640 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003641 if ((reader == NULL) || (reader->ctxt == NULL) ||
3642 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003643 return(NULL);
3644
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003645 reader->preserve = 1;
3646 if ((reader->ctxt->myDoc->dict != NULL) &&
3647 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3648 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003649 return(reader->ctxt->myDoc);
3650}
3651
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003652#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003653/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003654 * xmlTextReaderRelaxNGSetSchema:
3655 * @reader: the xmlTextReaderPtr used
3656 * @schema: a precompiled RelaxNG schema
3657 *
3658 * Use RelaxNG to validate the document as it is processed.
3659 * Activation is only possible before the first Read().
3660 * if @schema is NULL, then RelaxNG validation is desactivated.
3661 @ The @schema should not be freed until the reader is deallocated
3662 * or its use has been deactivated.
3663 *
3664 * Returns 0 in case the RelaxNG validation could be (des)activated and
3665 * -1 in case of error.
3666 */
3667int
3668xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3669 if (schema == NULL) {
3670 if (reader->rngSchemas != NULL) {
3671 xmlRelaxNGFree(reader->rngSchemas);
3672 reader->rngSchemas = NULL;
3673 }
3674 if (reader->rngValidCtxt != NULL) {
3675 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3676 reader->rngValidCtxt = NULL;
3677 }
3678 return(0);
3679 }
3680 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3681 return(-1);
3682 if (reader->rngSchemas != NULL) {
3683 xmlRelaxNGFree(reader->rngSchemas);
3684 reader->rngSchemas = NULL;
3685 }
3686 if (reader->rngValidCtxt != NULL) {
3687 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3688 reader->rngValidCtxt = NULL;
3689 }
3690 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3691 if (reader->rngValidCtxt == NULL)
3692 return(-1);
3693 if (reader->errorFunc != NULL) {
3694 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3695 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3696 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3697 reader->errorFuncArg);
3698 }
3699 reader->rngValidErrors = 0;
3700 reader->rngFullNode = NULL;
3701 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3702 return(0);
3703}
3704
3705/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003706 * xmlTextReaderRelaxNGValidate:
3707 * @reader: the xmlTextReaderPtr used
3708 * @rng: the path to a RelaxNG schema or NULL
3709 *
3710 * Use RelaxNG to validate the document as it is processed.
3711 * Activation is only possible before the first Read().
3712 * if @rng is NULL, then RelaxNG validation is desactivated.
3713 *
3714 * Returns 0 in case the RelaxNG validation could be (des)activated and
3715 * -1 in case of error.
3716 */
3717int
3718xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3719 xmlRelaxNGParserCtxtPtr ctxt;
3720
3721 if (reader == NULL)
3722 return(-1);
3723
3724 if (rng == NULL) {
3725 if (reader->rngSchemas != NULL) {
3726 xmlRelaxNGFree(reader->rngSchemas);
3727 reader->rngSchemas = NULL;
3728 }
3729 if (reader->rngValidCtxt != NULL) {
3730 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3731 reader->rngValidCtxt = NULL;
3732 }
3733 return(0);
3734 }
3735 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3736 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003737 if (reader->rngSchemas != NULL) {
3738 xmlRelaxNGFree(reader->rngSchemas);
3739 reader->rngSchemas = NULL;
3740 }
3741 if (reader->rngValidCtxt != NULL) {
3742 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3743 reader->rngValidCtxt = NULL;
3744 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003745 ctxt = xmlRelaxNGNewParserCtxt(rng);
3746 if (reader->errorFunc != NULL) {
3747 xmlRelaxNGSetParserErrors(ctxt,
3748 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3749 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3750 reader->errorFuncArg);
3751 }
3752 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3753 xmlRelaxNGFreeParserCtxt(ctxt);
3754 if (reader->rngSchemas == NULL)
3755 return(-1);
3756 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3757 if (reader->rngValidCtxt == NULL)
3758 return(-1);
3759 if (reader->errorFunc != NULL) {
3760 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3761 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3762 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3763 reader->errorFuncArg);
3764 }
3765 reader->rngValidErrors = 0;
3766 reader->rngFullNode = NULL;
3767 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3768 return(0);
3769}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003770#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003771
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003772/************************************************************************
3773 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003774 * Error Handling Extensions *
3775 * *
3776 ************************************************************************/
3777
3778/* helper to build a xmlMalloc'ed string from a format and va_list */
3779static char *
3780xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3781 int size;
3782 int chars;
3783 char *larger;
3784 char *str;
3785
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003786 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003787 if (str == NULL) {
3788 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3789 return NULL;
3790 }
3791
3792 size = 150;
3793
3794 while (1) {
3795 chars = vsnprintf(str, size, msg, ap);
3796 if ((chars > -1) && (chars < size))
3797 break;
3798 if (chars > -1)
3799 size += chars + 1;
3800 else
3801 size += 100;
3802 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3803 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3804 xmlFree(str);
3805 return NULL;
3806 }
3807 str = larger;
3808 }
3809
3810 return str;
3811}
3812
Daniel Veillard417be3a2003-01-20 21:26:34 +00003813/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003814 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003815 * @locator: the xmlTextReaderLocatorPtr used
3816 *
3817 * Obtain the line number for the given locator.
3818 *
3819 * Returns the line number or -1 in case of error.
3820 */
3821int
3822xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3823 /* we know that locator is a xmlParserCtxtPtr */
3824 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3825 int ret = -1;
3826
3827 if (ctx->node != NULL) {
3828 ret = xmlGetLineNo(ctx->node);
3829 }
3830 else {
3831 /* inspired from error.c */
3832 xmlParserInputPtr input;
3833 input = ctx->input;
3834 if ((input->filename == NULL) && (ctx->inputNr > 1))
3835 input = ctx->inputTab[ctx->inputNr - 2];
3836 if (input != NULL) {
3837 ret = input->line;
3838 }
3839 else {
3840 ret = -1;
3841 }
3842 }
3843
3844 return ret;
3845}
3846
3847/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003848 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003849 * @locator: the xmlTextReaderLocatorPtr used
3850 *
3851 * Obtain the base URI for the given locator.
3852 *
3853 * Returns the base URI or NULL in case of error.
3854 */
3855xmlChar *
3856xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3857 /* we know that locator is a xmlParserCtxtPtr */
3858 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3859 xmlChar *ret = NULL;
3860
3861 if (ctx->node != NULL) {
3862 ret = xmlNodeGetBase(NULL,ctx->node);
3863 }
3864 else {
3865 /* inspired from error.c */
3866 xmlParserInputPtr input;
3867 input = ctx->input;
3868 if ((input->filename == NULL) && (ctx->inputNr > 1))
3869 input = ctx->inputTab[ctx->inputNr - 2];
3870 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003871 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003872 }
3873 else {
3874 ret = NULL;
3875 }
3876 }
3877
3878 return ret;
3879}
3880
Daniel Veillard26f70262003-01-16 22:45:08 +00003881static void
William M. Brack899e64a2003-09-26 18:03:42 +00003882xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003883 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3884 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3885
3886 if (str != NULL) {
3887 reader->errorFunc(reader->errorFuncArg,
3888 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003889 severity,
3890 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003891 xmlFree(str);
3892 }
3893}
3894
3895static void
William M. Brack93d004f2004-02-03 00:14:10 +00003896xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3897 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3898 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3899
3900 if (error && reader->sErrorFunc) {
3901 reader->sErrorFunc(reader->errorFuncArg,
3902 (xmlErrorPtr) error);
3903 }
3904}
3905
3906static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003907xmlTextReaderError(void *ctxt, const char *msg, ...) {
3908 va_list ap;
3909
3910 va_start(ap,msg);
3911 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003912 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003913 xmlTextReaderBuildMessage(msg,ap));
3914 va_end(ap);
3915
3916}
3917
3918static void
3919xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3920 va_list ap;
3921
3922 va_start(ap,msg);
3923 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003924 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003925 xmlTextReaderBuildMessage(msg,ap));
3926 va_end(ap);
3927}
3928
3929static void
3930xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3931 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003932 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003933
Daniel Veillard417be3a2003-01-20 21:26:34 +00003934 if ((len > 1) && (msg[len - 2] != ':')) {
3935 /*
3936 * some callbacks only report locator information:
3937 * skip them (mimicking behaviour in error.c)
3938 */
3939 va_start(ap,msg);
3940 xmlTextReaderGenericError(ctxt,
3941 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3942 xmlTextReaderBuildMessage(msg,ap));
3943 va_end(ap);
3944 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003945}
3946
3947static void
3948xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3949 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003950 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003951
Daniel Veillard417be3a2003-01-20 21:26:34 +00003952 if ((len != 0) && (msg[len - 1] != ':')) {
3953 /*
3954 * some callbacks only report locator information:
3955 * skip them (mimicking behaviour in error.c)
3956 */
3957 va_start(ap,msg);
3958 xmlTextReaderGenericError(ctxt,
3959 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3960 xmlTextReaderBuildMessage(msg,ap));
3961 va_end(ap);
3962 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003963}
3964
3965/**
3966 * xmlTextReaderSetErrorHandler:
3967 * @reader: the xmlTextReaderPtr used
3968 * @f: the callback function to call on error and warnings
3969 * @arg: a user argument to pass to the callback function
3970 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003971 * Register a callback function that will be called on error and warnings.
3972 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003973 * If @f is NULL, the default error and warning handlers are restored.
3974 */
3975void
3976xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3977 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003978 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003979 if (f != NULL) {
3980 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003981 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003982 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3983 reader->ctxt->sax->warning = xmlTextReaderWarning;
3984 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3985 reader->errorFunc = f;
3986 reader->errorFuncArg = arg;
3987 }
3988 else {
3989 /* restore defaults */
3990 reader->ctxt->sax->error = xmlParserError;
3991 reader->ctxt->vctxt.error = xmlParserValidityError;
3992 reader->ctxt->sax->warning = xmlParserWarning;
3993 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3994 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00003995 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003996 reader->errorFuncArg = NULL;
3997 }
3998}
3999
Daniel Veillard417be3a2003-01-20 21:26:34 +00004000/**
William M. Brack93d004f2004-02-03 00:14:10 +00004001* xmlTextReaderSetStructuredErrorHandler:
4002 * @reader: the xmlTextReaderPtr used
4003 * @f: the callback function to call on error and warnings
4004 * @arg: a user argument to pass to the callback function
4005 *
4006 * Register a callback function that will be called on error and warnings.
4007 *
4008 * If @f is NULL, the default error and warning handlers are restored.
4009 */
4010void
4011xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4012 xmlStructuredErrorFunc f,
4013 void *arg) {
4014 if (f != NULL) {
4015 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4016 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4017 reader->ctxt->sax->warning = xmlTextReaderWarning;
4018 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4019 reader->sErrorFunc = f;
4020 reader->errorFunc = NULL;
4021 reader->errorFuncArg = arg;
4022 }
4023 else {
4024 /* restore defaults */
4025 reader->ctxt->sax->error = xmlParserError;
4026 reader->ctxt->sax->serror = NULL;
4027 reader->ctxt->vctxt.error = xmlParserValidityError;
4028 reader->ctxt->sax->warning = xmlParserWarning;
4029 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4030 reader->errorFunc = NULL;
4031 reader->sErrorFunc = NULL;
4032 reader->errorFuncArg = NULL;
4033 }
4034}
4035
4036/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004037 * xmlTextReaderIsValid:
4038 * @reader: the xmlTextReaderPtr used
4039 *
4040 * Retrieve the validity status from the parser context
4041 *
4042 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4043 */
4044int
4045xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004046 if (reader == NULL) return(-1);
4047#ifdef LIBXML_SCHEMAS_ENABLED
4048 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4049 return(reader->rngValidErrors == 0);
4050#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004051 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004052 return(reader->ctxt->valid);
4053 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004054}
4055
4056/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004057 * xmlTextReaderGetErrorHandler:
4058 * @reader: the xmlTextReaderPtr used
4059 * @f: the callback function or NULL is no callback has been registered
4060 * @arg: a user argument
4061 *
4062 * Retrieve the error callback function and user argument.
4063 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004064void
4065xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4066 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004067 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004068 *f = reader->errorFunc;
4069 *arg = reader->errorFuncArg;
4070}
4071
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004072
4073/************************************************************************
4074 * *
4075 * New set (2.6.0) of simpler and more flexible APIs *
4076 * *
4077 ************************************************************************/
4078
4079/**
4080 * xmlTextReaderSetup:
4081 * @reader: an XML reader
4082 * @URL: the base URL to use for the document
4083 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004084 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004085 * @reuse: keep the context for reuse
4086 *
4087 * Setup an XML reader with new options
4088 *
4089 * Returns 0 in case of success and -1 in case of error.
4090 */
4091static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004092xmlTextReaderSetup(xmlTextReaderPtr reader,
4093 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004094 const char *encoding, int options)
4095{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004096 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004097 return (-1);
4098
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004099 reader->doc = NULL;
4100 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004101 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004102 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004103 if ((input != NULL) && (reader->input != NULL) &&
4104 (reader->allocs & XML_TEXTREADER_INPUT)) {
4105 xmlFreeParserInputBuffer(reader->input);
4106 reader->input = NULL;
4107 reader->allocs -= XML_TEXTREADER_INPUT;
4108 }
4109 if (input != NULL) {
4110 reader->input = input;
4111 reader->allocs |= XML_TEXTREADER_INPUT;
4112 }
4113 if (reader->buffer == NULL)
4114 reader->buffer = xmlBufferCreateSize(100);
4115 if (reader->buffer == NULL) {
4116 xmlGenericError(xmlGenericErrorContext,
4117 "xmlTextReaderSetup : malloc failed\n");
4118 return (-1);
4119 }
4120 if (reader->sax == NULL)
4121 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4122 if (reader->sax == NULL) {
4123 xmlGenericError(xmlGenericErrorContext,
4124 "xmlTextReaderSetup : malloc failed\n");
4125 return (-1);
4126 }
4127 xmlSAXVersion(reader->sax, 2);
4128 reader->startElement = reader->sax->startElement;
4129 reader->sax->startElement = xmlTextReaderStartElement;
4130 reader->endElement = reader->sax->endElement;
4131 reader->sax->endElement = xmlTextReaderEndElement;
4132#ifdef LIBXML_SAX1_ENABLED
4133 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4134#endif /* LIBXML_SAX1_ENABLED */
4135 reader->startElementNs = reader->sax->startElementNs;
4136 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4137 reader->endElementNs = reader->sax->endElementNs;
4138 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4139#ifdef LIBXML_SAX1_ENABLED
4140 } else {
4141 reader->startElementNs = NULL;
4142 reader->endElementNs = NULL;
4143 }
4144#endif /* LIBXML_SAX1_ENABLED */
4145 reader->characters = reader->sax->characters;
4146 reader->sax->characters = xmlTextReaderCharacters;
4147 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4148 reader->cdataBlock = reader->sax->cdataBlock;
4149 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4150
4151 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4152 reader->node = NULL;
4153 reader->curnode = NULL;
4154 if (input != NULL) {
4155 if (reader->input->buffer->use < 4) {
4156 xmlParserInputBufferRead(input, 4);
4157 }
4158 if (reader->ctxt == NULL) {
4159 if (reader->input->buffer->use >= 4) {
4160 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4161 (const char *) reader->input->buffer->content, 4, URL);
4162 reader->base = 0;
4163 reader->cur = 4;
4164 } else {
4165 reader->ctxt =
4166 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4167 reader->base = 0;
4168 reader->cur = 0;
4169 }
4170 } else {
4171 xmlParserInputPtr inputStream;
4172 xmlParserInputBufferPtr buf;
4173 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4174
4175 if (reader->ctxt->myDoc != NULL)
4176 xmlDictReference(reader->ctxt->myDoc->dict);
4177 xmlCtxtReset(reader->ctxt);
4178 buf = xmlAllocParserInputBuffer(enc);
4179 if (buf == NULL) return(-1);
4180 inputStream = xmlNewInputStream(reader->ctxt);
4181 if (inputStream == NULL) {
4182 xmlFreeParserInputBuffer(buf);
4183 return(-1);
4184 }
4185
4186 if (URL == NULL)
4187 inputStream->filename = NULL;
4188 else
4189 inputStream->filename = (char *)
4190 xmlCanonicPath((const xmlChar *) URL);
4191 inputStream->buf = buf;
4192 inputStream->base = inputStream->buf->buffer->content;
4193 inputStream->cur = inputStream->buf->buffer->content;
4194 inputStream->end =
4195 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4196
4197 inputPush(reader->ctxt, inputStream);
4198 reader->cur = 0;
4199 }
4200 if (reader->ctxt == NULL) {
4201 xmlGenericError(xmlGenericErrorContext,
4202 "xmlTextReaderSetup : malloc failed\n");
4203 return (-1);
4204 }
4205 }
4206 if (reader->dict != NULL) {
4207 if (reader->ctxt->dict != NULL) {
4208 if (reader->dict != reader->ctxt->dict) {
4209 xmlDictFree(reader->dict);
4210 reader->dict = reader->ctxt->dict;
4211 }
4212 } else {
4213 reader->ctxt->dict = reader->dict;
4214 }
4215 } else {
4216 if (reader->ctxt->dict == NULL)
4217 reader->ctxt->dict = xmlDictCreate();
4218 reader->dict = reader->ctxt->dict;
4219 }
4220 reader->ctxt->_private = reader;
4221 reader->ctxt->linenumbers = 1;
4222 reader->ctxt->dictNames = 1;
4223 /*
4224 * use the parser dictionnary to allocate all elements and attributes names
4225 */
4226 reader->ctxt->docdict = 1;
4227
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004228#ifdef LIBXML_XINCLUDE_ENABLED
4229 if (reader->xincctxt != NULL) {
4230 xmlXIncludeFreeContext(reader->xincctxt);
4231 reader->xincctxt = NULL;
4232 }
4233 if (options & XML_PARSE_XINCLUDE) {
4234 reader->xinclude = 1;
4235 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4236 options -= XML_PARSE_XINCLUDE;
4237 } else
4238 reader->xinclude = 0;
4239 reader->in_xinclude = 0;
4240#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004241#ifdef LIBXML_PATTERN_ENABLED
4242 if (reader->patternTab == NULL) {
4243 reader->patternNr = 0;
4244 reader->patternMax = 0;
4245 }
4246 while (reader->patternNr > 0) {
4247 reader->patternNr--;
4248 if (reader->patternTab[reader->patternNr] != NULL) {
4249 xmlFreePattern(reader->patternTab[reader->patternNr]);
4250 reader->patternTab[reader->patternNr] = NULL;
4251 }
4252 }
4253#endif
4254
Daniel Veillardc36965d2003-12-02 10:28:48 +00004255 if (options & XML_PARSE_DTDVALID)
4256 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4257
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004258 xmlCtxtUseOptions(reader->ctxt, options);
4259 if (encoding != NULL) {
4260 xmlCharEncodingHandlerPtr hdlr;
4261
4262 hdlr = xmlFindCharEncodingHandler(encoding);
4263 if (hdlr != NULL)
4264 xmlSwitchToEncoding(reader->ctxt, hdlr);
4265 }
4266 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4267 (reader->ctxt->input->filename == NULL))
4268 reader->ctxt->input->filename = (char *)
4269 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004270
4271 reader->doc = NULL;
4272
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004273 return (0);
4274}
4275
4276/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004277 * xmlReaderWalker:
4278 * @doc: a preparsed document
4279 *
4280 * Create an xmltextReader for a preparsed document.
4281 *
4282 * Returns the new reader or NULL in case of error.
4283 */
4284xmlTextReaderPtr
4285xmlReaderWalker(xmlDocPtr doc)
4286{
4287 xmlTextReaderPtr ret;
4288
4289 if (doc == NULL)
4290 return(NULL);
4291
4292 ret = xmlMalloc(sizeof(xmlTextReader));
4293 if (ret == NULL) {
4294 xmlGenericError(xmlGenericErrorContext,
4295 "xmlNewTextReader : malloc failed\n");
4296 return(NULL);
4297 }
4298 memset(ret, 0, sizeof(xmlTextReader));
4299 ret->entNr = 0;
4300 ret->input = NULL;
4301 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4302 ret->node = NULL;
4303 ret->curnode = NULL;
4304 ret->base = 0;
4305 ret->cur = 0;
4306 ret->allocs = XML_TEXTREADER_CTXT;
4307 ret->doc = doc;
4308 ret->state = XML_TEXTREADER_START;
4309 ret->dict = xmlDictCreate();
4310 return(ret);
4311}
4312
4313/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004314 * xmlReaderForDoc:
4315 * @cur: a pointer to a zero terminated string
4316 * @URL: the base URL to use for the document
4317 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004318 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004319 *
4320 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004321 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004322 *
4323 * Returns the new reader or NULL in case of error.
4324 */
4325xmlTextReaderPtr
4326xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4327 int options)
4328{
4329 int len;
4330
4331 if (cur == NULL)
4332 return (NULL);
4333 len = xmlStrlen(cur);
4334
4335 return (xmlReaderForMemory
4336 ((const char *) cur, len, URL, encoding, options));
4337}
4338
4339/**
4340 * xmlReaderForFile:
4341 * @filename: a file or URL
4342 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004343 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004344 *
4345 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004346 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004347 *
4348 * Returns the new reader or NULL in case of error.
4349 */
4350xmlTextReaderPtr
4351xmlReaderForFile(const char *filename, const char *encoding, int options)
4352{
4353 xmlTextReaderPtr reader;
4354
4355 reader = xmlNewTextReaderFilename(filename);
4356 if (reader == NULL)
4357 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004358 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004359 return (reader);
4360}
4361
4362/**
4363 * xmlReaderForMemory:
4364 * @buffer: a pointer to a char array
4365 * @size: the size of the array
4366 * @URL: the base URL to use for the document
4367 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004368 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004369 *
4370 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004371 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004372 *
4373 * Returns the new reader or NULL in case of error.
4374 */
4375xmlTextReaderPtr
4376xmlReaderForMemory(const char *buffer, int size, const char *URL,
4377 const char *encoding, int options)
4378{
4379 xmlTextReaderPtr reader;
4380 xmlParserInputBufferPtr buf;
4381
4382 buf =
4383 xmlParserInputBufferCreateMem(buffer, size,
4384 XML_CHAR_ENCODING_NONE);
4385 if (buf == NULL) {
4386 return (NULL);
4387 }
4388 reader = xmlNewTextReader(buf, URL);
4389 if (reader == NULL) {
4390 xmlFreeParserInputBuffer(buf);
4391 return (NULL);
4392 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004393 reader->allocs |= XML_TEXTREADER_INPUT;
4394 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004395 return (reader);
4396}
4397
4398/**
4399 * xmlReaderForFd:
4400 * @fd: an open file descriptor
4401 * @URL: the base URL to use for the document
4402 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004403 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004404 *
4405 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004406 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004407 * NOTE that the file descriptor will not be closed when the
4408 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004409 *
4410 * Returns the new reader or NULL in case of error.
4411 */
4412xmlTextReaderPtr
4413xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4414{
4415 xmlTextReaderPtr reader;
4416 xmlParserInputBufferPtr input;
4417
4418 if (fd < 0)
4419 return (NULL);
4420
4421 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4422 if (input == NULL)
4423 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004424 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004425 reader = xmlNewTextReader(input, URL);
4426 if (reader == NULL) {
4427 xmlFreeParserInputBuffer(input);
4428 return (NULL);
4429 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004430 reader->allocs |= XML_TEXTREADER_INPUT;
4431 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004432 return (reader);
4433}
4434
4435/**
4436 * xmlReaderForIO:
4437 * @ioread: an I/O read function
4438 * @ioclose: an I/O close function
4439 * @ioctx: an I/O handler
4440 * @URL: the base URL to use for the document
4441 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004442 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004443 *
4444 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004445 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004446 *
4447 * Returns the new reader or NULL in case of error.
4448 */
4449xmlTextReaderPtr
4450xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4451 void *ioctx, const char *URL, const char *encoding,
4452 int options)
4453{
4454 xmlTextReaderPtr reader;
4455 xmlParserInputBufferPtr input;
4456
4457 if (ioread == NULL)
4458 return (NULL);
4459
4460 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4461 XML_CHAR_ENCODING_NONE);
4462 if (input == NULL)
4463 return (NULL);
4464 reader = xmlNewTextReader(input, URL);
4465 if (reader == NULL) {
4466 xmlFreeParserInputBuffer(input);
4467 return (NULL);
4468 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004469 reader->allocs |= XML_TEXTREADER_INPUT;
4470 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004471 return (reader);
4472}
4473
4474/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004475 * xmlReaderNewWalker:
4476 * @reader: an XML reader
4477 * @doc: a preparsed document
4478 *
4479 * Setup an xmltextReader to parse a preparsed XML document.
4480 * This reuses the existing @reader xmlTextReader.
4481 *
4482 * Returns 0 in case of success and -1 in case of error
4483 */
4484int
4485xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4486{
4487 if (doc == NULL)
4488 return (-1);
4489 if (reader == NULL)
4490 return (-1);
4491
4492 if (reader->ctxt != NULL) {
4493 xmlCtxtReset(reader->ctxt);
4494 }
4495
4496 reader->entNr = 0;
4497 reader->input = NULL;
4498 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4499 reader->node = NULL;
4500 reader->curnode = NULL;
4501 reader->base = 0;
4502 reader->cur = 0;
4503 reader->allocs = XML_TEXTREADER_CTXT;
4504 reader->doc = doc;
4505 reader->state = XML_TEXTREADER_START;
4506 if (reader->dict == NULL) {
4507 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4508 reader->dict = reader->ctxt->dict;
4509 else
4510 reader->dict = xmlDictCreate();
4511 }
4512 return(0);
4513}
4514
4515/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004516 * xmlReaderNewDoc:
4517 * @reader: an XML reader
4518 * @cur: a pointer to a zero terminated string
4519 * @URL: the base URL to use for the document
4520 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004521 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004522 *
4523 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004524 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004525 * This reuses the existing @reader xmlTextReader.
4526 *
4527 * Returns 0 in case of success and -1 in case of error
4528 */
4529int
4530xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4531 const char *URL, const char *encoding, int options)
4532{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004533
4534 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004535
4536 if (cur == NULL)
4537 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004538 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004539 return (-1);
4540
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004541 len = xmlStrlen(cur);
4542 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4543 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004544}
4545
4546/**
4547 * xmlReaderNewFile:
4548 * @reader: an XML reader
4549 * @filename: a file or URL
4550 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004551 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004552 *
4553 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004554 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004555 * This reuses the existing @reader xmlTextReader.
4556 *
4557 * Returns 0 in case of success and -1 in case of error
4558 */
4559int
4560xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4561 const char *encoding, int options)
4562{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004563 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004564
4565 if (filename == NULL)
4566 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004567 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004568 return (-1);
4569
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004570 input =
4571 xmlParserInputBufferCreateFilename(filename,
4572 XML_CHAR_ENCODING_NONE);
4573 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004574 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004575 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004576}
4577
4578/**
4579 * xmlReaderNewMemory:
4580 * @reader: an XML reader
4581 * @buffer: a pointer to a char array
4582 * @size: the size of the array
4583 * @URL: the base URL to use for the document
4584 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004585 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004586 *
4587 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004588 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004589 * This reuses the existing @reader xmlTextReader.
4590 *
4591 * Returns 0 in case of success and -1 in case of error
4592 */
4593int
4594xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4595 const char *URL, const char *encoding, int options)
4596{
4597 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004598
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004599 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004600 return (-1);
4601 if (buffer == NULL)
4602 return (-1);
4603
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004604 input = xmlParserInputBufferCreateMem(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004605 XML_CHAR_ENCODING_NONE);
4606 if (input == NULL) {
4607 return (-1);
4608 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004609 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004610}
4611
4612/**
4613 * xmlReaderNewFd:
4614 * @reader: an XML reader
4615 * @fd: an open file descriptor
4616 * @URL: the base URL to use for the document
4617 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004618 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004619 *
4620 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004621 * NOTE that the file descriptor will not be closed when the
4622 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004623 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004624 * This reuses the existing @reader xmlTextReader.
4625 *
4626 * Returns 0 in case of success and -1 in case of error
4627 */
4628int
4629xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4630 const char *URL, const char *encoding, int options)
4631{
4632 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004633
4634 if (fd < 0)
4635 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004636 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004637 return (-1);
4638
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004639 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4640 if (input == NULL)
4641 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004642 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004643 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004644}
4645
4646/**
4647 * xmlReaderNewIO:
4648 * @reader: an XML reader
4649 * @ioread: an I/O read function
4650 * @ioclose: an I/O close function
4651 * @ioctx: an I/O handler
4652 * @URL: the base URL to use for the document
4653 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004654 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004655 *
4656 * Setup an xmltextReader to parse an XML document from I/O functions
4657 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004658 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004659 * This reuses the existing @reader xmlTextReader.
4660 *
4661 * Returns 0 in case of success and -1 in case of error
4662 */
4663int
4664xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4665 xmlInputCloseCallback ioclose, void *ioctx,
4666 const char *URL, const char *encoding, int options)
4667{
4668 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004669
4670 if (ioread == NULL)
4671 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004672 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004673 return (-1);
4674
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004675 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4676 XML_CHAR_ENCODING_NONE);
4677 if (input == NULL)
4678 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004679 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004680}
Daniel Veillard26f70262003-01-16 22:45:08 +00004681/************************************************************************
4682 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004683 * Utilities *
4684 * *
4685 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004686#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004687/**
4688 * xmlBase64Decode:
4689 * @in: the input buffer
4690 * @inlen: the size of the input (in), the size read from it (out)
4691 * @to: the output buffer
4692 * @tolen: the size of the output (in), the size written to (out)
4693 *
4694 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004695 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004696 *
4697 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4698 * 2 if there wasn't enough space on the output or -1 in case of error.
4699 */
4700static int
4701xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4702 unsigned char *to, unsigned long *tolen) {
4703 unsigned long incur; /* current index in in[] */
4704 unsigned long inblk; /* last block index in in[] */
4705 unsigned long outcur; /* current index in out[] */
4706 unsigned long inmax; /* size of in[] */
4707 unsigned long outmax; /* size of out[] */
4708 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004709 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004710 int nbintmp; /* number of byte in intmp[] */
4711 int is_ignore; /* cur should be ignored */
4712 int is_end = 0; /* the end of the base64 was found */
4713 int retval = 1;
4714 int i;
4715
4716 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4717 return(-1);
4718
4719 incur = 0;
4720 inblk = 0;
4721 outcur = 0;
4722 inmax = *inlen;
4723 outmax = *tolen;
4724 nbintmp = 0;
4725
4726 while (1) {
4727 if (incur >= inmax)
4728 break;
4729 cur = in[incur++];
4730 is_ignore = 0;
4731 if ((cur >= 'A') && (cur <= 'Z'))
4732 cur = cur - 'A';
4733 else if ((cur >= 'a') && (cur <= 'z'))
4734 cur = cur - 'a' + 26;
4735 else if ((cur >= '0') && (cur <= '9'))
4736 cur = cur - '0' + 52;
4737 else if (cur == '+')
4738 cur = 62;
4739 else if (cur == '/')
4740 cur = 63;
4741 else if (cur == '.')
4742 cur = 0;
4743 else if (cur == '=') /*no op , end of the base64 stream */
4744 is_end = 1;
4745 else {
4746 is_ignore = 1;
4747 if (nbintmp == 0)
4748 inblk = incur;
4749 }
4750
4751 if (!is_ignore) {
4752 int nbouttmp = 3;
4753 int is_break = 0;
4754
4755 if (is_end) {
4756 if (nbintmp == 0)
4757 break;
4758 if ((nbintmp == 1) || (nbintmp == 2))
4759 nbouttmp = 1;
4760 else
4761 nbouttmp = 2;
4762 nbintmp = 3;
4763 is_break = 1;
4764 }
4765 intmp[nbintmp++] = cur;
4766 /*
4767 * if intmp is full, push the 4byte sequence as a 3 byte
4768 * sequence out
4769 */
4770 if (nbintmp == 4) {
4771 nbintmp = 0;
4772 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4773 outtmp[1] =
4774 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4775 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4776 if (outcur + 3 >= outmax) {
4777 retval = 2;
4778 break;
4779 }
4780
4781 for (i = 0; i < nbouttmp; i++)
4782 to[outcur++] = outtmp[i];
4783 inblk = incur;
4784 }
4785
4786 if (is_break) {
4787 retval = 0;
4788 break;
4789 }
4790 }
4791 }
4792
4793 *tolen = outcur;
4794 *inlen = inblk;
4795 return (retval);
4796}
4797
4798/*
4799 * Test routine for the xmlBase64Decode function
4800 */
4801#if 0
4802int main(int argc, char **argv) {
4803 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4804 char output[100];
4805 char output2[100];
4806 char output3[100];
4807 unsigned long inlen = strlen(input);
4808 unsigned long outlen = 100;
4809 int ret;
4810 unsigned long cons, tmp, tmp2, prod;
4811
4812 /*
4813 * Direct
4814 */
4815 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4816
4817 output[outlen] = 0;
4818 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4819
4820 /*
4821 * output chunking
4822 */
4823 cons = 0;
4824 prod = 0;
4825 while (cons < inlen) {
4826 tmp = 5;
4827 tmp2 = inlen - cons;
4828
4829 printf("%ld %ld\n", cons, prod);
4830 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4831 cons += tmp2;
4832 prod += tmp;
4833 printf("%ld %ld\n", cons, prod);
4834 }
4835 output2[outlen] = 0;
4836 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4837
4838 /*
4839 * input chunking
4840 */
4841 cons = 0;
4842 prod = 0;
4843 while (cons < inlen) {
4844 tmp = 100 - prod;
4845 tmp2 = inlen - cons;
4846 if (tmp2 > 5)
4847 tmp2 = 5;
4848
4849 printf("%ld %ld\n", cons, prod);
4850 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4851 cons += tmp2;
4852 prod += tmp;
4853 printf("%ld %ld\n", cons, prod);
4854 }
4855 output3[outlen] = 0;
4856 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4857 return(0);
4858
4859}
4860#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004861#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004862#endif /* LIBXML_READER_ENABLED */