blob: e1c2ef8a8dc530eb63640bfa6db1d755757b9737 [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard067bae52003-01-05 01:27:54 +000015 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000016 * - setting(s) for NoBlanks
17 * - performances and tuning ...
18 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000019#define IN_LIBXML
20#include "libxml.h"
21
Daniel Veillard81273902003-09-30 00:43:48 +000022#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000024#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025
26#ifdef HAVE_CTYPE_H
27#include <ctype.h>
28#endif
29#ifdef HAVE_STDLIB_H
30#include <stdlib.h>
31#endif
32
33#include <libxml/xmlmemory.h>
34#include <libxml/xmlIO.h>
35#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000036#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000037#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000038#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000039#ifdef LIBXML_XINCLUDE_ENABLED
40#include <libxml/xinclude.h>
41#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000042#ifdef LIBXML_PATTERN_ENABLED
43#include <libxml/pattern.h>
44#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000045
46/* #define DEBUG_CALLBACKS */
47/* #define DEBUG_READER */
48
49/**
50 * TODO:
51 *
52 * macro to flag unimplemented blocks
53 */
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
59#ifdef DEBUG_READER
60#define DUMP_READER xmlTextReaderDebug(reader);
61#else
62#define DUMP_READER
63#endif
64
Daniel Veillarda880b122003-04-21 21:36:41 +000065#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000066/************************************************************************
67 * *
68 * The parser: maps the Text Reader API on top of the existing *
69 * parsing routines building a tree *
70 * *
71 ************************************************************************/
72
73#define XML_TEXTREADER_INPUT 1
74#define XML_TEXTREADER_CTXT 2
75
76typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000077 XML_TEXTREADER_MODE_INITIAL = 0,
78 XML_TEXTREADER_MODE_INTERACTIVE = 1,
79 XML_TEXTREADER_MODE_ERROR = 2,
80 XML_TEXTREADER_MODE_EOF =3,
81 XML_TEXTREADER_MODE_CLOSED = 4,
82 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000083} xmlTextReaderMode;
84
85typedef enum {
86 XML_TEXTREADER_NONE = -1,
87 XML_TEXTREADER_START= 0,
88 XML_TEXTREADER_ELEMENT= 1,
89 XML_TEXTREADER_END= 2,
90 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000091 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000092 XML_TEXTREADER_DONE= 5,
93 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000094} xmlTextReaderState;
95
Daniel Veillardf4e55762003-04-15 23:32:22 +000096typedef enum {
97 XML_TEXTREADER_NOT_VALIDATE = 0,
98 XML_TEXTREADER_VALIDATE_DTD = 1,
99 XML_TEXTREADER_VALIDATE_RNG = 2
100} xmlTextReaderValidate;
101
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000102struct _xmlTextReader {
103 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000104 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000105 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000106 int allocs; /* what structure were deallocated */
107 xmlTextReaderState state;
108 xmlParserCtxtPtr ctxt; /* the parser context */
109 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
110 xmlParserInputBufferPtr input; /* the input */
111 startElementSAXFunc startElement;/* initial SAX callbacks */
112 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000113 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000114 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000115 charactersSAXFunc characters;
116 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000117 unsigned int base; /* base of the segment in the input */
118 unsigned int cur; /* current position in the input */
119 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000120 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000121 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000122 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000123 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000124 xmlBufferPtr buffer; /* used to return const xmlChar * */
125 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000126
127 /* entity stack when traversing entities content */
128 xmlNodePtr ent; /* Current Entity Ref Node */
129 int entNr; /* Depth of the entities stack */
130 int entMax; /* Max depth of the entities stack */
131 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000132
133 /* error handling */
134 xmlTextReaderErrorFunc errorFunc; /* callback function */
135 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000136
137#ifdef LIBXML_SCHEMAS_ENABLED
138 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000139 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
140 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
141 int rngValidErrors;/* The number of errors detected */
142 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
143#endif
144#ifdef LIBXML_XINCLUDE_ENABLED
145 /* Handling of XInclude processing */
146 int xinclude; /* is xinclude asked for */
147 const xmlChar * xinclude_name; /* the xinclude name from dict */
148 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
149 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000150#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000151#ifdef LIBXML_PATTERN_ENABLED
152 int patternNr; /* number of preserve patterns */
153 int patternMax; /* max preserve patterns */
154 xmlPatternPtr *patternTab; /* array of preserve patterns */
155#endif
156 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000157 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000158 /* Structured error handling */
159 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000160};
161
Daniel Veillarde8039df2003-10-27 11:25:13 +0000162#define NODE_IS_EMPTY 0x1
163#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000164#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000165
Daniel Veillarde72c5082003-09-19 12:44:05 +0000166/**
167 * CONSTSTR:
168 *
169 * Macro used to return an interned string
170 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000171#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
172#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
173
174static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
175static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000176
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000177/************************************************************************
178 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000179 * Our own version of the freeing routines as we recycle nodes *
180 * *
181 ************************************************************************/
182/**
183 * DICT_FREE:
184 * @str: a string
185 *
186 * Free a string if it is not owned by the "dict" dictionnary in the
187 * current scope
188 */
189#define DICT_FREE(str) \
190 if ((str) && ((!dict) || \
191 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
192 xmlFree((char *)(str));
193
194static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
195static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
196
197/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000198 * xmlFreeID:
199 * @not: A id
200 *
201 * Deallocate the memory used by an id definition
202 */
203static void
204xmlFreeID(xmlIDPtr id) {
205 xmlDictPtr dict = NULL;
206
207 if (id == NULL) return;
208
209 if (id->doc != NULL)
210 dict = id->doc->dict;
211
212 if (id->value != NULL)
213 DICT_FREE(id->value)
214 xmlFree(id);
215}
216
217/**
218 * xmlTextReaderRemoveID:
219 * @doc: the document
220 * @attr: the attribute
221 *
222 * Remove the given attribute from the ID table maintained internally.
223 *
224 * Returns -1 if the lookup failed and 0 otherwise
225 */
226static int
227xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
228 xmlIDTablePtr table;
229 xmlIDPtr id;
230 xmlChar *ID;
231
232 if (doc == NULL) return(-1);
233 if (attr == NULL) return(-1);
234 table = (xmlIDTablePtr) doc->ids;
235 if (table == NULL)
236 return(-1);
237
238 if (attr == NULL)
239 return(-1);
240 ID = xmlNodeListGetString(doc, attr->children, 1);
241 if (ID == NULL)
242 return(-1);
243 id = xmlHashLookup(table, ID);
244 xmlFree(ID);
245 if (id == NULL || id->attr != attr) {
246 return(-1);
247 }
248 id->name = attr->name;
249 id->attr = NULL;
250 return(0);
251}
252
253/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000254 * xmlTextReaderFreeProp:
255 * @reader: the xmlTextReaderPtr used
256 * @cur: the node
257 *
258 * Free a node.
259 */
260static void
261xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
262 xmlDictPtr dict;
263
264 dict = reader->ctxt->dict;
265 if (cur == NULL) return;
266
267 /* Check for ID removal -> leading to invalid references ! */
268 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
269 ((cur->parent->doc->intSubset != NULL) ||
270 (cur->parent->doc->extSubset != NULL))) {
271 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000272 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000273 }
274 if (cur->children != NULL)
275 xmlTextReaderFreeNodeList(reader, cur->children);
276
277 DICT_FREE(cur->name);
278 if ((reader != NULL) && (reader->ctxt != NULL) &&
279 (reader->ctxt->freeAttrsNr < 100)) {
280 cur->next = reader->ctxt->freeAttrs;
281 reader->ctxt->freeAttrs = cur;
282 reader->ctxt->freeAttrsNr++;
283 } else {
284 xmlFree(cur);
285 }
286}
287
288/**
289 * xmlTextReaderFreePropList:
290 * @reader: the xmlTextReaderPtr used
291 * @cur: the first property in the list
292 *
293 * Free a property and all its siblings, all the children are freed too.
294 */
295static void
296xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
297 xmlAttrPtr next;
298 if (cur == NULL) return;
299 while (cur != NULL) {
300 next = cur->next;
301 xmlTextReaderFreeProp(reader, cur);
302 cur = next;
303 }
304}
305
306/**
307 * xmlTextReaderFreeNodeList:
308 * @reader: the xmlTextReaderPtr used
309 * @cur: the first node in the list
310 *
311 * Free a node and all its siblings, this is a recursive behaviour, all
312 * the children are freed too.
313 */
314static void
315xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
316 xmlNodePtr next;
317 xmlDictPtr dict;
318
319 dict = reader->ctxt->dict;
320 if (cur == NULL) return;
321 if (cur->type == XML_NAMESPACE_DECL) {
322 xmlFreeNsList((xmlNsPtr) cur);
323 return;
324 }
325 if ((cur->type == XML_DOCUMENT_NODE) ||
326 (cur->type == XML_HTML_DOCUMENT_NODE)) {
327 xmlFreeDoc((xmlDocPtr) cur);
328 return;
329 }
330 while (cur != NULL) {
331 next = cur->next;
332 /* unroll to speed up freeing the document */
333 if (cur->type != XML_DTD_NODE) {
334
335 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000336 (cur->type != XML_ENTITY_REF_NODE)) {
337 if (cur->children->parent == cur)
338 xmlTextReaderFreeNodeList(reader, cur->children);
339 cur->children = NULL;
340 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000341 if (((cur->type == XML_ELEMENT_NODE) ||
342 (cur->type == XML_XINCLUDE_START) ||
343 (cur->type == XML_XINCLUDE_END)) &&
344 (cur->properties != NULL))
345 xmlTextReaderFreePropList(reader, cur->properties);
346 if ((cur->type != XML_ELEMENT_NODE) &&
347 (cur->type != XML_XINCLUDE_START) &&
348 (cur->type != XML_XINCLUDE_END) &&
349 (cur->type != XML_ENTITY_REF_NODE)) {
350 DICT_FREE(cur->content);
351 }
352 if (((cur->type == XML_ELEMENT_NODE) ||
353 (cur->type == XML_XINCLUDE_START) ||
354 (cur->type == XML_XINCLUDE_END)) &&
355 (cur->nsDef != NULL))
356 xmlFreeNsList(cur->nsDef);
357
358 /*
359 * we don't free element names here they are interned now
360 */
361 if ((cur->type != XML_TEXT_NODE) &&
362 (cur->type != XML_COMMENT_NODE))
363 DICT_FREE(cur->name);
364 if (((cur->type == XML_ELEMENT_NODE) ||
365 (cur->type == XML_TEXT_NODE)) &&
366 (reader != NULL) && (reader->ctxt != NULL) &&
367 (reader->ctxt->freeElemsNr < 100)) {
368 cur->next = reader->ctxt->freeElems;
369 reader->ctxt->freeElems = cur;
370 reader->ctxt->freeElemsNr++;
371 } else {
372 xmlFree(cur);
373 }
374 }
375 cur = next;
376 }
377}
378
379/**
380 * xmlTextReaderFreeNode:
381 * @reader: the xmlTextReaderPtr used
382 * @cur: the node
383 *
384 * Free a node, this is a recursive behaviour, all the children are freed too.
385 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
386 */
387static void
388xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
389 xmlDictPtr dict;
390
391 dict = reader->ctxt->dict;
392 if (cur->type == XML_DTD_NODE) {
393 xmlFreeDtd((xmlDtdPtr) cur);
394 return;
395 }
396 if (cur->type == XML_NAMESPACE_DECL) {
397 xmlFreeNs((xmlNsPtr) cur);
398 return;
399 }
400 if (cur->type == XML_ATTRIBUTE_NODE) {
401 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
402 return;
403 }
404
405 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000406 (cur->type != XML_ENTITY_REF_NODE)) {
407 if (cur->children->parent == cur)
408 xmlTextReaderFreeNodeList(reader, cur->children);
409 cur->children = NULL;
410 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000411 if (((cur->type == XML_ELEMENT_NODE) ||
412 (cur->type == XML_XINCLUDE_START) ||
413 (cur->type == XML_XINCLUDE_END)) &&
414 (cur->properties != NULL))
415 xmlTextReaderFreePropList(reader, cur->properties);
416 if ((cur->type != XML_ELEMENT_NODE) &&
417 (cur->type != XML_XINCLUDE_START) &&
418 (cur->type != XML_XINCLUDE_END) &&
419 (cur->type != XML_ENTITY_REF_NODE)) {
420 DICT_FREE(cur->content);
421 }
422 if (((cur->type == XML_ELEMENT_NODE) ||
423 (cur->type == XML_XINCLUDE_START) ||
424 (cur->type == XML_XINCLUDE_END)) &&
425 (cur->nsDef != NULL))
426 xmlFreeNsList(cur->nsDef);
427
428 /*
429 * we don't free names here they are interned now
430 */
431 if ((cur->type != XML_TEXT_NODE) &&
432 (cur->type != XML_COMMENT_NODE))
433 DICT_FREE(cur->name);
434 if (((cur->type == XML_ELEMENT_NODE) ||
435 (cur->type == XML_TEXT_NODE)) &&
436 (reader != NULL) && (reader->ctxt != NULL) &&
437 (reader->ctxt->freeElemsNr < 100)) {
438 cur->next = reader->ctxt->freeElems;
439 reader->ctxt->freeElems = cur;
440 reader->ctxt->freeElemsNr++;
441 } else {
442 xmlFree(cur);
443 }
444}
445
446/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000447 * xmlTextReaderFreeIDTable:
448 * @table: An id table
449 *
450 * Deallocate the memory used by an ID hash table.
451 */
William M. Brack60f394e2003-11-16 06:25:42 +0000452static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000453xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
454 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
455}
456
457/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000458 * xmlTextReaderFreeDoc:
459 * @reader: the xmlTextReaderPtr used
460 * @cur: pointer to the document
461 *
462 * Free up all the structures used by a document, tree included.
463 */
464static void
465xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
466 xmlDtdPtr extSubset, intSubset;
467
468 if (cur == NULL) return;
469
470 /*
471 * Do this before freeing the children list to avoid ID lookups
472 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000473 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000474 cur->ids = NULL;
475 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
476 cur->refs = NULL;
477 extSubset = cur->extSubset;
478 intSubset = cur->intSubset;
479 if (intSubset == extSubset)
480 extSubset = NULL;
481 if (extSubset != NULL) {
482 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
483 cur->extSubset = NULL;
484 xmlFreeDtd(extSubset);
485 }
486 if (intSubset != NULL) {
487 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
488 cur->intSubset = NULL;
489 xmlFreeDtd(intSubset);
490 }
491
492 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
493
494 if (cur->version != NULL) xmlFree((char *) cur->version);
495 if (cur->name != NULL) xmlFree((char *) cur->name);
496 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
497 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
498 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000499 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000500 xmlFree(cur);
501}
502
503/************************************************************************
504 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000505 * The reader core parser *
506 * *
507 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000508#ifdef DEBUG_READER
509static void
510xmlTextReaderDebug(xmlTextReaderPtr reader) {
511 if ((reader == NULL) || (reader->ctxt == NULL)) {
512 fprintf(stderr, "xmlTextReader NULL\n");
513 return;
514 }
515 fprintf(stderr, "xmlTextReader: state %d depth %d ",
516 reader->state, reader->depth);
517 if (reader->node == NULL) {
518 fprintf(stderr, "node = NULL\n");
519 } else {
520 fprintf(stderr, "node %s\n", reader->node->name);
521 }
522 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
523 reader->base, reader->cur, reader->ctxt->nodeNr);
524 if (reader->input->buffer == NULL) {
525 fprintf(stderr, "buffer is NULL\n");
526 } else {
527#ifdef LIBXML_DEBUG_ENABLED
528 xmlDebugDumpString(stderr,
529 &reader->input->buffer->content[reader->cur]);
530#endif
531 fprintf(stderr, "\n");
532 }
533}
534#endif
535
536/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000537 * xmlTextReaderEntPush:
538 * @reader: the xmlTextReaderPtr used
539 * @value: the entity reference node
540 *
541 * Pushes a new entity reference node on top of the entities stack
542 *
543 * Returns 0 in case of error, the index in the stack otherwise
544 */
545static int
546xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
547{
548 if (reader->entMax <= 0) {
549 reader->entMax = 10;
550 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
551 sizeof(reader->entTab[0]));
552 if (reader->entTab == NULL) {
553 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
554 return (0);
555 }
556 }
557 if (reader->entNr >= reader->entMax) {
558 reader->entMax *= 2;
559 reader->entTab =
560 (xmlNodePtr *) xmlRealloc(reader->entTab,
561 reader->entMax *
562 sizeof(reader->entTab[0]));
563 if (reader->entTab == NULL) {
564 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
565 return (0);
566 }
567 }
568 reader->entTab[reader->entNr] = value;
569 reader->ent = value;
570 return (reader->entNr++);
571}
572
573/**
574 * xmlTextReaderEntPop:
575 * @reader: the xmlTextReaderPtr used
576 *
577 * Pops the top element entity from the entities stack
578 *
579 * Returns the entity just removed
580 */
581static xmlNodePtr
582xmlTextReaderEntPop(xmlTextReaderPtr reader)
583{
584 xmlNodePtr ret;
585
586 if (reader->entNr <= 0)
587 return (0);
588 reader->entNr--;
589 if (reader->entNr > 0)
590 reader->ent = reader->entTab[reader->entNr - 1];
591 else
592 reader->ent = NULL;
593 ret = reader->entTab[reader->entNr];
594 reader->entTab[reader->entNr] = 0;
595 return (ret);
596}
597
598/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000599 * xmlTextReaderStartElement:
600 * @ctx: the user data (XML parser context)
601 * @fullname: The element name, including namespace prefix
602 * @atts: An array of name/value attributes pairs, NULL terminated
603 *
604 * called when an opening tag has been processed.
605 */
606static void
607xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
608 const xmlChar **atts) {
609 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
610 xmlTextReaderPtr reader = ctxt->_private;
611
612#ifdef DEBUG_CALLBACKS
613 printf("xmlTextReaderStartElement(%s)\n", fullname);
614#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000615 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000616 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000617 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
618 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
619 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000620 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000621 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000622 if (reader != NULL)
623 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000624}
625
626/**
627 * xmlTextReaderEndElement:
628 * @ctx: the user data (XML parser context)
629 * @fullname: The element name, including namespace prefix
630 *
631 * called when an ending tag has been processed.
632 */
633static void
634xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
635 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
636 xmlTextReaderPtr reader = ctxt->_private;
637
638#ifdef DEBUG_CALLBACKS
639 printf("xmlTextReaderEndElement(%s)\n", fullname);
640#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000641 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000642 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000643 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000644}
645
646/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000647 * xmlTextReaderStartElementNs:
648 * @ctx: the user data (XML parser context)
649 * @localname: the local name of the element
650 * @prefix: the element namespace prefix if available
651 * @URI: the element namespace name if available
652 * @nb_namespaces: number of namespace definitions on that node
653 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
654 * @nb_attributes: the number of attributes on that node
655 * nb_defaulted: the number of defaulted attributes.
656 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
657 * attribute values.
658 *
659 * called when an opening tag has been processed.
660 */
661static void
662xmlTextReaderStartElementNs(void *ctx,
663 const xmlChar *localname,
664 const xmlChar *prefix,
665 const xmlChar *URI,
666 int nb_namespaces,
667 const xmlChar **namespaces,
668 int nb_attributes,
669 int nb_defaulted,
670 const xmlChar **attributes)
671{
672 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
673 xmlTextReaderPtr reader = ctxt->_private;
674
675#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000676 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000677#endif
678 if ((reader != NULL) && (reader->startElementNs != NULL)) {
679 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
680 namespaces, nb_attributes, nb_defaulted,
681 attributes);
682 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
683 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
684 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000685 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000686 }
687 if (reader != NULL)
688 reader->state = XML_TEXTREADER_ELEMENT;
689}
690
691/**
692 * xmlTextReaderEndElementNs:
693 * @ctx: the user data (XML parser context)
694 * @localname: the local name of the element
695 * @prefix: the element namespace prefix if available
696 * @URI: the element namespace name if available
697 *
698 * called when an ending tag has been processed.
699 */
700static void
701xmlTextReaderEndElementNs(void *ctx,
702 const xmlChar * localname,
703 const xmlChar * prefix,
704 const xmlChar * URI)
705{
706 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
707 xmlTextReaderPtr reader = ctxt->_private;
708
709#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000710 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000711#endif
712 if ((reader != NULL) && (reader->endElementNs != NULL)) {
713 reader->endElementNs(ctx, localname, prefix, URI);
714 }
715}
716
717
718/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000719 * xmlTextReaderCharacters:
720 * @ctx: the user data (XML parser context)
721 * @ch: a xmlChar string
722 * @len: the number of xmlChar
723 *
724 * receiving some chars from the parser.
725 */
726static void
727xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
728{
729 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
730 xmlTextReaderPtr reader = ctxt->_private;
731
732#ifdef DEBUG_CALLBACKS
733 printf("xmlTextReaderCharacters()\n");
734#endif
735 if ((reader != NULL) && (reader->characters != NULL)) {
736 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000737 }
738}
739
740/**
741 * xmlTextReaderCDataBlock:
742 * @ctx: the user data (XML parser context)
743 * @value: The pcdata content
744 * @len: the block length
745 *
746 * called when a pcdata block has been parsed
747 */
748static void
749xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
750{
751 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
752 xmlTextReaderPtr reader = ctxt->_private;
753
754#ifdef DEBUG_CALLBACKS
755 printf("xmlTextReaderCDataBlock()\n");
756#endif
757 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
758 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000759 }
760}
761
762/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000763 * xmlTextReaderPushData:
764 * @reader: the xmlTextReaderPtr used
765 *
766 * Push data down the progressive parser until a significant callback
767 * got raised.
768 *
769 * Returns -1 in case of failure, 0 otherwise
770 */
771static int
772xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000773 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000774 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000775 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000776
777 if ((reader->input == NULL) || (reader->input->buffer == NULL))
778 return(-1);
779
Daniel Veillardea7751d2002-12-20 00:16:24 +0000780 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000781 reader->state = XML_TEXTREADER_NONE;
782 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000783
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000784 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000785 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000786 /*
787 * Refill the buffer unless we are at the end of the stream
788 */
789 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
790 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000791 if ((val == 0) &&
792 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
793 if (inbuf->use == reader->cur) {
794 reader->mode = XML_TEXTREADER_MODE_EOF;
795 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000796 }
797 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000798 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000799 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000800 if ((oldstate != XML_TEXTREADER_START) ||
801 (reader->ctxt->myDoc != NULL))
802 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000803 } else if (val == 0) {
804 /* mark the end of the stream and process the remains */
805 reader->mode = XML_TEXTREADER_MODE_EOF;
806 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000807 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000808
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000809 } else
810 break;
811 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000812 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000813 * parse by block of CHUNK_SIZE bytes, various tests show that
814 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000815 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000816 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000817 val = xmlParseChunk(reader->ctxt,
818 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000819 CHUNK_SIZE, 0);
820 reader->cur += CHUNK_SIZE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000821 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000822 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000823 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000824 s = inbuf->use - reader->cur;
825 val = xmlParseChunk(reader->ctxt,
826 (const char *) &inbuf->content[reader->cur],
827 s, 0);
828 reader->cur += s;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000829 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000830 return(-1);
831 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000832 }
833 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000834
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000835 /*
836 * Discard the consumed input when needed and possible
837 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000838 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000839 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
840 if ((reader->cur >= 4096) &&
841 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
842 val = xmlBufferShrink(inbuf, reader->cur);
843 if (val >= 0) {
844 reader->cur -= val;
845 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000846 }
847 }
848 }
849
850 /*
851 * At the end of the stream signal that the work is done to the Push
852 * parser.
853 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000854 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000855 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000856 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000857 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000858 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000859 s, 1);
860 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000861 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000862 if ((val != 0) && (reader->ctxt->wellFormed == 0))
863 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000864 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000865 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000866 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000867 return(0);
868}
869
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000870#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000871/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000872 * xmlTextReaderValidatePush:
873 * @reader: the xmlTextReaderPtr used
874 *
875 * Push the current node for validation
876 */
877static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000878xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000879 xmlNodePtr node = reader->node;
880
Daniel Veillardf54cd532004-02-25 11:52:31 +0000881#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000882 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
883 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
884 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
885 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
886 reader->ctxt->myDoc, node, node->name);
887 } else {
888 /* TODO use the BuildQName interface */
889 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000890
Daniel Veillardf4e55762003-04-15 23:32:22 +0000891 qname = xmlStrdup(node->ns->prefix);
892 qname = xmlStrcat(qname, BAD_CAST ":");
893 qname = xmlStrcat(qname, node->name);
894 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
895 reader->ctxt->myDoc, node, qname);
896 if (qname != NULL)
897 xmlFree(qname);
898 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000899 }
900#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000901#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000902 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000903 (reader->rngValidCtxt != NULL)) {
904 int ret;
905
906 if (reader->rngFullNode != NULL) return;
907 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
908 reader->ctxt->myDoc,
909 node);
910 if (ret == 0) {
911 /*
912 * this element requires a full tree
913 */
914 node = xmlTextReaderExpand(reader);
915 if (node == NULL) {
916printf("Expand failed !\n");
917 ret = -1;
918 } else {
919 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
920 reader->ctxt->myDoc,
921 node);
922 reader->rngFullNode = node;
923 }
924 }
925 if (ret != 1)
926 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000927 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000928#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000929}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000930
931/**
932 * xmlTextReaderValidateCData:
933 * @reader: the xmlTextReaderPtr used
934 * @data: pointer to the CData
935 * @len: lenght of the CData block in bytes.
936 *
937 * Push some CData for validation
938 */
939static void
940xmlTextReaderValidateCData(xmlTextReaderPtr reader,
941 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000942#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000943 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
944 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
945 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
946 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000947 }
948#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000949#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000950 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000951 (reader->rngValidCtxt != NULL)) {
952 int ret;
953
954 if (reader->rngFullNode != NULL) return;
955 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
956 if (ret != 1)
957 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000958 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000959#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000960}
961
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000962/**
963 * xmlTextReaderValidatePop:
964 * @reader: the xmlTextReaderPtr used
965 *
966 * Pop the current node from validation
967 */
968static void
969xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
970 xmlNodePtr node = reader->node;
971
Daniel Veillardf54cd532004-02-25 11:52:31 +0000972#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000973 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
974 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
975 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
976 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
977 reader->ctxt->myDoc, node, node->name);
978 } else {
979 /* TODO use the BuildQName interface */
980 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000981
Daniel Veillardf4e55762003-04-15 23:32:22 +0000982 qname = xmlStrdup(node->ns->prefix);
983 qname = xmlStrcat(qname, BAD_CAST ":");
984 qname = xmlStrcat(qname, node->name);
985 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
986 reader->ctxt->myDoc, node, qname);
987 if (qname != NULL)
988 xmlFree(qname);
989 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000990 }
991#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000992#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000993 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000994 (reader->rngValidCtxt != NULL)) {
995 int ret;
996
997 if (reader->rngFullNode != NULL) {
998 if (node == reader->rngFullNode)
999 reader->rngFullNode = NULL;
1000 return;
1001 }
1002 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1003 reader->ctxt->myDoc,
1004 node);
1005 if (ret != 1)
1006 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001007 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001008#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001009}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001010
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001011/**
1012 * xmlTextReaderValidateEntity:
1013 * @reader: the xmlTextReaderPtr used
1014 *
1015 * Handle the validation when an entity reference is encountered and
1016 * entity substitution is not activated. As a result the parser interface
1017 * must walk through the entity and do the validation calls
1018 */
1019static void
1020xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1021 xmlNodePtr oldnode = reader->node;
1022 xmlNodePtr node = reader->node;
1023 xmlParserCtxtPtr ctxt = reader->ctxt;
1024
1025 do {
1026 if (node->type == XML_ENTITY_REF_NODE) {
1027 /*
1028 * Case where the underlying tree is not availble, lookup the entity
1029 * and walk it.
1030 */
1031 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1032 (ctxt->sax->getEntity != NULL)) {
1033 node->children = (xmlNodePtr)
1034 ctxt->sax->getEntity(ctxt, node->name);
1035 }
1036
1037 if ((node->children != NULL) &&
1038 (node->children->type == XML_ENTITY_DECL) &&
1039 (node->children->children != NULL)) {
1040 xmlTextReaderEntPush(reader, node);
1041 node = node->children->children;
1042 continue;
1043 } else {
1044 /*
1045 * The error has probably be raised already.
1046 */
1047 if (node == oldnode)
1048 break;
1049 node = node->next;
1050 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001051#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001052 } else if (node->type == XML_ELEMENT_NODE) {
1053 reader->node = node;
1054 xmlTextReaderValidatePush(reader);
1055 } else if ((node->type == XML_TEXT_NODE) ||
1056 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001057 xmlTextReaderValidateCData(reader, node->content,
1058 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001059#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001060 }
1061
1062 /*
1063 * go to next node
1064 */
1065 if (node->children != NULL) {
1066 node = node->children;
1067 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001068 } else if (node->type == XML_ELEMENT_NODE) {
1069 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001070 }
1071 if (node->next != NULL) {
1072 node = node->next;
1073 continue;
1074 }
1075 do {
1076 node = node->parent;
1077 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001078 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001079 if (reader->entNr == 0) {
1080 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001081 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001082 xmlUnlinkNode(tmp);
1083 xmlTextReaderFreeNode(reader, tmp);
1084 } else
1085 break;
1086 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001087 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001088 reader->node = node;
1089 xmlTextReaderValidatePop(reader);
1090 }
1091 if ((node->type == XML_ENTITY_DECL) &&
1092 (reader->ent != NULL) && (reader->ent->children == node)) {
1093 node = xmlTextReaderEntPop(reader);
1094 }
1095 if (node == oldnode)
1096 break;
1097 if (node->next != NULL) {
1098 node = node->next;
1099 break;
1100 }
1101 } while ((node != NULL) && (node != oldnode));
1102 } while ((node != NULL) && (node != oldnode));
1103 reader->node = oldnode;
1104}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001105#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001106
1107
1108/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001109 * xmlTextReaderGetSuccessor:
1110 * @cur: the current node
1111 *
1112 * Get the successor of a node if available.
1113 *
1114 * Returns the successor node or NULL
1115 */
1116static xmlNodePtr
1117xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1118 if (cur == NULL) return(NULL) ; /* ERROR */
1119 if (cur->next != NULL) return(cur->next) ;
1120 do {
1121 cur = cur->parent;
1122 if (cur == NULL) return(NULL);
1123 if (cur->next != NULL) return(cur->next);
1124 } while (cur != NULL);
1125 return(cur);
1126}
1127
1128/**
1129 * xmlTextReaderDoExpand:
1130 * @reader: the xmlTextReaderPtr used
1131 *
1132 * Makes sure that the current node is fully read as well as all its
1133 * descendant. It means the full DOM subtree must be available at the
1134 * end of the call.
1135 *
1136 * Returns 1 if the node was expanded successfully, 0 if there is no more
1137 * nodes to read, or -1 in case of error
1138 */
1139static int
1140xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1141 int val;
1142
1143 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1144 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001145 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001146 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1147
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001148 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1149 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001150 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001151 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001152 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1153 return(1);
1154 val = xmlTextReaderPushData(reader);
1155 if (val < 0)
1156 return(-1);
1157 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1158 return(1);
1159}
1160
1161/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001162 * xmlTextReaderRead:
1163 * @reader: the xmlTextReaderPtr used
1164 *
1165 * Moves the position of the current instance to the next node in
1166 * the stream, exposing its properties.
1167 *
1168 * Returns 1 if the node was read successfully, 0 if there is no more
1169 * nodes to read, or -1 in case of error
1170 */
1171int
1172xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001173 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001174 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001175 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001176
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001177
1178 if (reader == NULL)
1179 return(-1);
1180 if (reader->doc != NULL)
1181 return(xmlTextReaderReadTree(reader));
1182 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001183 return(-1);
1184 if (reader->ctxt->wellFormed != 1)
1185 return(-1);
1186
1187#ifdef DEBUG_READER
1188 fprintf(stderr, "\nREAD ");
1189 DUMP_READER
1190#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001191 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001192 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1193 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001194 /*
1195 * Initial state
1196 */
1197 do {
1198 val = xmlTextReaderPushData(reader);
1199 if (val < 0)
1200 return(-1);
1201 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001202 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1203 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001204 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001205 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001206 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001207 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001208 if (reader->node == NULL)
1209 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001210 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001212 if (reader->ctxt->myDoc != NULL) {
1213 reader->node = reader->ctxt->myDoc->children;
1214 }
1215 if (reader->node == NULL)
1216 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001217 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001218 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001219 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001220 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001221 }
1222 oldstate = reader->state;
1223 olddepth = reader->ctxt->nodeNr;
1224 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001225
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001226get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001227 /*
1228 * If we are not backtracking on ancestors or examined nodes,
1229 * that the parser didn't finished or that we arent at the end
1230 * of stream, continue processing.
1231 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001232 while ((reader->node->next == NULL) &&
1233 (reader->ctxt->nodeNr == olddepth) &&
1234 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001235 (reader->node->children == NULL) ||
1236 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001237 ((reader->node->children != NULL) &&
1238 (reader->node->children->type == XML_TEXT_NODE) &&
1239 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001240 (reader->node->type == XML_DTD_NODE) ||
1241 (reader->node->type == XML_DOCUMENT_NODE) ||
1242 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001243 ((reader->ctxt->node == NULL) ||
1244 (reader->ctxt->node == reader->node) ||
1245 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001246 (reader->ctxt->instate != XML_PARSER_EOF)) {
1247 val = xmlTextReaderPushData(reader);
1248 if (val < 0)
1249 return(-1);
1250 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001251 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001252 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001253 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001254 if ((reader->node->children != NULL) &&
1255 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001256 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001257 (reader->node->type != XML_DTD_NODE)) {
1258 reader->node = reader->node->children;
1259 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001260 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001261 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001262 }
1263 }
1264 if (reader->node->next != NULL) {
1265 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001266 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001267 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001268 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1269#ifdef LIBXML_XINCLUDE_ENABLED
1270 && (reader->in_xinclude <= 0)
1271#endif
1272 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001273 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001274 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001275 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001276#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001277 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001278 (reader->node->type == XML_ELEMENT_NODE))
1279 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001280#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001281 if ((reader->preserves > 0) &&
1282 (reader->node->extra & NODE_IS_SPRESERVED))
1283 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001284 reader->node = reader->node->next;
1285 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001286
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287 /*
1288 * Cleanup of the old node
1289 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001290 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001291#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001292 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001293#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001294 (reader->entNr == 0) &&
1295 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001296 (reader->node->prev->type != XML_DTD_NODE) &&
1297 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001298 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001299 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001300 xmlUnlinkNode(tmp);
1301 xmlTextReaderFreeNode(reader, tmp);
1302 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001303 }
1304
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001305 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001306 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001307 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001308 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001309 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001310 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001311 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001312 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001313 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001314#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001315 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001316 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001317#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001318 if ((reader->preserves > 0) &&
1319 (reader->node->extra & NODE_IS_SPRESERVED))
1320 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001321 reader->node = reader->node->parent;
1322 if ((reader->node == NULL) ||
1323 (reader->node->type == XML_DOCUMENT_NODE) ||
1324#ifdef LIBXML_DOCB_ENABLED
1325 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1326#endif
1327 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001328 if (reader->mode != XML_TEXTREADER_DONE) {
1329 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1330 reader->mode = XML_TEXTREADER_DONE;
1331 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001332 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001333 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001334
1335 /*
1336 * Cleanup of the old node
1337 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001338 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001339#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001340 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001341#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001342 (reader->entNr == 0) &&
1343 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001344 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001345 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001346 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001347 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001348 }
1349
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001350 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001351 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001352 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001353#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001354 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001355#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001356 (reader->entNr == 0) &&
1357 (reader->node->last != NULL) &&
1358 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1359 xmlNodePtr tmp = reader->node->last;
1360 xmlUnlinkNode(tmp);
1361 xmlTextReaderFreeNode(reader, tmp);
1362 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 reader->depth--;
1364 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001365
1366node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001367 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001368
1369 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001370 * If we are in the middle of a piece of CDATA make sure it's finished
1371 */
1372 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001373 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001374 ((reader->node->type == XML_TEXT_NODE) ||
1375 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1376 xmlTextReaderExpand(reader);
1377 }
1378
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001379#ifdef LIBXML_XINCLUDE_ENABLED
1380 /*
1381 * Handle XInclude if asked for
1382 */
1383 if ((reader->xinclude) && (reader->node != NULL) &&
1384 (reader->node->type == XML_ELEMENT_NODE) &&
1385 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001386 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1387 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001388 if (reader->xincctxt == NULL) {
1389 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001390 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001391 }
1392 /*
1393 * expand that node and process it
1394 */
1395 xmlTextReaderExpand(reader);
1396 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1397 }
1398 if (reader->node->type == XML_XINCLUDE_START) {
1399 reader->in_xinclude++;
1400 goto get_next_node;
1401 }
1402 if (reader->node->type == XML_XINCLUDE_END) {
1403 reader->in_xinclude--;
1404 goto get_next_node;
1405 }
1406#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001407 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001408 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001409 */
1410 if ((reader->node != NULL) &&
1411 (reader->node->type == XML_ENTITY_REF_NODE) &&
1412 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1413 /*
1414 * Case where the underlying tree is not availble, lookup the entity
1415 * and walk it.
1416 */
1417 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1418 (reader->ctxt->sax->getEntity != NULL)) {
1419 reader->node->children = (xmlNodePtr)
1420 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1421 }
1422
1423 if ((reader->node->children != NULL) &&
1424 (reader->node->children->type == XML_ENTITY_DECL) &&
1425 (reader->node->children->children != NULL)) {
1426 xmlTextReaderEntPush(reader, reader->node);
1427 reader->node = reader->node->children->children;
1428 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001429#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001430 } else if ((reader->node != NULL) &&
1431 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001432 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001433 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001434#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001435 }
1436 if ((reader->node != NULL) &&
1437 (reader->node->type == XML_ENTITY_DECL) &&
1438 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1439 reader->node = xmlTextReaderEntPop(reader);
1440 reader->depth++;
1441 goto get_next_node;
1442 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001443#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001444 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001445 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001446
1447 if ((node->type == XML_ELEMENT_NODE) &&
1448 ((reader->state != XML_TEXTREADER_END) &&
1449 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1450 xmlTextReaderValidatePush(reader);
1451 } else if ((node->type == XML_TEXT_NODE) ||
1452 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001453 xmlTextReaderValidateCData(reader, node->content,
1454 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001455 }
1456 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001457#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001458#ifdef LIBXML_PATTERN_ENABLED
1459 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1460 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1461 int i;
1462 for (i = 0;i < reader->patternNr;i++) {
1463 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1464 xmlTextReaderPreserve(reader);
1465 break;
1466 }
1467 }
1468 }
1469#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001470 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001471node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001472 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001473 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001474}
1475
Daniel Veillard67df8092002-12-16 22:04:11 +00001476/**
1477 * xmlTextReaderReadState:
1478 * @reader: the xmlTextReaderPtr used
1479 *
1480 * Gets the read state of the reader.
1481 *
1482 * Returns the state value, or -1 in case of error
1483 */
1484int
1485xmlTextReaderReadState(xmlTextReaderPtr reader) {
1486 if (reader == NULL)
1487 return(-1);
1488 return(reader->mode);
1489}
1490
1491/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001492 * xmlTextReaderExpand:
1493 * @reader: the xmlTextReaderPtr used
1494 *
1495 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001496 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001497 *
1498 * Returns a node pointer valid until the next xmlTextReaderRead() call
1499 * or NULL in case of error.
1500 */
1501xmlNodePtr
1502xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001503 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001504 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001505 if (reader->doc != NULL)
1506 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001507 if (reader->ctxt == NULL)
1508 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001509 if (xmlTextReaderDoExpand(reader) < 0)
1510 return(NULL);
1511 return(reader->node);
1512}
1513
1514/**
1515 * xmlTextReaderNext:
1516 * @reader: the xmlTextReaderPtr used
1517 *
1518 * Skip to the node following the current one in document order while
1519 * avoiding the subtree if any.
1520 *
1521 * Returns 1 if the node was read successfully, 0 if there is no more
1522 * nodes to read, or -1 in case of error
1523 */
1524int
1525xmlTextReaderNext(xmlTextReaderPtr reader) {
1526 int ret;
1527 xmlNodePtr cur;
1528
1529 if (reader == NULL)
1530 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001531 if (reader->doc != NULL)
1532 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001533 cur = reader->node;
1534 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1535 return(xmlTextReaderRead(reader));
1536 if (reader->state == XML_TEXTREADER_END)
1537 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001538 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001539 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001540 do {
1541 ret = xmlTextReaderRead(reader);
1542 if (ret != 1)
1543 return(ret);
1544 } while (reader->node != cur);
1545 return(xmlTextReaderRead(reader));
1546}
1547
1548/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001549 * xmlTextReaderReadInnerXml:
1550 * @reader: the xmlTextReaderPtr used
1551 *
1552 * Reads the contents of the current node, including child nodes and markup.
1553 *
1554 * Returns a string containing the XML content, or NULL if the current node
1555 * is neither an element nor attribute, or has no child nodes. The
1556 * string must be deallocated by the caller.
1557 */
1558xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001559xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001560 TODO
1561 return(NULL);
1562}
1563
1564/**
1565 * xmlTextReaderReadOuterXml:
1566 * @reader: the xmlTextReaderPtr used
1567 *
1568 * Reads the contents of the current node, including child nodes and markup.
1569 *
1570 * Returns a string containing the XML content, or NULL if the current node
1571 * is neither an element nor attribute, or has no child nodes. The
1572 * string must be deallocated by the caller.
1573 */
1574xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001575xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001576 TODO
1577 return(NULL);
1578}
1579
1580/**
1581 * xmlTextReaderReadString:
1582 * @reader: the xmlTextReaderPtr used
1583 *
1584 * Reads the contents of an element or a text node as a string.
1585 *
1586 * Returns a string containing the contents of the Element or Text node,
1587 * or NULL if the reader is positioned on any other type of node.
1588 * The string must be deallocated by the caller.
1589 */
1590xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001591xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001592 TODO
1593 return(NULL);
1594}
1595
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001596#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001597/**
1598 * xmlTextReaderReadBase64:
1599 * @reader: the xmlTextReaderPtr used
1600 * @array: a byte array to store the content.
1601 * @offset: the zero-based index into array where the method should
1602 * begin to write.
1603 * @len: the number of bytes to write.
1604 *
1605 * Reads and decodes the Base64 encoded contents of an element and
1606 * stores the result in a byte buffer.
1607 *
1608 * Returns the number of bytes written to array, or zero if the current
1609 * instance is not positioned on an element or -1 in case of error.
1610 */
1611int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001612xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1613 unsigned char *array ATTRIBUTE_UNUSED,
1614 int offset ATTRIBUTE_UNUSED,
1615 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001616 if ((reader == NULL) || (reader->ctxt == NULL))
1617 return(-1);
1618 if (reader->ctxt->wellFormed != 1)
1619 return(-1);
1620
1621 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1622 return(0);
1623 TODO
1624 return(0);
1625}
1626
1627/**
1628 * xmlTextReaderReadBinHex:
1629 * @reader: the xmlTextReaderPtr used
1630 * @array: a byte array to store the content.
1631 * @offset: the zero-based index into array where the method should
1632 * begin to write.
1633 * @len: the number of bytes to write.
1634 *
1635 * Reads and decodes the BinHex encoded contents of an element and
1636 * stores the result in a byte buffer.
1637 *
1638 * Returns the number of bytes written to array, or zero if the current
1639 * instance is not positioned on an element or -1 in case of error.
1640 */
1641int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001642xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1643 unsigned char *array ATTRIBUTE_UNUSED,
1644 int offset ATTRIBUTE_UNUSED,
1645 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001646 if ((reader == NULL) || (reader->ctxt == NULL))
1647 return(-1);
1648 if (reader->ctxt->wellFormed != 1)
1649 return(-1);
1650
1651 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1652 return(0);
1653 TODO
1654 return(0);
1655}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001656#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001657
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001658/************************************************************************
1659 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001660 * Operating on a preparsed tree *
1661 * *
1662 ************************************************************************/
1663static int
1664xmlTextReaderNextTree(xmlTextReaderPtr reader)
1665{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001666 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001667 return(-1);
1668
1669 if (reader->state == XML_TEXTREADER_END)
1670 return(0);
1671
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001672 if (reader->node == NULL) {
1673 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001674 reader->state = XML_TEXTREADER_END;
1675 return(0);
1676 }
1677
1678 reader->node = reader->doc->children;
1679 reader->state = XML_TEXTREADER_START;
1680 return(1);
1681 }
1682
1683 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1684 if (reader->node->children != 0) {
1685 reader->node = reader->node->children;
1686 reader->depth++;
1687 reader->state = XML_TEXTREADER_START;
1688 return(1);
1689 }
1690
1691 if ((reader->node->type == XML_ELEMENT_NODE) ||
1692 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1693 reader->state = XML_TEXTREADER_BACKTRACK;
1694 return(1);
1695 }
1696 }
1697
1698 if (reader->node->next != 0) {
1699 reader->node = reader->node->next;
1700 reader->state = XML_TEXTREADER_START;
1701 return(1);
1702 }
1703
1704 if (reader->node->parent != 0) {
1705 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1706 reader->state = XML_TEXTREADER_END;
1707 return(0);
1708 }
1709
1710 reader->node = reader->node->parent;
1711 reader->depth--;
1712 reader->state = XML_TEXTREADER_BACKTRACK;
1713 return(1);
1714 }
1715
1716 reader->state = XML_TEXTREADER_END;
1717
1718 return(1);
1719}
1720
1721/**
1722 * xmlTextReaderReadTree:
1723 * @reader: the xmlTextReaderPtr used
1724 *
1725 * Moves the position of the current instance to the next node in
1726 * the stream, exposing its properties.
1727 *
1728 * Returns 1 if the node was read successfully, 0 if there is no more
1729 * nodes to read, or -1 in case of error
1730 */
1731static int
1732xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1733 if (reader->state == XML_TEXTREADER_END)
1734 return(0);
1735
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001736next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001737 if (reader->node == NULL) {
1738 if (reader->doc->children == NULL) {
1739 reader->state = XML_TEXTREADER_END;
1740 return(0);
1741 }
1742
1743 reader->node = reader->doc->children;
1744 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001745 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001746 }
1747
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001748 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1749 (reader->node->type != XML_DTD_NODE) &&
1750 (reader->node->type != XML_XINCLUDE_START) &&
1751 (reader->node->type != XML_ENTITY_REF_NODE)) {
1752 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001753 reader->node = reader->node->children;
1754 reader->depth++;
1755 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001756 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001757 }
1758
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001759 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001760 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001761 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001762 }
1763 }
1764
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001765 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001766 reader->node = reader->node->next;
1767 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001768 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001769 }
1770
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001771 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001772 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1773 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1774 reader->state = XML_TEXTREADER_END;
1775 return(0);
1776 }
1777
1778 reader->node = reader->node->parent;
1779 reader->depth--;
1780 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001781 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001782 }
1783
1784 reader->state = XML_TEXTREADER_END;
1785
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001786found_node:
1787 if ((reader->node->type == XML_XINCLUDE_START) ||
1788 (reader->node->type == XML_XINCLUDE_END))
1789 goto next_node;
1790
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001791 return(1);
1792}
1793
1794/**
William M. Brackb1d53162003-11-18 06:54:40 +00001795 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001796 * @reader: the xmlTextReaderPtr used
1797 *
1798 * Skip to the node following the current one in document order while
1799 * avoiding the subtree if any.
1800 * Currently implemented only for Readers built on a document
1801 *
1802 * Returns 1 if the node was read successfully, 0 if there is no more
1803 * nodes to read, or -1 in case of error
1804 */
1805int
1806xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1807 if (reader == NULL)
1808 return(-1);
1809 if (reader->doc == NULL) {
1810 TODO
1811 return(-1);
1812 }
1813
1814 if (reader->state == XML_TEXTREADER_END)
1815 return(0);
1816
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001817 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001818 return(xmlTextReaderNextTree(reader));
1819
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001820 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001821 reader->node = reader->node->next;
1822 reader->state = XML_TEXTREADER_START;
1823 return(1);
1824 }
1825
1826 return(0);
1827}
1828
1829/************************************************************************
1830 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001831 * Constructor and destructors *
1832 * *
1833 ************************************************************************/
1834/**
1835 * xmlNewTextReader:
1836 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001837 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001838 *
1839 * Create an xmlTextReader structure fed with @input
1840 *
1841 * Returns the new xmlTextReaderPtr or NULL in case of error
1842 */
1843xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001844xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001845 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001846
1847 if (input == NULL)
1848 return(NULL);
1849 ret = xmlMalloc(sizeof(xmlTextReader));
1850 if (ret == NULL) {
1851 xmlGenericError(xmlGenericErrorContext,
1852 "xmlNewTextReader : malloc failed\n");
1853 return(NULL);
1854 }
1855 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001856 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001857 ret->entTab = NULL;
1858 ret->entMax = 0;
1859 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001860 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001861 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001862 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1863 if (ret->sax == NULL) {
1864 xmlFree(ret);
1865 xmlGenericError(xmlGenericErrorContext,
1866 "xmlNewTextReader : malloc failed\n");
1867 return(NULL);
1868 }
Daniel Veillard81273902003-09-30 00:43:48 +00001869 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001870 ret->startElement = ret->sax->startElement;
1871 ret->sax->startElement = xmlTextReaderStartElement;
1872 ret->endElement = ret->sax->endElement;
1873 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001874#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001875 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001876#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001877 ret->startElementNs = ret->sax->startElementNs;
1878 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1879 ret->endElementNs = ret->sax->endElementNs;
1880 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001881#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001882 } else {
1883 ret->startElementNs = NULL;
1884 ret->endElementNs = NULL;
1885 }
Daniel Veillard81273902003-09-30 00:43:48 +00001886#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001887 ret->characters = ret->sax->characters;
1888 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001889 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001890 ret->cdataBlock = ret->sax->cdataBlock;
1891 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001892
Daniel Veillard67df8092002-12-16 22:04:11 +00001893 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001894 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001895 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001896 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001897 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001898 }
1899 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001900 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001901 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001902 ret->base = 0;
1903 ret->cur = 4;
1904 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001905 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001906 ret->base = 0;
1907 ret->cur = 0;
1908 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001909 if (ret->ctxt == NULL) {
1910 xmlGenericError(xmlGenericErrorContext,
1911 "xmlNewTextReader : malloc failed\n");
1912 xmlFree(ret->sax);
1913 xmlFree(ret);
1914 return(NULL);
1915 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001916 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001917 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001918 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001919 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001920 /*
1921 * use the parser dictionnary to allocate all elements and attributes names
1922 */
1923 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001924 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001925#ifdef LIBXML_XINCLUDE_ENABLED
1926 ret->xinclude = 0;
1927#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001928#ifdef LIBXML_PATTERN_ENABLED
1929 ret->patternMax = 0;
1930 ret->patternTab = NULL;
1931#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001932 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001933}
1934
1935/**
1936 * xmlNewTextReaderFilename:
1937 * @URI: the URI of the resource to process
1938 *
1939 * Create an xmlTextReader structure fed with the resource at @URI
1940 *
1941 * Returns the new xmlTextReaderPtr or NULL in case of error
1942 */
1943xmlTextReaderPtr
1944xmlNewTextReaderFilename(const char *URI) {
1945 xmlParserInputBufferPtr input;
1946 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001947 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001948
1949 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1950 if (input == NULL)
1951 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001952 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001953 if (ret == NULL) {
1954 xmlFreeParserInputBuffer(input);
1955 return(NULL);
1956 }
1957 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001958 if (ret->ctxt->directory == NULL)
1959 directory = xmlParserGetDirectory(URI);
1960 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1961 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1962 if (directory != NULL)
1963 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001964 return(ret);
1965}
1966
1967/**
1968 * xmlFreeTextReader:
1969 * @reader: the xmlTextReaderPtr
1970 *
1971 * Deallocate all the resources associated to the reader
1972 */
1973void
1974xmlFreeTextReader(xmlTextReaderPtr reader) {
1975 if (reader == NULL)
1976 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001977#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001978 if (reader->rngSchemas != NULL) {
1979 xmlRelaxNGFree(reader->rngSchemas);
1980 reader->rngSchemas = NULL;
1981 }
1982 if (reader->rngValidCtxt != NULL) {
1983 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1984 reader->rngValidCtxt = NULL;
1985 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001986#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001987#ifdef LIBXML_XINCLUDE_ENABLED
1988 if (reader->xincctxt != NULL)
1989 xmlXIncludeFreeContext(reader->xincctxt);
1990#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001991#ifdef LIBXML_PATTERN_ENABLED
1992 if (reader->patternTab != NULL) {
1993 int i;
1994 for (i = 0;i < reader->patternNr;i++) {
1995 if (reader->patternTab[i] != NULL)
1996 xmlFreePattern(reader->patternTab[i]);
1997 }
1998 xmlFree(reader->patternTab);
1999 }
2000#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002001 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002002 if (reader->dict == reader->ctxt->dict)
2003 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002004 if (reader->ctxt->myDoc != NULL) {
2005 if (reader->preserve == 0)
2006 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2007 reader->ctxt->myDoc = NULL;
2008 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002009 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2010 (reader->ctxt->vctxt.vstateMax > 0)){
2011 xmlFree(reader->ctxt->vctxt.vstateTab);
2012 reader->ctxt->vctxt.vstateTab = 0;
2013 reader->ctxt->vctxt.vstateMax = 0;
2014 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002015 if (reader->allocs & XML_TEXTREADER_CTXT)
2016 xmlFreeParserCtxt(reader->ctxt);
2017 }
2018 if (reader->sax != NULL)
2019 xmlFree(reader->sax);
2020 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2021 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002022 if (reader->faketext != NULL) {
2023 xmlFreeNode(reader->faketext);
2024 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002025 if (reader->buffer != NULL)
2026 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002027 if (reader->entTab != NULL)
2028 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002029 if (reader->dict != NULL)
2030 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002031 xmlFree(reader);
2032}
2033
2034/************************************************************************
2035 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002036 * Methods for XmlTextReader *
2037 * *
2038 ************************************************************************/
2039/**
2040 * xmlTextReaderClose:
2041 * @reader: the xmlTextReaderPtr used
2042 *
2043 * This method releases any resources allocated by the current instance
2044 * changes the state to Closed and close any underlying input.
2045 *
2046 * Returns 0 or -1 in case of error
2047 */
2048int
2049xmlTextReaderClose(xmlTextReaderPtr reader) {
2050 if (reader == NULL)
2051 return(-1);
2052 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002053 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002054 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2055 if (reader->ctxt != NULL) {
2056 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002057 if (reader->preserve == 0)
2058 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002059 reader->ctxt->myDoc = NULL;
2060 }
2061 if (reader->allocs & XML_TEXTREADER_CTXT) {
2062 xmlFreeParserCtxt(reader->ctxt);
2063 reader->allocs -= XML_TEXTREADER_CTXT;
2064 }
2065 }
2066 if (reader->sax != NULL) {
2067 xmlFree(reader->sax);
2068 reader->sax = NULL;
2069 }
2070 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2071 xmlFreeParserInputBuffer(reader->input);
2072 reader->allocs -= XML_TEXTREADER_INPUT;
2073 }
2074 return(0);
2075}
2076
2077/**
2078 * xmlTextReaderGetAttributeNo:
2079 * @reader: the xmlTextReaderPtr used
2080 * @no: the zero-based index of the attribute relative to the containing element
2081 *
2082 * Provides the value of the attribute with the specified index relative
2083 * to the containing element.
2084 *
2085 * Returns a string containing the value of the specified attribute, or NULL
2086 * in case of error. The string must be deallocated by the caller.
2087 */
2088xmlChar *
2089xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2090 xmlChar *ret;
2091 int i;
2092 xmlAttrPtr cur;
2093 xmlNsPtr ns;
2094
2095 if (reader == NULL)
2096 return(NULL);
2097 if (reader->node == NULL)
2098 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002099 if (reader->curnode != NULL)
2100 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002101 /* TODO: handle the xmlDecl */
2102 if (reader->node->type != XML_ELEMENT_NODE)
2103 return(NULL);
2104
2105 ns = reader->node->nsDef;
2106 for (i = 0;(i < no) && (ns != NULL);i++) {
2107 ns = ns->next;
2108 }
2109 if (ns != NULL)
2110 return(xmlStrdup(ns->href));
2111
2112 cur = reader->node->properties;
2113 if (cur == NULL)
2114 return(NULL);
2115 for (;i < no;i++) {
2116 cur = cur->next;
2117 if (cur == NULL)
2118 return(NULL);
2119 }
2120 /* TODO walk the DTD if present */
2121
2122 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2123 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2124 return(ret);
2125}
2126
2127/**
2128 * xmlTextReaderGetAttribute:
2129 * @reader: the xmlTextReaderPtr used
2130 * @name: the qualified name of the attribute.
2131 *
2132 * Provides the value of the attribute with the specified qualified name.
2133 *
2134 * Returns a string containing the value of the specified attribute, or NULL
2135 * in case of error. The string must be deallocated by the caller.
2136 */
2137xmlChar *
2138xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2139 xmlChar *prefix = NULL;
2140 xmlChar *localname;
2141 xmlNsPtr ns;
2142 xmlChar *ret = NULL;
2143
2144 if ((reader == NULL) || (name == NULL))
2145 return(NULL);
2146 if (reader->node == NULL)
2147 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002148 if (reader->curnode != NULL)
2149 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002150
2151 /* TODO: handle the xmlDecl */
2152 if (reader->node->type != XML_ELEMENT_NODE)
2153 return(NULL);
2154
2155 localname = xmlSplitQName2(name, &prefix);
2156 if (localname == NULL)
2157 return(xmlGetProp(reader->node, name));
2158
2159 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2160 if (ns != NULL)
2161 ret = xmlGetNsProp(reader->node, localname, ns->href);
2162
2163 if (localname != NULL)
2164 xmlFree(localname);
2165 if (prefix != NULL)
2166 xmlFree(prefix);
2167 return(ret);
2168}
2169
2170
2171/**
2172 * xmlTextReaderGetAttributeNs:
2173 * @reader: the xmlTextReaderPtr used
2174 * @localName: the local name of the attribute.
2175 * @namespaceURI: the namespace URI of the attribute.
2176 *
2177 * Provides the value of the specified attribute
2178 *
2179 * Returns a string containing the value of the specified attribute, or NULL
2180 * in case of error. The string must be deallocated by the caller.
2181 */
2182xmlChar *
2183xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2184 const xmlChar *namespaceURI) {
2185 if ((reader == NULL) || (localName == NULL))
2186 return(NULL);
2187 if (reader->node == NULL)
2188 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002189 if (reader->curnode != NULL)
2190 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002191
2192 /* TODO: handle the xmlDecl */
2193 if (reader->node->type != XML_ELEMENT_NODE)
2194 return(NULL);
2195
2196 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2197}
2198
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002199/**
2200 * xmlTextReaderGetRemainder:
2201 * @reader: the xmlTextReaderPtr used
2202 *
2203 * Method to get the remainder of the buffered XML. this method stops the
2204 * parser, set its state to End Of File and return the input stream with
2205 * what is left that the parser did not use.
2206 *
2207 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2208 * in case of error.
2209 */
2210xmlParserInputBufferPtr
2211xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2212 xmlParserInputBufferPtr ret = NULL;
2213
2214 if (reader == NULL)
2215 return(NULL);
2216 if (reader->node == NULL)
2217 return(NULL);
2218
2219 reader->node = NULL;
2220 reader->curnode = NULL;
2221 reader->mode = XML_TEXTREADER_MODE_EOF;
2222 if (reader->ctxt != NULL) {
2223 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002224 if (reader->preserve == 0)
2225 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002226 reader->ctxt->myDoc = NULL;
2227 }
2228 if (reader->allocs & XML_TEXTREADER_CTXT) {
2229 xmlFreeParserCtxt(reader->ctxt);
2230 reader->allocs -= XML_TEXTREADER_CTXT;
2231 }
2232 }
2233 if (reader->sax != NULL) {
2234 xmlFree(reader->sax);
2235 reader->sax = NULL;
2236 }
2237 if (reader->allocs & XML_TEXTREADER_INPUT) {
2238 ret = reader->input;
2239 reader->allocs -= XML_TEXTREADER_INPUT;
2240 } else {
2241 /*
2242 * Hum, one may need to duplicate the data structure because
2243 * without reference counting the input may be freed twice:
2244 * - by the layer which allocated it.
2245 * - by the layer to which would have been returned to.
2246 */
2247 TODO
2248 return(NULL);
2249 }
2250 return(ret);
2251}
2252
2253/**
2254 * xmlTextReaderLookupNamespace:
2255 * @reader: the xmlTextReaderPtr used
2256 * @prefix: the prefix whose namespace URI is to be resolved. To return
2257 * the default namespace, specify NULL
2258 *
2259 * Resolves a namespace prefix in the scope of the current element.
2260 *
2261 * Returns a string containing the namespace URI to which the prefix maps
2262 * or NULL in case of error. The string must be deallocated by the caller.
2263 */
2264xmlChar *
2265xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2266 xmlNsPtr ns;
2267
2268 if (reader == NULL)
2269 return(NULL);
2270 if (reader->node == NULL)
2271 return(NULL);
2272
2273 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2274 if (ns == NULL)
2275 return(NULL);
2276 return(xmlStrdup(ns->href));
2277}
2278
2279/**
2280 * xmlTextReaderMoveToAttributeNo:
2281 * @reader: the xmlTextReaderPtr used
2282 * @no: the zero-based index of the attribute relative to the containing
2283 * element.
2284 *
2285 * Moves the position of the current instance to the attribute with
2286 * the specified index relative to the containing element.
2287 *
2288 * Returns 1 in case of success, -1 in case of error, 0 if not found
2289 */
2290int
2291xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2292 int i;
2293 xmlAttrPtr cur;
2294 xmlNsPtr ns;
2295
2296 if (reader == NULL)
2297 return(-1);
2298 if (reader->node == NULL)
2299 return(-1);
2300 /* TODO: handle the xmlDecl */
2301 if (reader->node->type != XML_ELEMENT_NODE)
2302 return(-1);
2303
2304 reader->curnode = NULL;
2305
2306 ns = reader->node->nsDef;
2307 for (i = 0;(i < no) && (ns != NULL);i++) {
2308 ns = ns->next;
2309 }
2310 if (ns != NULL) {
2311 reader->curnode = (xmlNodePtr) ns;
2312 return(1);
2313 }
2314
2315 cur = reader->node->properties;
2316 if (cur == NULL)
2317 return(0);
2318 for (;i < no;i++) {
2319 cur = cur->next;
2320 if (cur == NULL)
2321 return(0);
2322 }
2323 /* TODO walk the DTD if present */
2324
2325 reader->curnode = (xmlNodePtr) cur;
2326 return(1);
2327}
2328
2329/**
2330 * xmlTextReaderMoveToAttribute:
2331 * @reader: the xmlTextReaderPtr used
2332 * @name: the qualified name of the attribute.
2333 *
2334 * Moves the position of the current instance to the attribute with
2335 * the specified qualified name.
2336 *
2337 * Returns 1 in case of success, -1 in case of error, 0 if not found
2338 */
2339int
2340xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2341 xmlChar *prefix = NULL;
2342 xmlChar *localname;
2343 xmlNsPtr ns;
2344 xmlAttrPtr prop;
2345
2346 if ((reader == NULL) || (name == NULL))
2347 return(-1);
2348 if (reader->node == NULL)
2349 return(-1);
2350
2351 /* TODO: handle the xmlDecl */
2352 if (reader->node->type != XML_ELEMENT_NODE)
2353 return(0);
2354
2355 localname = xmlSplitQName2(name, &prefix);
2356 if (localname == NULL) {
2357 /*
2358 * Namespace default decl
2359 */
2360 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2361 ns = reader->node->nsDef;
2362 while (ns != NULL) {
2363 if (ns->prefix == NULL) {
2364 reader->curnode = (xmlNodePtr) ns;
2365 return(1);
2366 }
2367 ns = ns->next;
2368 }
2369 return(0);
2370 }
2371
2372 prop = reader->node->properties;
2373 while (prop != NULL) {
2374 /*
2375 * One need to have
2376 * - same attribute names
2377 * - and the attribute carrying that namespace
2378 */
2379 if ((xmlStrEqual(prop->name, name)) &&
2380 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2381 reader->curnode = (xmlNodePtr) prop;
2382 return(1);
2383 }
2384 prop = prop->next;
2385 }
2386 return(0);
2387 }
2388
2389 /*
2390 * Namespace default decl
2391 */
2392 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2393 ns = reader->node->nsDef;
2394 while (ns != NULL) {
2395 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2396 reader->curnode = (xmlNodePtr) ns;
2397 goto found;
2398 }
2399 ns = ns->next;
2400 }
2401 goto not_found;
2402 }
2403 prop = reader->node->properties;
2404 while (prop != NULL) {
2405 /*
2406 * One need to have
2407 * - same attribute names
2408 * - and the attribute carrying that namespace
2409 */
2410 if ((xmlStrEqual(prop->name, localname)) &&
2411 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2412 reader->curnode = (xmlNodePtr) prop;
2413 goto found;
2414 }
2415 prop = prop->next;
2416 }
2417not_found:
2418 if (localname != NULL)
2419 xmlFree(localname);
2420 if (prefix != NULL)
2421 xmlFree(prefix);
2422 return(0);
2423
2424found:
2425 if (localname != NULL)
2426 xmlFree(localname);
2427 if (prefix != NULL)
2428 xmlFree(prefix);
2429 return(1);
2430}
2431
2432/**
2433 * xmlTextReaderMoveToAttributeNs:
2434 * @reader: the xmlTextReaderPtr used
2435 * @localName: the local name of the attribute.
2436 * @namespaceURI: the namespace URI of the attribute.
2437 *
2438 * Moves the position of the current instance to the attribute with the
2439 * specified local name and namespace URI.
2440 *
2441 * Returns 1 in case of success, -1 in case of error, 0 if not found
2442 */
2443int
2444xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2445 const xmlChar *localName, const xmlChar *namespaceURI) {
2446 xmlAttrPtr prop;
2447 xmlNodePtr node;
2448
2449 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2450 return(-1);
2451 if (reader->node == NULL)
2452 return(-1);
2453 if (reader->node->type != XML_ELEMENT_NODE)
2454 return(0);
2455 node = reader->node;
2456
2457 /*
2458 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2459 * namespace name associated to "xmlns"
2460 */
2461 prop = node->properties;
2462 while (prop != NULL) {
2463 /*
2464 * One need to have
2465 * - same attribute names
2466 * - and the attribute carrying that namespace
2467 */
2468 if (xmlStrEqual(prop->name, localName) &&
2469 ((prop->ns != NULL) &&
2470 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2471 reader->curnode = (xmlNodePtr) prop;
2472 return(1);
2473 }
2474 prop = prop->next;
2475 }
2476 return(0);
2477}
2478
2479/**
2480 * xmlTextReaderMoveToFirstAttribute:
2481 * @reader: the xmlTextReaderPtr used
2482 *
2483 * Moves the position of the current instance to the first attribute
2484 * associated with the current node.
2485 *
2486 * Returns 1 in case of success, -1 in case of error, 0 if not found
2487 */
2488int
2489xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2490 if (reader == NULL)
2491 return(-1);
2492 if (reader->node == NULL)
2493 return(-1);
2494 if (reader->node->type != XML_ELEMENT_NODE)
2495 return(0);
2496
2497 if (reader->node->nsDef != NULL) {
2498 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2499 return(1);
2500 }
2501 if (reader->node->properties != NULL) {
2502 reader->curnode = (xmlNodePtr) reader->node->properties;
2503 return(1);
2504 }
2505 return(0);
2506}
2507
2508/**
2509 * xmlTextReaderMoveToNextAttribute:
2510 * @reader: the xmlTextReaderPtr used
2511 *
2512 * Moves the position of the current instance to the next attribute
2513 * associated with the current node.
2514 *
2515 * Returns 1 in case of success, -1 in case of error, 0 if not found
2516 */
2517int
2518xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2519 if (reader == NULL)
2520 return(-1);
2521 if (reader->node == NULL)
2522 return(-1);
2523 if (reader->node->type != XML_ELEMENT_NODE)
2524 return(0);
2525 if (reader->curnode == NULL)
2526 return(xmlTextReaderMoveToFirstAttribute(reader));
2527
2528 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2529 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2530 if (ns->next != NULL) {
2531 reader->curnode = (xmlNodePtr) ns->next;
2532 return(1);
2533 }
2534 if (reader->node->properties != NULL) {
2535 reader->curnode = (xmlNodePtr) reader->node->properties;
2536 return(1);
2537 }
2538 return(0);
2539 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2540 (reader->curnode->next != NULL)) {
2541 reader->curnode = reader->curnode->next;
2542 return(1);
2543 }
2544 return(0);
2545}
2546
2547/**
2548 * xmlTextReaderMoveToElement:
2549 * @reader: the xmlTextReaderPtr used
2550 *
2551 * Moves the position of the current instance to the node that
2552 * contains the current Attribute node.
2553 *
2554 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2555 */
2556int
2557xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2558 if (reader == NULL)
2559 return(-1);
2560 if (reader->node == NULL)
2561 return(-1);
2562 if (reader->node->type != XML_ELEMENT_NODE)
2563 return(0);
2564 if (reader->curnode != NULL) {
2565 reader->curnode = NULL;
2566 return(1);
2567 }
2568 return(0);
2569}
2570
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002571/**
2572 * xmlTextReaderReadAttributeValue:
2573 * @reader: the xmlTextReaderPtr used
2574 *
2575 * Parses an attribute value into one or more Text and EntityReference nodes.
2576 *
2577 * Returns 1 in case of success, 0 if the reader was not positionned on an
2578 * ttribute node or all the attribute values have been read, or -1
2579 * in case of error.
2580 */
2581int
2582xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2583 if (reader == NULL)
2584 return(-1);
2585 if (reader->node == NULL)
2586 return(-1);
2587 if (reader->curnode == NULL)
2588 return(0);
2589 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2590 if (reader->curnode->children == NULL)
2591 return(0);
2592 reader->curnode = reader->curnode->children;
2593 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2594 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2595
2596 if (reader->faketext == NULL) {
2597 reader->faketext = xmlNewDocText(reader->node->doc,
2598 ns->href);
2599 } else {
2600 if (reader->faketext->content != NULL)
2601 xmlFree(reader->faketext->content);
2602 reader->faketext->content = xmlStrdup(ns->href);
2603 }
2604 reader->curnode = reader->faketext;
2605 } else {
2606 if (reader->curnode->next == NULL)
2607 return(0);
2608 reader->curnode = reader->curnode->next;
2609 }
2610 return(1);
2611}
2612
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002613/************************************************************************
2614 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002615 * Acces API to the current node *
2616 * *
2617 ************************************************************************/
2618/**
2619 * xmlTextReaderAttributeCount:
2620 * @reader: the xmlTextReaderPtr used
2621 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002622 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002623 *
2624 * Returns 0 i no attributes, -1 in case of error or the attribute count
2625 */
2626int
2627xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2628 int ret;
2629 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002630 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002631 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002632
2633 if (reader == NULL)
2634 return(-1);
2635 if (reader->node == NULL)
2636 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002637
2638 if (reader->curnode != NULL)
2639 node = reader->curnode;
2640 else
2641 node = reader->node;
2642
2643 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002644 return(0);
2645 if ((reader->state == XML_TEXTREADER_END) ||
2646 (reader->state == XML_TEXTREADER_BACKTRACK))
2647 return(0);
2648 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002649 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002650 while (attr != NULL) {
2651 ret++;
2652 attr = attr->next;
2653 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002654 ns = node->nsDef;
2655 while (ns != NULL) {
2656 ret++;
2657 ns = ns->next;
2658 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002659 return(ret);
2660}
2661
2662/**
2663 * xmlTextReaderNodeType:
2664 * @reader: the xmlTextReaderPtr used
2665 *
2666 * Get the node type of the current node
2667 * Reference:
2668 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2669 *
2670 * Returns the xmlNodeType of the current node or -1 in case of error
2671 */
2672int
2673xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002674 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002675
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002676 if (reader == NULL)
2677 return(-1);
2678 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002679 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002680 if (reader->curnode != NULL)
2681 node = reader->curnode;
2682 else
2683 node = reader->node;
2684 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002685 case XML_ELEMENT_NODE:
2686 if ((reader->state == XML_TEXTREADER_END) ||
2687 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002688 return(XML_READER_TYPE_END_ELEMENT);
2689 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002690 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002691 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002692 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002693 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002694 if (xmlIsBlankNode(reader->node)) {
2695 if (xmlNodeGetSpacePreserve(reader->node))
2696 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2697 else
2698 return(XML_READER_TYPE_WHITESPACE);
2699 } else {
2700 return(XML_READER_TYPE_TEXT);
2701 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002702 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002703 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002704 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002705 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002706 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002707 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002708 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002709 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002710 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002711 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002712 case XML_DOCUMENT_NODE:
2713 case XML_HTML_DOCUMENT_NODE:
2714#ifdef LIBXML_DOCB_ENABLED
2715 case XML_DOCB_DOCUMENT_NODE:
2716#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002717 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002718 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002719 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002720 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002721 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002722 case XML_DOCUMENT_TYPE_NODE:
2723 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002724 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002725
2726 case XML_ELEMENT_DECL:
2727 case XML_ATTRIBUTE_DECL:
2728 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002729 case XML_XINCLUDE_START:
2730 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002731 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002732 }
2733 return(-1);
2734}
2735
2736/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002737 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002738 * @reader: the xmlTextReaderPtr used
2739 *
2740 * Check if the current node is empty
2741 *
2742 * Returns 1 if empty, 0 if not and -1 in case of error
2743 */
2744int
2745xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2746 if ((reader == NULL) || (reader->node == NULL))
2747 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002748 if (reader->node->type != XML_ELEMENT_NODE)
2749 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002750 if (reader->curnode != NULL)
2751 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002752 if (reader->node->children != NULL)
2753 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002754 if (reader->state == XML_TEXTREADER_END)
2755 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002756 if (reader->doc != NULL)
2757 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002758#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002759 if (reader->in_xinclude > 0)
2760 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002761#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002762 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002763}
2764
2765/**
2766 * xmlTextReaderLocalName:
2767 * @reader: the xmlTextReaderPtr used
2768 *
2769 * The local name of the node.
2770 *
2771 * Returns the local name or NULL if not available
2772 */
2773xmlChar *
2774xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002775 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002776 if ((reader == NULL) || (reader->node == NULL))
2777 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002778 if (reader->curnode != NULL)
2779 node = reader->curnode;
2780 else
2781 node = reader->node;
2782 if (node->type == XML_NAMESPACE_DECL) {
2783 xmlNsPtr ns = (xmlNsPtr) node;
2784 if (ns->prefix == NULL)
2785 return(xmlStrdup(BAD_CAST "xmlns"));
2786 else
2787 return(xmlStrdup(ns->prefix));
2788 }
2789 if ((node->type != XML_ELEMENT_NODE) &&
2790 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002791 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002792 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002793}
2794
2795/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002796 * xmlTextReaderConstLocalName:
2797 * @reader: the xmlTextReaderPtr used
2798 *
2799 * The local name of the node.
2800 *
2801 * Returns the local name or NULL if not available, the
2802 * string will be deallocated with the reader.
2803 */
2804const xmlChar *
2805xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2806 xmlNodePtr node;
2807 if ((reader == NULL) || (reader->node == NULL))
2808 return(NULL);
2809 if (reader->curnode != NULL)
2810 node = reader->curnode;
2811 else
2812 node = reader->node;
2813 if (node->type == XML_NAMESPACE_DECL) {
2814 xmlNsPtr ns = (xmlNsPtr) node;
2815 if (ns->prefix == NULL)
2816 return(CONSTSTR(BAD_CAST "xmlns"));
2817 else
2818 return(ns->prefix);
2819 }
2820 if ((node->type != XML_ELEMENT_NODE) &&
2821 (node->type != XML_ATTRIBUTE_NODE))
2822 return(xmlTextReaderConstName(reader));
2823 return(node->name);
2824}
2825
2826/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002827 * xmlTextReaderName:
2828 * @reader: the xmlTextReaderPtr used
2829 *
2830 * The qualified name of the node, equal to Prefix :LocalName.
2831 *
2832 * Returns the local name or NULL if not available
2833 */
2834xmlChar *
2835xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002836 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002837 xmlChar *ret;
2838
2839 if ((reader == NULL) || (reader->node == NULL))
2840 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002841 if (reader->curnode != NULL)
2842 node = reader->curnode;
2843 else
2844 node = reader->node;
2845 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002846 case XML_ELEMENT_NODE:
2847 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002848 if ((node->ns == NULL) ||
2849 (node->ns->prefix == NULL))
2850 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002851
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002852 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002853 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002854 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002855 return(ret);
2856 case XML_TEXT_NODE:
2857 return(xmlStrdup(BAD_CAST "#text"));
2858 case XML_CDATA_SECTION_NODE:
2859 return(xmlStrdup(BAD_CAST "#cdata-section"));
2860 case XML_ENTITY_NODE:
2861 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002862 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002863 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002864 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002865 case XML_COMMENT_NODE:
2866 return(xmlStrdup(BAD_CAST "#comment"));
2867 case XML_DOCUMENT_NODE:
2868 case XML_HTML_DOCUMENT_NODE:
2869#ifdef LIBXML_DOCB_ENABLED
2870 case XML_DOCB_DOCUMENT_NODE:
2871#endif
2872 return(xmlStrdup(BAD_CAST "#document"));
2873 case XML_DOCUMENT_FRAG_NODE:
2874 return(xmlStrdup(BAD_CAST "#document-fragment"));
2875 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002876 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002877 case XML_DOCUMENT_TYPE_NODE:
2878 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002879 return(xmlStrdup(node->name));
2880 case XML_NAMESPACE_DECL: {
2881 xmlNsPtr ns = (xmlNsPtr) node;
2882
2883 ret = xmlStrdup(BAD_CAST "xmlns");
2884 if (ns->prefix == NULL)
2885 return(ret);
2886 ret = xmlStrcat(ret, BAD_CAST ":");
2887 ret = xmlStrcat(ret, ns->prefix);
2888 return(ret);
2889 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002890
2891 case XML_ELEMENT_DECL:
2892 case XML_ATTRIBUTE_DECL:
2893 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002894 case XML_XINCLUDE_START:
2895 case XML_XINCLUDE_END:
2896 return(NULL);
2897 }
2898 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002899}
2900
2901/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002902 * xmlTextReaderConstName:
2903 * @reader: the xmlTextReaderPtr used
2904 *
2905 * The qualified name of the node, equal to Prefix :LocalName.
2906 *
2907 * Returns the local name or NULL if not available, the string is
2908 * deallocated with the reader.
2909 */
2910const xmlChar *
2911xmlTextReaderConstName(xmlTextReaderPtr reader) {
2912 xmlNodePtr node;
2913
2914 if ((reader == NULL) || (reader->node == NULL))
2915 return(NULL);
2916 if (reader->curnode != NULL)
2917 node = reader->curnode;
2918 else
2919 node = reader->node;
2920 switch (node->type) {
2921 case XML_ELEMENT_NODE:
2922 case XML_ATTRIBUTE_NODE:
2923 if ((node->ns == NULL) ||
2924 (node->ns->prefix == NULL))
2925 return(node->name);
2926 return(CONSTQSTR(node->ns->prefix, node->name));
2927 case XML_TEXT_NODE:
2928 return(CONSTSTR(BAD_CAST "#text"));
2929 case XML_CDATA_SECTION_NODE:
2930 return(CONSTSTR(BAD_CAST "#cdata-section"));
2931 case XML_ENTITY_NODE:
2932 case XML_ENTITY_REF_NODE:
2933 return(CONSTSTR(node->name));
2934 case XML_PI_NODE:
2935 return(CONSTSTR(node->name));
2936 case XML_COMMENT_NODE:
2937 return(CONSTSTR(BAD_CAST "#comment"));
2938 case XML_DOCUMENT_NODE:
2939 case XML_HTML_DOCUMENT_NODE:
2940#ifdef LIBXML_DOCB_ENABLED
2941 case XML_DOCB_DOCUMENT_NODE:
2942#endif
2943 return(CONSTSTR(BAD_CAST "#document"));
2944 case XML_DOCUMENT_FRAG_NODE:
2945 return(CONSTSTR(BAD_CAST "#document-fragment"));
2946 case XML_NOTATION_NODE:
2947 return(CONSTSTR(node->name));
2948 case XML_DOCUMENT_TYPE_NODE:
2949 case XML_DTD_NODE:
2950 return(CONSTSTR(node->name));
2951 case XML_NAMESPACE_DECL: {
2952 xmlNsPtr ns = (xmlNsPtr) node;
2953
2954 if (ns->prefix == NULL)
2955 return(CONSTSTR(BAD_CAST "xmlns"));
2956 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2957 }
2958
2959 case XML_ELEMENT_DECL:
2960 case XML_ATTRIBUTE_DECL:
2961 case XML_ENTITY_DECL:
2962 case XML_XINCLUDE_START:
2963 case XML_XINCLUDE_END:
2964 return(NULL);
2965 }
2966 return(NULL);
2967}
2968
2969/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002970 * xmlTextReaderPrefix:
2971 * @reader: the xmlTextReaderPtr used
2972 *
2973 * A shorthand reference to the namespace associated with the node.
2974 *
2975 * Returns the prefix or NULL if not available
2976 */
2977xmlChar *
2978xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002979 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002980 if ((reader == NULL) || (reader->node == NULL))
2981 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002982 if (reader->curnode != NULL)
2983 node = reader->curnode;
2984 else
2985 node = reader->node;
2986 if (node->type == XML_NAMESPACE_DECL) {
2987 xmlNsPtr ns = (xmlNsPtr) node;
2988 if (ns->prefix == NULL)
2989 return(NULL);
2990 return(xmlStrdup(BAD_CAST "xmlns"));
2991 }
2992 if ((node->type != XML_ELEMENT_NODE) &&
2993 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002994 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002995 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002996 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002997 return(NULL);
2998}
2999
3000/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003001 * xmlTextReaderConstPrefix:
3002 * @reader: the xmlTextReaderPtr used
3003 *
3004 * A shorthand reference to the namespace associated with the node.
3005 *
3006 * Returns the prefix or NULL if not available, the string is deallocated
3007 * with the reader.
3008 */
3009const xmlChar *
3010xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3011 xmlNodePtr node;
3012 if ((reader == NULL) || (reader->node == NULL))
3013 return(NULL);
3014 if (reader->curnode != NULL)
3015 node = reader->curnode;
3016 else
3017 node = reader->node;
3018 if (node->type == XML_NAMESPACE_DECL) {
3019 xmlNsPtr ns = (xmlNsPtr) node;
3020 if (ns->prefix == NULL)
3021 return(NULL);
3022 return(CONSTSTR(BAD_CAST "xmlns"));
3023 }
3024 if ((node->type != XML_ELEMENT_NODE) &&
3025 (node->type != XML_ATTRIBUTE_NODE))
3026 return(NULL);
3027 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3028 return(CONSTSTR(node->ns->prefix));
3029 return(NULL);
3030}
3031
3032/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003033 * xmlTextReaderNamespaceUri:
3034 * @reader: the xmlTextReaderPtr used
3035 *
3036 * The URI defining the namespace associated with the node.
3037 *
3038 * Returns the namespace URI or NULL if not available
3039 */
3040xmlChar *
3041xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003042 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003043 if ((reader == NULL) || (reader->node == NULL))
3044 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003045 if (reader->curnode != NULL)
3046 node = reader->curnode;
3047 else
3048 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003049 if (node->type == XML_NAMESPACE_DECL)
3050 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003051 if ((node->type != XML_ELEMENT_NODE) &&
3052 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003053 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003054 if (node->ns != NULL)
3055 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003056 return(NULL);
3057}
3058
3059/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003060 * xmlTextReaderConstNamespaceUri:
3061 * @reader: the xmlTextReaderPtr used
3062 *
3063 * The URI defining the namespace associated with the node.
3064 *
3065 * Returns the namespace URI or NULL if not available, the string
3066 * will be deallocated with the reader
3067 */
3068const xmlChar *
3069xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3070 xmlNodePtr node;
3071 if ((reader == NULL) || (reader->node == NULL))
3072 return(NULL);
3073 if (reader->curnode != NULL)
3074 node = reader->curnode;
3075 else
3076 node = reader->node;
3077 if (node->type == XML_NAMESPACE_DECL)
3078 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3079 if ((node->type != XML_ELEMENT_NODE) &&
3080 (node->type != XML_ATTRIBUTE_NODE))
3081 return(NULL);
3082 if (node->ns != NULL)
3083 return(CONSTSTR(node->ns->href));
3084 return(NULL);
3085}
3086
3087/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003088 * xmlTextReaderBaseUri:
3089 * @reader: the xmlTextReaderPtr used
3090 *
3091 * The base URI of the node.
3092 *
3093 * Returns the base URI or NULL if not available
3094 */
3095xmlChar *
3096xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3097 if ((reader == NULL) || (reader->node == NULL))
3098 return(NULL);
3099 return(xmlNodeGetBase(NULL, reader->node));
3100}
3101
3102/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003103 * xmlTextReaderConstBaseUri:
3104 * @reader: the xmlTextReaderPtr used
3105 *
3106 * The base URI of the node.
3107 *
3108 * Returns the base URI or NULL if not available, the string
3109 * will be deallocated with the reader
3110 */
3111const xmlChar *
3112xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3113 xmlChar *tmp;
3114 const xmlChar *ret;
3115
3116 if ((reader == NULL) || (reader->node == NULL))
3117 return(NULL);
3118 tmp = xmlNodeGetBase(NULL, reader->node);
3119 if (tmp == NULL)
3120 return(NULL);
3121 ret = CONSTSTR(tmp);
3122 xmlFree(tmp);
3123 return(ret);
3124}
3125
3126/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003127 * xmlTextReaderDepth:
3128 * @reader: the xmlTextReaderPtr used
3129 *
3130 * The depth of the node in the tree.
3131 *
3132 * Returns the depth or -1 in case of error
3133 */
3134int
3135xmlTextReaderDepth(xmlTextReaderPtr reader) {
3136 if (reader == NULL)
3137 return(-1);
3138 if (reader->node == NULL)
3139 return(0);
3140
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003141 if (reader->curnode != NULL) {
3142 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3143 (reader->curnode->type == XML_NAMESPACE_DECL))
3144 return(reader->depth + 1);
3145 return(reader->depth + 2);
3146 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003147 return(reader->depth);
3148}
3149
3150/**
3151 * xmlTextReaderHasAttributes:
3152 * @reader: the xmlTextReaderPtr used
3153 *
3154 * Whether the node has attributes.
3155 *
3156 * Returns 1 if true, 0 if false, and -1 in case or error
3157 */
3158int
3159xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003160 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003161 if (reader == NULL)
3162 return(-1);
3163 if (reader->node == NULL)
3164 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003165 if (reader->curnode != NULL)
3166 node = reader->curnode;
3167 else
3168 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003169
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003170 if ((node->type == XML_ELEMENT_NODE) &&
3171 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003172 return(1);
3173 /* TODO: handle the xmlDecl */
3174 return(0);
3175}
3176
3177/**
3178 * xmlTextReaderHasValue:
3179 * @reader: the xmlTextReaderPtr used
3180 *
3181 * Whether the node can have a text value.
3182 *
3183 * Returns 1 if true, 0 if false, and -1 in case or error
3184 */
3185int
3186xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003187 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003188 if (reader == NULL)
3189 return(-1);
3190 if (reader->node == NULL)
3191 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003192 if (reader->curnode != NULL)
3193 node = reader->curnode;
3194 else
3195 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003196
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003197 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003198 case XML_ATTRIBUTE_NODE:
3199 case XML_TEXT_NODE:
3200 case XML_CDATA_SECTION_NODE:
3201 case XML_PI_NODE:
3202 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003203 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003204 return(1);
3205 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003206 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003207 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003208 return(0);
3209}
3210
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003211/**
3212 * xmlTextReaderValue:
3213 * @reader: the xmlTextReaderPtr used
3214 *
3215 * Provides the text value of the node if present
3216 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003217 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003218 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003219 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003220xmlChar *
3221xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003222 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003223 if (reader == NULL)
3224 return(NULL);
3225 if (reader->node == NULL)
3226 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003227 if (reader->curnode != NULL)
3228 node = reader->curnode;
3229 else
3230 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003231
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003232 switch (node->type) {
3233 case XML_NAMESPACE_DECL:
3234 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003235 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003236 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003237
3238 if (attr->parent != NULL)
3239 return (xmlNodeListGetString
3240 (attr->parent->doc, attr->children, 1));
3241 else
3242 return (xmlNodeListGetString(NULL, attr->children, 1));
3243 break;
3244 }
3245 case XML_TEXT_NODE:
3246 case XML_CDATA_SECTION_NODE:
3247 case XML_PI_NODE:
3248 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003249 if (node->content != NULL)
3250 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003251 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003252 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003253 }
3254 return(NULL);
3255}
3256
3257/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003258 * xmlTextReaderConstValue:
3259 * @reader: the xmlTextReaderPtr used
3260 *
3261 * Provides the text value of the node if present
3262 *
3263 * Returns the string or NULL if not available. The result will be
3264 * deallocated on the next Read() operation.
3265 */
3266const xmlChar *
3267xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3268 xmlNodePtr node;
3269 if (reader == NULL)
3270 return(NULL);
3271 if (reader->node == NULL)
3272 return(NULL);
3273 if (reader->curnode != NULL)
3274 node = reader->curnode;
3275 else
3276 node = reader->node;
3277
3278 switch (node->type) {
3279 case XML_NAMESPACE_DECL:
3280 return(((xmlNsPtr) node)->href);
3281 case XML_ATTRIBUTE_NODE:{
3282 xmlAttrPtr attr = (xmlAttrPtr) node;
3283
3284 if ((attr->children != NULL) &&
3285 (attr->children->type == XML_TEXT_NODE) &&
3286 (attr->children->next == NULL))
3287 return(attr->children->content);
3288 else {
3289 reader->buffer->use = 0;
3290 xmlNodeBufGetContent(reader->buffer, node);
3291 return(reader->buffer->content);
3292 }
3293 break;
3294 }
3295 case XML_TEXT_NODE:
3296 case XML_CDATA_SECTION_NODE:
3297 case XML_PI_NODE:
3298 case XML_COMMENT_NODE:
3299 return(node->content);
3300 default:
3301 break;
3302 }
3303 return(NULL);
3304}
3305
3306/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003307 * xmlTextReaderIsDefault:
3308 * @reader: the xmlTextReaderPtr used
3309 *
3310 * Whether an Attribute node was generated from the default value
3311 * defined in the DTD or schema.
3312 *
3313 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3314 */
3315int
3316xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3317 if (reader == NULL)
3318 return(-1);
3319 return(0);
3320}
3321
3322/**
3323 * xmlTextReaderQuoteChar:
3324 * @reader: the xmlTextReaderPtr used
3325 *
3326 * The quotation mark character used to enclose the value of an attribute.
3327 *
3328 * Returns " or ' and -1 in case of error
3329 */
3330int
3331xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3332 if (reader == NULL)
3333 return(-1);
3334 /* TODO maybe lookup the attribute value for " first */
3335 return((int) '"');
3336}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003337
3338/**
3339 * xmlTextReaderXmlLang:
3340 * @reader: the xmlTextReaderPtr used
3341 *
3342 * The xml:lang scope within which the node resides.
3343 *
3344 * Returns the xml:lang value or NULL if none exists.
3345 */
3346xmlChar *
3347xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3348 if (reader == NULL)
3349 return(NULL);
3350 if (reader->node == NULL)
3351 return(NULL);
3352 return(xmlNodeGetLang(reader->node));
3353}
3354
Daniel Veillard67df8092002-12-16 22:04:11 +00003355/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003356 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003357 * @reader: the xmlTextReaderPtr used
3358 *
3359 * The xml:lang scope within which the node resides.
3360 *
3361 * Returns the xml:lang value or NULL if none exists.
3362 */
3363const xmlChar *
3364xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3365 xmlChar *tmp;
3366 const xmlChar *ret;
3367
3368 if (reader == NULL)
3369 return(NULL);
3370 if (reader->node == NULL)
3371 return(NULL);
3372 tmp = xmlNodeGetLang(reader->node);
3373 if (tmp == NULL)
3374 return(NULL);
3375 ret = CONSTSTR(tmp);
3376 xmlFree(tmp);
3377 return(ret);
3378}
3379
3380/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003381 * xmlTextReaderConstString:
3382 * @reader: the xmlTextReaderPtr used
3383 * @str: the string to intern.
3384 *
3385 * Get an interned string from the reader, allows for example to
3386 * speedup string name comparisons
3387 *
3388 * Returns an interned copy of the string or NULL in case of error. The
3389 * string will be deallocated with the reader.
3390 */
3391const xmlChar *
3392xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3393 if (reader == NULL)
3394 return(NULL);
3395 return(CONSTSTR(str));
3396}
3397
3398/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003399 * xmlTextReaderNormalization:
3400 * @reader: the xmlTextReaderPtr used
3401 *
3402 * The value indicating whether to normalize white space and attribute values.
3403 * Since attribute value and end of line normalizations are a MUST in the XML
3404 * specification only the value true is accepted. The broken bahaviour of
3405 * accepting out of range character entities like &#0; is of course not
3406 * supported either.
3407 *
3408 * Returns 1 or -1 in case of error.
3409 */
3410int
3411xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3412 if (reader == NULL)
3413 return(-1);
3414 return(1);
3415}
3416
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003417/************************************************************************
3418 * *
3419 * Extensions to the base APIs *
3420 * *
3421 ************************************************************************/
3422
3423/**
3424 * xmlTextReaderSetParserProp:
3425 * @reader: the xmlTextReaderPtr used
3426 * @prop: the xmlParserProperties to set
3427 * @value: usually 0 or 1 to (de)activate it
3428 *
3429 * Change the parser processing behaviour by changing some of its internal
3430 * properties. Note that some properties can only be changed before any
3431 * read has been done.
3432 *
3433 * Returns 0 if the call was successful, or -1 in case of error
3434 */
3435int
3436xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3437 xmlParserProperties p = (xmlParserProperties) prop;
3438 xmlParserCtxtPtr ctxt;
3439
3440 if ((reader == NULL) || (reader->ctxt == NULL))
3441 return(-1);
3442 ctxt = reader->ctxt;
3443
3444 switch (p) {
3445 case XML_PARSER_LOADDTD:
3446 if (value != 0) {
3447 if (ctxt->loadsubset == 0) {
3448 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3449 return(-1);
3450 ctxt->loadsubset = XML_DETECT_IDS;
3451 }
3452 } else {
3453 ctxt->loadsubset = 0;
3454 }
3455 return(0);
3456 case XML_PARSER_DEFAULTATTRS:
3457 if (value != 0) {
3458 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3459 } else {
3460 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3461 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3462 }
3463 return(0);
3464 case XML_PARSER_VALIDATE:
3465 if (value != 0) {
3466 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003467 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003468 } else {
3469 ctxt->validate = 0;
3470 }
3471 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003472 case XML_PARSER_SUBST_ENTITIES:
3473 if (value != 0) {
3474 ctxt->replaceEntities = 1;
3475 } else {
3476 ctxt->replaceEntities = 0;
3477 }
3478 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003479 }
3480 return(-1);
3481}
3482
3483/**
3484 * xmlTextReaderGetParserProp:
3485 * @reader: the xmlTextReaderPtr used
3486 * @prop: the xmlParserProperties to get
3487 *
3488 * Read the parser internal property.
3489 *
3490 * Returns the value, usually 0 or 1, or -1 in case of error.
3491 */
3492int
3493xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3494 xmlParserProperties p = (xmlParserProperties) prop;
3495 xmlParserCtxtPtr ctxt;
3496
3497 if ((reader == NULL) || (reader->ctxt == NULL))
3498 return(-1);
3499 ctxt = reader->ctxt;
3500
3501 switch (p) {
3502 case XML_PARSER_LOADDTD:
3503 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3504 return(1);
3505 return(0);
3506 case XML_PARSER_DEFAULTATTRS:
3507 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3508 return(1);
3509 return(0);
3510 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003511 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003512 case XML_PARSER_SUBST_ENTITIES:
3513 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003514 }
3515 return(-1);
3516}
3517
Daniel Veillarde18fc182002-12-28 22:56:33 +00003518/**
3519 * xmlTextReaderCurrentNode:
3520 * @reader: the xmlTextReaderPtr used
3521 *
3522 * Hacking interface allowing to get the xmlNodePtr correponding to the
3523 * current node being accessed by the xmlTextReader. This is dangerous
3524 * because the underlying node may be destroyed on the next Reads.
3525 *
3526 * Returns the xmlNodePtr or NULL in case of error.
3527 */
3528xmlNodePtr
3529xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3530 if (reader == NULL)
3531 return(NULL);
3532
3533 if (reader->curnode != NULL)
3534 return(reader->curnode);
3535 return(reader->node);
3536}
3537
3538/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003539 * xmlTextReaderPreserve:
3540 * @reader: the xmlTextReaderPtr used
3541 *
3542 *
3543 * current node being accessed by the xmlTextReader. This is dangerous
3544 * because the underlying node may be destroyed on the next Reads.
3545 *
3546 * Returns the xmlNodePtr or NULL in case of error.
3547 */
3548xmlNodePtr
3549xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3550 xmlNodePtr cur, parent;
3551
3552 if (reader == NULL)
3553 return(NULL);
3554
3555 if (reader->curnode != NULL)
3556 cur = reader->curnode;
3557 else
3558 cur = reader->node;
3559 if (cur == NULL)
3560 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003561
3562 if (cur->type != XML_DOCUMENT_NODE) {
3563 cur->extra |= NODE_IS_PRESERVED;
3564 cur->extra |= NODE_IS_SPRESERVED;
3565 }
3566 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003567
3568 parent = cur->parent;;
3569 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003570 if (parent->type == XML_ELEMENT_NODE)
3571 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003572 parent = parent->parent;
3573 }
3574 return(cur);
3575}
3576
Daniel Veillard1e906612003-12-05 14:57:46 +00003577#ifdef LIBXML_PATTERN_ENABLED
3578/**
3579 * xmlTextReaderPreservePattern:
3580 * @reader: the xmlTextReaderPtr used
3581 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003582 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003583 *
3584 * This tells the XML Reader to preserve all nodes matched by the
3585 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3586 * keep an handle on the resulting document once parsing has finished
3587 *
3588 * Returns a positive number in case of success and -1 in case of error
3589 */
3590int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003591xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3592 const xmlChar **namespaces)
3593{
Daniel Veillard1e906612003-12-05 14:57:46 +00003594 xmlPatternPtr comp;
3595
3596 if ((reader == NULL) || (pattern == NULL))
3597 return(-1);
3598
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003599 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003600 if (comp == NULL)
3601 return(-1);
3602
3603 if (reader->patternMax <= 0) {
3604 reader->patternMax = 4;
3605 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3606 sizeof(reader->patternTab[0]));
3607 if (reader->patternTab == NULL) {
3608 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3609 return (-1);
3610 }
3611 }
3612 if (reader->patternNr >= reader->patternMax) {
3613 xmlPatternPtr *tmp;
3614 reader->patternMax *= 2;
3615 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3616 reader->patternMax *
3617 sizeof(reader->patternTab[0]));
3618 if (tmp == NULL) {
3619 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3620 reader->patternMax /= 2;
3621 return (-1);
3622 }
3623 reader->patternTab = tmp;
3624 }
3625 reader->patternTab[reader->patternNr] = comp;
3626 return(reader->patternNr++);
3627}
3628#endif
3629
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003630/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003631 * xmlTextReaderCurrentDoc:
3632 * @reader: the xmlTextReaderPtr used
3633 *
3634 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003635 * current document being accessed by the xmlTextReader.
3636 * NOTE: as a result of this call, the reader will not destroy the
3637 * associated XML document and calling xmlFreeDoc() on the result
3638 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003639 *
3640 * Returns the xmlDocPtr or NULL in case of error.
3641 */
3642xmlDocPtr
3643xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003644 if (reader == NULL)
3645 return(NULL);
3646 if (reader->doc != NULL)
3647 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003648 if ((reader == NULL) || (reader->ctxt == NULL) ||
3649 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003650 return(NULL);
3651
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003652 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00003653 return(reader->ctxt->myDoc);
3654}
3655
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003656#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003657/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003658 * xmlTextReaderRelaxNGSetSchema:
3659 * @reader: the xmlTextReaderPtr used
3660 * @schema: a precompiled RelaxNG schema
3661 *
3662 * Use RelaxNG to validate the document as it is processed.
3663 * Activation is only possible before the first Read().
3664 * if @schema is NULL, then RelaxNG validation is desactivated.
3665 @ The @schema should not be freed until the reader is deallocated
3666 * or its use has been deactivated.
3667 *
3668 * Returns 0 in case the RelaxNG validation could be (des)activated and
3669 * -1 in case of error.
3670 */
3671int
3672xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3673 if (schema == NULL) {
3674 if (reader->rngSchemas != NULL) {
3675 xmlRelaxNGFree(reader->rngSchemas);
3676 reader->rngSchemas = NULL;
3677 }
3678 if (reader->rngValidCtxt != NULL) {
3679 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3680 reader->rngValidCtxt = NULL;
3681 }
3682 return(0);
3683 }
3684 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3685 return(-1);
3686 if (reader->rngSchemas != NULL) {
3687 xmlRelaxNGFree(reader->rngSchemas);
3688 reader->rngSchemas = NULL;
3689 }
3690 if (reader->rngValidCtxt != NULL) {
3691 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3692 reader->rngValidCtxt = NULL;
3693 }
3694 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3695 if (reader->rngValidCtxt == NULL)
3696 return(-1);
3697 if (reader->errorFunc != NULL) {
3698 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3699 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3700 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3701 reader->errorFuncArg);
3702 }
3703 reader->rngValidErrors = 0;
3704 reader->rngFullNode = NULL;
3705 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3706 return(0);
3707}
3708
3709/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003710 * xmlTextReaderRelaxNGValidate:
3711 * @reader: the xmlTextReaderPtr used
3712 * @rng: the path to a RelaxNG schema or NULL
3713 *
3714 * Use RelaxNG to validate the document as it is processed.
3715 * Activation is only possible before the first Read().
3716 * if @rng is NULL, then RelaxNG validation is desactivated.
3717 *
3718 * Returns 0 in case the RelaxNG validation could be (des)activated and
3719 * -1 in case of error.
3720 */
3721int
3722xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3723 xmlRelaxNGParserCtxtPtr ctxt;
3724
3725 if (reader == NULL)
3726 return(-1);
3727
3728 if (rng == NULL) {
3729 if (reader->rngSchemas != NULL) {
3730 xmlRelaxNGFree(reader->rngSchemas);
3731 reader->rngSchemas = NULL;
3732 }
3733 if (reader->rngValidCtxt != NULL) {
3734 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3735 reader->rngValidCtxt = NULL;
3736 }
3737 return(0);
3738 }
3739 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3740 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003741 if (reader->rngSchemas != NULL) {
3742 xmlRelaxNGFree(reader->rngSchemas);
3743 reader->rngSchemas = NULL;
3744 }
3745 if (reader->rngValidCtxt != NULL) {
3746 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3747 reader->rngValidCtxt = NULL;
3748 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003749 ctxt = xmlRelaxNGNewParserCtxt(rng);
3750 if (reader->errorFunc != NULL) {
3751 xmlRelaxNGSetParserErrors(ctxt,
3752 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3753 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3754 reader->errorFuncArg);
3755 }
3756 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3757 xmlRelaxNGFreeParserCtxt(ctxt);
3758 if (reader->rngSchemas == NULL)
3759 return(-1);
3760 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3761 if (reader->rngValidCtxt == NULL)
3762 return(-1);
3763 if (reader->errorFunc != NULL) {
3764 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3765 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3766 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3767 reader->errorFuncArg);
3768 }
3769 reader->rngValidErrors = 0;
3770 reader->rngFullNode = NULL;
3771 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3772 return(0);
3773}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003774#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003775
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003776/************************************************************************
3777 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003778 * Error Handling Extensions *
3779 * *
3780 ************************************************************************/
3781
3782/* helper to build a xmlMalloc'ed string from a format and va_list */
3783static char *
3784xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3785 int size;
3786 int chars;
3787 char *larger;
3788 char *str;
3789
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003790 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003791 if (str == NULL) {
3792 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3793 return NULL;
3794 }
3795
3796 size = 150;
3797
3798 while (1) {
3799 chars = vsnprintf(str, size, msg, ap);
3800 if ((chars > -1) && (chars < size))
3801 break;
3802 if (chars > -1)
3803 size += chars + 1;
3804 else
3805 size += 100;
3806 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3807 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3808 xmlFree(str);
3809 return NULL;
3810 }
3811 str = larger;
3812 }
3813
3814 return str;
3815}
3816
Daniel Veillard417be3a2003-01-20 21:26:34 +00003817/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003818 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003819 * @locator: the xmlTextReaderLocatorPtr used
3820 *
3821 * Obtain the line number for the given locator.
3822 *
3823 * Returns the line number or -1 in case of error.
3824 */
3825int
3826xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3827 /* we know that locator is a xmlParserCtxtPtr */
3828 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3829 int ret = -1;
3830
3831 if (ctx->node != NULL) {
3832 ret = xmlGetLineNo(ctx->node);
3833 }
3834 else {
3835 /* inspired from error.c */
3836 xmlParserInputPtr input;
3837 input = ctx->input;
3838 if ((input->filename == NULL) && (ctx->inputNr > 1))
3839 input = ctx->inputTab[ctx->inputNr - 2];
3840 if (input != NULL) {
3841 ret = input->line;
3842 }
3843 else {
3844 ret = -1;
3845 }
3846 }
3847
3848 return ret;
3849}
3850
3851/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003852 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003853 * @locator: the xmlTextReaderLocatorPtr used
3854 *
3855 * Obtain the base URI for the given locator.
3856 *
3857 * Returns the base URI or NULL in case of error.
3858 */
3859xmlChar *
3860xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3861 /* we know that locator is a xmlParserCtxtPtr */
3862 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3863 xmlChar *ret = NULL;
3864
3865 if (ctx->node != NULL) {
3866 ret = xmlNodeGetBase(NULL,ctx->node);
3867 }
3868 else {
3869 /* inspired from error.c */
3870 xmlParserInputPtr input;
3871 input = ctx->input;
3872 if ((input->filename == NULL) && (ctx->inputNr > 1))
3873 input = ctx->inputTab[ctx->inputNr - 2];
3874 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003875 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003876 }
3877 else {
3878 ret = NULL;
3879 }
3880 }
3881
3882 return ret;
3883}
3884
Daniel Veillard26f70262003-01-16 22:45:08 +00003885static void
William M. Brack899e64a2003-09-26 18:03:42 +00003886xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003887 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3888 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3889
3890 if (str != NULL) {
3891 reader->errorFunc(reader->errorFuncArg,
3892 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003893 severity,
3894 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003895 xmlFree(str);
3896 }
3897}
3898
3899static void
William M. Brack93d004f2004-02-03 00:14:10 +00003900xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3901 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3902 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3903
3904 if (error && reader->sErrorFunc) {
3905 reader->sErrorFunc(reader->errorFuncArg,
3906 (xmlErrorPtr) error);
3907 }
3908}
3909
3910static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003911xmlTextReaderError(void *ctxt, const char *msg, ...) {
3912 va_list ap;
3913
3914 va_start(ap,msg);
3915 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003916 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003917 xmlTextReaderBuildMessage(msg,ap));
3918 va_end(ap);
3919
3920}
3921
3922static void
3923xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3924 va_list ap;
3925
3926 va_start(ap,msg);
3927 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003928 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003929 xmlTextReaderBuildMessage(msg,ap));
3930 va_end(ap);
3931}
3932
3933static void
3934xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3935 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003936 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003937
Daniel Veillard417be3a2003-01-20 21:26:34 +00003938 if ((len > 1) && (msg[len - 2] != ':')) {
3939 /*
3940 * some callbacks only report locator information:
3941 * skip them (mimicking behaviour in error.c)
3942 */
3943 va_start(ap,msg);
3944 xmlTextReaderGenericError(ctxt,
3945 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3946 xmlTextReaderBuildMessage(msg,ap));
3947 va_end(ap);
3948 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003949}
3950
3951static void
3952xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3953 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003954 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003955
Daniel Veillard417be3a2003-01-20 21:26:34 +00003956 if ((len != 0) && (msg[len - 1] != ':')) {
3957 /*
3958 * some callbacks only report locator information:
3959 * skip them (mimicking behaviour in error.c)
3960 */
3961 va_start(ap,msg);
3962 xmlTextReaderGenericError(ctxt,
3963 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3964 xmlTextReaderBuildMessage(msg,ap));
3965 va_end(ap);
3966 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003967}
3968
3969/**
3970 * xmlTextReaderSetErrorHandler:
3971 * @reader: the xmlTextReaderPtr used
3972 * @f: the callback function to call on error and warnings
3973 * @arg: a user argument to pass to the callback function
3974 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003975 * Register a callback function that will be called on error and warnings.
3976 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003977 * If @f is NULL, the default error and warning handlers are restored.
3978 */
3979void
3980xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3981 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003982 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003983 if (f != NULL) {
3984 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003985 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003986 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3987 reader->ctxt->sax->warning = xmlTextReaderWarning;
3988 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3989 reader->errorFunc = f;
3990 reader->errorFuncArg = arg;
3991 }
3992 else {
3993 /* restore defaults */
3994 reader->ctxt->sax->error = xmlParserError;
3995 reader->ctxt->vctxt.error = xmlParserValidityError;
3996 reader->ctxt->sax->warning = xmlParserWarning;
3997 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3998 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00003999 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004000 reader->errorFuncArg = NULL;
4001 }
4002}
4003
Daniel Veillard417be3a2003-01-20 21:26:34 +00004004/**
William M. Brack93d004f2004-02-03 00:14:10 +00004005* xmlTextReaderSetStructuredErrorHandler:
4006 * @reader: the xmlTextReaderPtr used
4007 * @f: the callback function to call on error and warnings
4008 * @arg: a user argument to pass to the callback function
4009 *
4010 * Register a callback function that will be called on error and warnings.
4011 *
4012 * If @f is NULL, the default error and warning handlers are restored.
4013 */
4014void
4015xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4016 xmlStructuredErrorFunc f,
4017 void *arg) {
4018 if (f != NULL) {
4019 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4020 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4021 reader->ctxt->sax->warning = xmlTextReaderWarning;
4022 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4023 reader->sErrorFunc = f;
4024 reader->errorFunc = NULL;
4025 reader->errorFuncArg = arg;
4026 }
4027 else {
4028 /* restore defaults */
4029 reader->ctxt->sax->error = xmlParserError;
4030 reader->ctxt->sax->serror = NULL;
4031 reader->ctxt->vctxt.error = xmlParserValidityError;
4032 reader->ctxt->sax->warning = xmlParserWarning;
4033 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4034 reader->errorFunc = NULL;
4035 reader->sErrorFunc = NULL;
4036 reader->errorFuncArg = NULL;
4037 }
4038}
4039
4040/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004041 * xmlTextReaderIsValid:
4042 * @reader: the xmlTextReaderPtr used
4043 *
4044 * Retrieve the validity status from the parser context
4045 *
4046 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4047 */
4048int
4049xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004050 if (reader == NULL) return(-1);
4051#ifdef LIBXML_SCHEMAS_ENABLED
4052 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4053 return(reader->rngValidErrors == 0);
4054#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004055 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004056 return(reader->ctxt->valid);
4057 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004058}
4059
4060/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004061 * xmlTextReaderGetErrorHandler:
4062 * @reader: the xmlTextReaderPtr used
4063 * @f: the callback function or NULL is no callback has been registered
4064 * @arg: a user argument
4065 *
4066 * Retrieve the error callback function and user argument.
4067 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004068void
4069xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4070 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004071 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004072 *f = reader->errorFunc;
4073 *arg = reader->errorFuncArg;
4074}
4075
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004076
4077/************************************************************************
4078 * *
4079 * New set (2.6.0) of simpler and more flexible APIs *
4080 * *
4081 ************************************************************************/
4082
4083/**
4084 * xmlTextReaderSetup:
4085 * @reader: an XML reader
4086 * @URL: the base URL to use for the document
4087 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004088 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004089 * @reuse: keep the context for reuse
4090 *
4091 * Setup an XML reader with new options
4092 *
4093 * Returns 0 in case of success and -1 in case of error.
4094 */
4095static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004096xmlTextReaderSetup(xmlTextReaderPtr reader,
4097 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004098 const char *encoding, int options)
4099{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004100 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004101 return (-1);
4102
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004103 reader->doc = NULL;
4104 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004105 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004106 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004107 if ((input != NULL) && (reader->input != NULL) &&
4108 (reader->allocs & XML_TEXTREADER_INPUT)) {
4109 xmlFreeParserInputBuffer(reader->input);
4110 reader->input = NULL;
4111 reader->allocs -= XML_TEXTREADER_INPUT;
4112 }
4113 if (input != NULL) {
4114 reader->input = input;
4115 reader->allocs |= XML_TEXTREADER_INPUT;
4116 }
4117 if (reader->buffer == NULL)
4118 reader->buffer = xmlBufferCreateSize(100);
4119 if (reader->buffer == NULL) {
4120 xmlGenericError(xmlGenericErrorContext,
4121 "xmlTextReaderSetup : malloc failed\n");
4122 return (-1);
4123 }
4124 if (reader->sax == NULL)
4125 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4126 if (reader->sax == NULL) {
4127 xmlGenericError(xmlGenericErrorContext,
4128 "xmlTextReaderSetup : malloc failed\n");
4129 return (-1);
4130 }
4131 xmlSAXVersion(reader->sax, 2);
4132 reader->startElement = reader->sax->startElement;
4133 reader->sax->startElement = xmlTextReaderStartElement;
4134 reader->endElement = reader->sax->endElement;
4135 reader->sax->endElement = xmlTextReaderEndElement;
4136#ifdef LIBXML_SAX1_ENABLED
4137 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4138#endif /* LIBXML_SAX1_ENABLED */
4139 reader->startElementNs = reader->sax->startElementNs;
4140 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4141 reader->endElementNs = reader->sax->endElementNs;
4142 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4143#ifdef LIBXML_SAX1_ENABLED
4144 } else {
4145 reader->startElementNs = NULL;
4146 reader->endElementNs = NULL;
4147 }
4148#endif /* LIBXML_SAX1_ENABLED */
4149 reader->characters = reader->sax->characters;
4150 reader->sax->characters = xmlTextReaderCharacters;
4151 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4152 reader->cdataBlock = reader->sax->cdataBlock;
4153 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4154
4155 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4156 reader->node = NULL;
4157 reader->curnode = NULL;
4158 if (input != NULL) {
4159 if (reader->input->buffer->use < 4) {
4160 xmlParserInputBufferRead(input, 4);
4161 }
4162 if (reader->ctxt == NULL) {
4163 if (reader->input->buffer->use >= 4) {
4164 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4165 (const char *) reader->input->buffer->content, 4, URL);
4166 reader->base = 0;
4167 reader->cur = 4;
4168 } else {
4169 reader->ctxt =
4170 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4171 reader->base = 0;
4172 reader->cur = 0;
4173 }
4174 } else {
4175 xmlParserInputPtr inputStream;
4176 xmlParserInputBufferPtr buf;
4177 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4178
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004179 xmlCtxtReset(reader->ctxt);
4180 buf = xmlAllocParserInputBuffer(enc);
4181 if (buf == NULL) return(-1);
4182 inputStream = xmlNewInputStream(reader->ctxt);
4183 if (inputStream == NULL) {
4184 xmlFreeParserInputBuffer(buf);
4185 return(-1);
4186 }
4187
4188 if (URL == NULL)
4189 inputStream->filename = NULL;
4190 else
4191 inputStream->filename = (char *)
4192 xmlCanonicPath((const xmlChar *) URL);
4193 inputStream->buf = buf;
4194 inputStream->base = inputStream->buf->buffer->content;
4195 inputStream->cur = inputStream->buf->buffer->content;
4196 inputStream->end =
4197 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4198
4199 inputPush(reader->ctxt, inputStream);
4200 reader->cur = 0;
4201 }
4202 if (reader->ctxt == NULL) {
4203 xmlGenericError(xmlGenericErrorContext,
4204 "xmlTextReaderSetup : malloc failed\n");
4205 return (-1);
4206 }
4207 }
4208 if (reader->dict != NULL) {
4209 if (reader->ctxt->dict != NULL) {
4210 if (reader->dict != reader->ctxt->dict) {
4211 xmlDictFree(reader->dict);
4212 reader->dict = reader->ctxt->dict;
4213 }
4214 } else {
4215 reader->ctxt->dict = reader->dict;
4216 }
4217 } else {
4218 if (reader->ctxt->dict == NULL)
4219 reader->ctxt->dict = xmlDictCreate();
4220 reader->dict = reader->ctxt->dict;
4221 }
4222 reader->ctxt->_private = reader;
4223 reader->ctxt->linenumbers = 1;
4224 reader->ctxt->dictNames = 1;
4225 /*
4226 * use the parser dictionnary to allocate all elements and attributes names
4227 */
4228 reader->ctxt->docdict = 1;
4229
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004230#ifdef LIBXML_XINCLUDE_ENABLED
4231 if (reader->xincctxt != NULL) {
4232 xmlXIncludeFreeContext(reader->xincctxt);
4233 reader->xincctxt = NULL;
4234 }
4235 if (options & XML_PARSE_XINCLUDE) {
4236 reader->xinclude = 1;
4237 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4238 options -= XML_PARSE_XINCLUDE;
4239 } else
4240 reader->xinclude = 0;
4241 reader->in_xinclude = 0;
4242#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004243#ifdef LIBXML_PATTERN_ENABLED
4244 if (reader->patternTab == NULL) {
4245 reader->patternNr = 0;
4246 reader->patternMax = 0;
4247 }
4248 while (reader->patternNr > 0) {
4249 reader->patternNr--;
4250 if (reader->patternTab[reader->patternNr] != NULL) {
4251 xmlFreePattern(reader->patternTab[reader->patternNr]);
4252 reader->patternTab[reader->patternNr] = NULL;
4253 }
4254 }
4255#endif
4256
Daniel Veillardc36965d2003-12-02 10:28:48 +00004257 if (options & XML_PARSE_DTDVALID)
4258 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4259
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004260 xmlCtxtUseOptions(reader->ctxt, options);
4261 if (encoding != NULL) {
4262 xmlCharEncodingHandlerPtr hdlr;
4263
4264 hdlr = xmlFindCharEncodingHandler(encoding);
4265 if (hdlr != NULL)
4266 xmlSwitchToEncoding(reader->ctxt, hdlr);
4267 }
4268 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4269 (reader->ctxt->input->filename == NULL))
4270 reader->ctxt->input->filename = (char *)
4271 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004272
4273 reader->doc = NULL;
4274
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004275 return (0);
4276}
4277
4278/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004279 * xmlReaderWalker:
4280 * @doc: a preparsed document
4281 *
4282 * Create an xmltextReader for a preparsed document.
4283 *
4284 * Returns the new reader or NULL in case of error.
4285 */
4286xmlTextReaderPtr
4287xmlReaderWalker(xmlDocPtr doc)
4288{
4289 xmlTextReaderPtr ret;
4290
4291 if (doc == NULL)
4292 return(NULL);
4293
4294 ret = xmlMalloc(sizeof(xmlTextReader));
4295 if (ret == NULL) {
4296 xmlGenericError(xmlGenericErrorContext,
4297 "xmlNewTextReader : malloc failed\n");
4298 return(NULL);
4299 }
4300 memset(ret, 0, sizeof(xmlTextReader));
4301 ret->entNr = 0;
4302 ret->input = NULL;
4303 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4304 ret->node = NULL;
4305 ret->curnode = NULL;
4306 ret->base = 0;
4307 ret->cur = 0;
4308 ret->allocs = XML_TEXTREADER_CTXT;
4309 ret->doc = doc;
4310 ret->state = XML_TEXTREADER_START;
4311 ret->dict = xmlDictCreate();
4312 return(ret);
4313}
4314
4315/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004316 * xmlReaderForDoc:
4317 * @cur: a pointer to a zero terminated string
4318 * @URL: the base URL to use for the document
4319 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004320 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004321 *
4322 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004323 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004324 *
4325 * Returns the new reader or NULL in case of error.
4326 */
4327xmlTextReaderPtr
4328xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4329 int options)
4330{
4331 int len;
4332
4333 if (cur == NULL)
4334 return (NULL);
4335 len = xmlStrlen(cur);
4336
4337 return (xmlReaderForMemory
4338 ((const char *) cur, len, URL, encoding, options));
4339}
4340
4341/**
4342 * xmlReaderForFile:
4343 * @filename: a file or URL
4344 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004345 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004346 *
4347 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004348 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004349 *
4350 * Returns the new reader or NULL in case of error.
4351 */
4352xmlTextReaderPtr
4353xmlReaderForFile(const char *filename, const char *encoding, int options)
4354{
4355 xmlTextReaderPtr reader;
4356
4357 reader = xmlNewTextReaderFilename(filename);
4358 if (reader == NULL)
4359 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004360 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004361 return (reader);
4362}
4363
4364/**
4365 * xmlReaderForMemory:
4366 * @buffer: a pointer to a char array
4367 * @size: the size of the array
4368 * @URL: the base URL to use for the document
4369 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004370 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004371 *
4372 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004373 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004374 *
4375 * Returns the new reader or NULL in case of error.
4376 */
4377xmlTextReaderPtr
4378xmlReaderForMemory(const char *buffer, int size, const char *URL,
4379 const char *encoding, int options)
4380{
4381 xmlTextReaderPtr reader;
4382 xmlParserInputBufferPtr buf;
4383
Daniel Veillard21924522004-02-19 16:37:07 +00004384 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004385 XML_CHAR_ENCODING_NONE);
4386 if (buf == NULL) {
4387 return (NULL);
4388 }
4389 reader = xmlNewTextReader(buf, URL);
4390 if (reader == NULL) {
4391 xmlFreeParserInputBuffer(buf);
4392 return (NULL);
4393 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004394 reader->allocs |= XML_TEXTREADER_INPUT;
4395 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004396 return (reader);
4397}
4398
4399/**
4400 * xmlReaderForFd:
4401 * @fd: an open file descriptor
4402 * @URL: the base URL to use for the document
4403 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004404 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004405 *
4406 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004407 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004408 * NOTE that the file descriptor will not be closed when the
4409 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004410 *
4411 * Returns the new reader or NULL in case of error.
4412 */
4413xmlTextReaderPtr
4414xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4415{
4416 xmlTextReaderPtr reader;
4417 xmlParserInputBufferPtr input;
4418
4419 if (fd < 0)
4420 return (NULL);
4421
4422 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4423 if (input == NULL)
4424 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004425 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004426 reader = xmlNewTextReader(input, URL);
4427 if (reader == NULL) {
4428 xmlFreeParserInputBuffer(input);
4429 return (NULL);
4430 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004431 reader->allocs |= XML_TEXTREADER_INPUT;
4432 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004433 return (reader);
4434}
4435
4436/**
4437 * xmlReaderForIO:
4438 * @ioread: an I/O read function
4439 * @ioclose: an I/O close function
4440 * @ioctx: an I/O handler
4441 * @URL: the base URL to use for the document
4442 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004443 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004444 *
4445 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004446 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004447 *
4448 * Returns the new reader or NULL in case of error.
4449 */
4450xmlTextReaderPtr
4451xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4452 void *ioctx, const char *URL, const char *encoding,
4453 int options)
4454{
4455 xmlTextReaderPtr reader;
4456 xmlParserInputBufferPtr input;
4457
4458 if (ioread == NULL)
4459 return (NULL);
4460
4461 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4462 XML_CHAR_ENCODING_NONE);
4463 if (input == NULL)
4464 return (NULL);
4465 reader = xmlNewTextReader(input, URL);
4466 if (reader == NULL) {
4467 xmlFreeParserInputBuffer(input);
4468 return (NULL);
4469 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004470 reader->allocs |= XML_TEXTREADER_INPUT;
4471 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004472 return (reader);
4473}
4474
4475/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004476 * xmlReaderNewWalker:
4477 * @reader: an XML reader
4478 * @doc: a preparsed document
4479 *
4480 * Setup an xmltextReader to parse a preparsed XML document.
4481 * This reuses the existing @reader xmlTextReader.
4482 *
4483 * Returns 0 in case of success and -1 in case of error
4484 */
4485int
4486xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4487{
4488 if (doc == NULL)
4489 return (-1);
4490 if (reader == NULL)
4491 return (-1);
4492
4493 if (reader->ctxt != NULL) {
4494 xmlCtxtReset(reader->ctxt);
4495 }
4496
4497 reader->entNr = 0;
4498 reader->input = NULL;
4499 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4500 reader->node = NULL;
4501 reader->curnode = NULL;
4502 reader->base = 0;
4503 reader->cur = 0;
4504 reader->allocs = XML_TEXTREADER_CTXT;
4505 reader->doc = doc;
4506 reader->state = XML_TEXTREADER_START;
4507 if (reader->dict == NULL) {
4508 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4509 reader->dict = reader->ctxt->dict;
4510 else
4511 reader->dict = xmlDictCreate();
4512 }
4513 return(0);
4514}
4515
4516/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004517 * xmlReaderNewDoc:
4518 * @reader: an XML reader
4519 * @cur: a pointer to a zero terminated string
4520 * @URL: the base URL to use for the document
4521 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004522 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004523 *
4524 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004525 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004526 * This reuses the existing @reader xmlTextReader.
4527 *
4528 * Returns 0 in case of success and -1 in case of error
4529 */
4530int
4531xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4532 const char *URL, const char *encoding, int options)
4533{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004534
4535 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004536
4537 if (cur == NULL)
4538 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004539 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004540 return (-1);
4541
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004542 len = xmlStrlen(cur);
4543 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4544 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004545}
4546
4547/**
4548 * xmlReaderNewFile:
4549 * @reader: an XML reader
4550 * @filename: a file or URL
4551 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004552 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004553 *
4554 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004555 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004556 * This reuses the existing @reader xmlTextReader.
4557 *
4558 * Returns 0 in case of success and -1 in case of error
4559 */
4560int
4561xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4562 const char *encoding, int options)
4563{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004564 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004565
4566 if (filename == NULL)
4567 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004568 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004569 return (-1);
4570
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004571 input =
4572 xmlParserInputBufferCreateFilename(filename,
4573 XML_CHAR_ENCODING_NONE);
4574 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004575 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004576 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004577}
4578
4579/**
4580 * xmlReaderNewMemory:
4581 * @reader: an XML reader
4582 * @buffer: a pointer to a char array
4583 * @size: the size of the array
4584 * @URL: the base URL to use for the document
4585 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004586 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004587 *
4588 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004589 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004590 * This reuses the existing @reader xmlTextReader.
4591 *
4592 * Returns 0 in case of success and -1 in case of error
4593 */
4594int
4595xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4596 const char *URL, const char *encoding, int options)
4597{
4598 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004599
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004600 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004601 return (-1);
4602 if (buffer == NULL)
4603 return (-1);
4604
Daniel Veillard21924522004-02-19 16:37:07 +00004605 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004606 XML_CHAR_ENCODING_NONE);
4607 if (input == NULL) {
4608 return (-1);
4609 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004610 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004611}
4612
4613/**
4614 * xmlReaderNewFd:
4615 * @reader: an XML reader
4616 * @fd: an open file descriptor
4617 * @URL: the base URL to use for the document
4618 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004619 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004620 *
4621 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004622 * NOTE that the file descriptor will not be closed when the
4623 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004624 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004625 * This reuses the existing @reader xmlTextReader.
4626 *
4627 * Returns 0 in case of success and -1 in case of error
4628 */
4629int
4630xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4631 const char *URL, const char *encoding, int options)
4632{
4633 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004634
4635 if (fd < 0)
4636 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004637 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004638 return (-1);
4639
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004640 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4641 if (input == NULL)
4642 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004643 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004644 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004645}
4646
4647/**
4648 * xmlReaderNewIO:
4649 * @reader: an XML reader
4650 * @ioread: an I/O read function
4651 * @ioclose: an I/O close function
4652 * @ioctx: an I/O handler
4653 * @URL: the base URL to use for the document
4654 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004655 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004656 *
4657 * Setup an xmltextReader to parse an XML document from I/O functions
4658 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004659 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004660 * This reuses the existing @reader xmlTextReader.
4661 *
4662 * Returns 0 in case of success and -1 in case of error
4663 */
4664int
4665xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4666 xmlInputCloseCallback ioclose, void *ioctx,
4667 const char *URL, const char *encoding, int options)
4668{
4669 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004670
4671 if (ioread == NULL)
4672 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004673 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004674 return (-1);
4675
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004676 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4677 XML_CHAR_ENCODING_NONE);
4678 if (input == NULL)
4679 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004680 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004681}
Daniel Veillard26f70262003-01-16 22:45:08 +00004682/************************************************************************
4683 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004684 * Utilities *
4685 * *
4686 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004687#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004688/**
4689 * xmlBase64Decode:
4690 * @in: the input buffer
4691 * @inlen: the size of the input (in), the size read from it (out)
4692 * @to: the output buffer
4693 * @tolen: the size of the output (in), the size written to (out)
4694 *
4695 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004696 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004697 *
4698 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4699 * 2 if there wasn't enough space on the output or -1 in case of error.
4700 */
4701static int
4702xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4703 unsigned char *to, unsigned long *tolen) {
4704 unsigned long incur; /* current index in in[] */
4705 unsigned long inblk; /* last block index in in[] */
4706 unsigned long outcur; /* current index in out[] */
4707 unsigned long inmax; /* size of in[] */
4708 unsigned long outmax; /* size of out[] */
4709 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004710 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004711 int nbintmp; /* number of byte in intmp[] */
4712 int is_ignore; /* cur should be ignored */
4713 int is_end = 0; /* the end of the base64 was found */
4714 int retval = 1;
4715 int i;
4716
4717 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4718 return(-1);
4719
4720 incur = 0;
4721 inblk = 0;
4722 outcur = 0;
4723 inmax = *inlen;
4724 outmax = *tolen;
4725 nbintmp = 0;
4726
4727 while (1) {
4728 if (incur >= inmax)
4729 break;
4730 cur = in[incur++];
4731 is_ignore = 0;
4732 if ((cur >= 'A') && (cur <= 'Z'))
4733 cur = cur - 'A';
4734 else if ((cur >= 'a') && (cur <= 'z'))
4735 cur = cur - 'a' + 26;
4736 else if ((cur >= '0') && (cur <= '9'))
4737 cur = cur - '0' + 52;
4738 else if (cur == '+')
4739 cur = 62;
4740 else if (cur == '/')
4741 cur = 63;
4742 else if (cur == '.')
4743 cur = 0;
4744 else if (cur == '=') /*no op , end of the base64 stream */
4745 is_end = 1;
4746 else {
4747 is_ignore = 1;
4748 if (nbintmp == 0)
4749 inblk = incur;
4750 }
4751
4752 if (!is_ignore) {
4753 int nbouttmp = 3;
4754 int is_break = 0;
4755
4756 if (is_end) {
4757 if (nbintmp == 0)
4758 break;
4759 if ((nbintmp == 1) || (nbintmp == 2))
4760 nbouttmp = 1;
4761 else
4762 nbouttmp = 2;
4763 nbintmp = 3;
4764 is_break = 1;
4765 }
4766 intmp[nbintmp++] = cur;
4767 /*
4768 * if intmp is full, push the 4byte sequence as a 3 byte
4769 * sequence out
4770 */
4771 if (nbintmp == 4) {
4772 nbintmp = 0;
4773 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4774 outtmp[1] =
4775 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4776 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4777 if (outcur + 3 >= outmax) {
4778 retval = 2;
4779 break;
4780 }
4781
4782 for (i = 0; i < nbouttmp; i++)
4783 to[outcur++] = outtmp[i];
4784 inblk = incur;
4785 }
4786
4787 if (is_break) {
4788 retval = 0;
4789 break;
4790 }
4791 }
4792 }
4793
4794 *tolen = outcur;
4795 *inlen = inblk;
4796 return (retval);
4797}
4798
4799/*
4800 * Test routine for the xmlBase64Decode function
4801 */
4802#if 0
4803int main(int argc, char **argv) {
4804 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4805 char output[100];
4806 char output2[100];
4807 char output3[100];
4808 unsigned long inlen = strlen(input);
4809 unsigned long outlen = 100;
4810 int ret;
4811 unsigned long cons, tmp, tmp2, prod;
4812
4813 /*
4814 * Direct
4815 */
4816 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4817
4818 output[outlen] = 0;
4819 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4820
4821 /*
4822 * output chunking
4823 */
4824 cons = 0;
4825 prod = 0;
4826 while (cons < inlen) {
4827 tmp = 5;
4828 tmp2 = inlen - cons;
4829
4830 printf("%ld %ld\n", cons, prod);
4831 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4832 cons += tmp2;
4833 prod += tmp;
4834 printf("%ld %ld\n", cons, prod);
4835 }
4836 output2[outlen] = 0;
4837 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4838
4839 /*
4840 * input chunking
4841 */
4842 cons = 0;
4843 prod = 0;
4844 while (cons < inlen) {
4845 tmp = 100 - prod;
4846 tmp2 = inlen - cons;
4847 if (tmp2 > 5)
4848 tmp2 = 5;
4849
4850 printf("%ld %ld\n", cons, prod);
4851 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4852 cons += tmp2;
4853 prod += tmp;
4854 printf("%ld %ld\n", cons, prod);
4855 }
4856 output3[outlen] = 0;
4857 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4858 return(0);
4859
4860}
4861#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004862#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004863#endif /* LIBXML_READER_ENABLED */