blob: e78b2865c3579e3eddffac864189b4b582336453 [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);
499 xmlFree(cur);
500}
501
502/************************************************************************
503 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000504 * The reader core parser *
505 * *
506 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000507#ifdef DEBUG_READER
508static void
509xmlTextReaderDebug(xmlTextReaderPtr reader) {
510 if ((reader == NULL) || (reader->ctxt == NULL)) {
511 fprintf(stderr, "xmlTextReader NULL\n");
512 return;
513 }
514 fprintf(stderr, "xmlTextReader: state %d depth %d ",
515 reader->state, reader->depth);
516 if (reader->node == NULL) {
517 fprintf(stderr, "node = NULL\n");
518 } else {
519 fprintf(stderr, "node %s\n", reader->node->name);
520 }
521 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
522 reader->base, reader->cur, reader->ctxt->nodeNr);
523 if (reader->input->buffer == NULL) {
524 fprintf(stderr, "buffer is NULL\n");
525 } else {
526#ifdef LIBXML_DEBUG_ENABLED
527 xmlDebugDumpString(stderr,
528 &reader->input->buffer->content[reader->cur]);
529#endif
530 fprintf(stderr, "\n");
531 }
532}
533#endif
534
535/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000536 * xmlTextReaderEntPush:
537 * @reader: the xmlTextReaderPtr used
538 * @value: the entity reference node
539 *
540 * Pushes a new entity reference node on top of the entities stack
541 *
542 * Returns 0 in case of error, the index in the stack otherwise
543 */
544static int
545xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
546{
547 if (reader->entMax <= 0) {
548 reader->entMax = 10;
549 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
550 sizeof(reader->entTab[0]));
551 if (reader->entTab == NULL) {
552 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
553 return (0);
554 }
555 }
556 if (reader->entNr >= reader->entMax) {
557 reader->entMax *= 2;
558 reader->entTab =
559 (xmlNodePtr *) xmlRealloc(reader->entTab,
560 reader->entMax *
561 sizeof(reader->entTab[0]));
562 if (reader->entTab == NULL) {
563 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
564 return (0);
565 }
566 }
567 reader->entTab[reader->entNr] = value;
568 reader->ent = value;
569 return (reader->entNr++);
570}
571
572/**
573 * xmlTextReaderEntPop:
574 * @reader: the xmlTextReaderPtr used
575 *
576 * Pops the top element entity from the entities stack
577 *
578 * Returns the entity just removed
579 */
580static xmlNodePtr
581xmlTextReaderEntPop(xmlTextReaderPtr reader)
582{
583 xmlNodePtr ret;
584
585 if (reader->entNr <= 0)
586 return (0);
587 reader->entNr--;
588 if (reader->entNr > 0)
589 reader->ent = reader->entTab[reader->entNr - 1];
590 else
591 reader->ent = NULL;
592 ret = reader->entTab[reader->entNr];
593 reader->entTab[reader->entNr] = 0;
594 return (ret);
595}
596
597/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000598 * xmlTextReaderStartElement:
599 * @ctx: the user data (XML parser context)
600 * @fullname: The element name, including namespace prefix
601 * @atts: An array of name/value attributes pairs, NULL terminated
602 *
603 * called when an opening tag has been processed.
604 */
605static void
606xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
607 const xmlChar **atts) {
608 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
609 xmlTextReaderPtr reader = ctxt->_private;
610
611#ifdef DEBUG_CALLBACKS
612 printf("xmlTextReaderStartElement(%s)\n", fullname);
613#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000614 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000615 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000616 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
617 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
618 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000619 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000620 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000621 if (reader != NULL)
622 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000623}
624
625/**
626 * xmlTextReaderEndElement:
627 * @ctx: the user data (XML parser context)
628 * @fullname: The element name, including namespace prefix
629 *
630 * called when an ending tag has been processed.
631 */
632static void
633xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
634 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
635 xmlTextReaderPtr reader = ctxt->_private;
636
637#ifdef DEBUG_CALLBACKS
638 printf("xmlTextReaderEndElement(%s)\n", fullname);
639#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000640 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000641 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000642 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000643}
644
645/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000646 * xmlTextReaderStartElementNs:
647 * @ctx: the user data (XML parser context)
648 * @localname: the local name of the element
649 * @prefix: the element namespace prefix if available
650 * @URI: the element namespace name if available
651 * @nb_namespaces: number of namespace definitions on that node
652 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
653 * @nb_attributes: the number of attributes on that node
654 * nb_defaulted: the number of defaulted attributes.
655 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
656 * attribute values.
657 *
658 * called when an opening tag has been processed.
659 */
660static void
661xmlTextReaderStartElementNs(void *ctx,
662 const xmlChar *localname,
663 const xmlChar *prefix,
664 const xmlChar *URI,
665 int nb_namespaces,
666 const xmlChar **namespaces,
667 int nb_attributes,
668 int nb_defaulted,
669 const xmlChar **attributes)
670{
671 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
672 xmlTextReaderPtr reader = ctxt->_private;
673
674#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000675 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000676#endif
677 if ((reader != NULL) && (reader->startElementNs != NULL)) {
678 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
679 namespaces, nb_attributes, nb_defaulted,
680 attributes);
681 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
682 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
683 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000684 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000685 }
686 if (reader != NULL)
687 reader->state = XML_TEXTREADER_ELEMENT;
688}
689
690/**
691 * xmlTextReaderEndElementNs:
692 * @ctx: the user data (XML parser context)
693 * @localname: the local name of the element
694 * @prefix: the element namespace prefix if available
695 * @URI: the element namespace name if available
696 *
697 * called when an ending tag has been processed.
698 */
699static void
700xmlTextReaderEndElementNs(void *ctx,
701 const xmlChar * localname,
702 const xmlChar * prefix,
703 const xmlChar * URI)
704{
705 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
706 xmlTextReaderPtr reader = ctxt->_private;
707
708#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000709 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000710#endif
711 if ((reader != NULL) && (reader->endElementNs != NULL)) {
712 reader->endElementNs(ctx, localname, prefix, URI);
713 }
714}
715
716
717/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000718 * xmlTextReaderCharacters:
719 * @ctx: the user data (XML parser context)
720 * @ch: a xmlChar string
721 * @len: the number of xmlChar
722 *
723 * receiving some chars from the parser.
724 */
725static void
726xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
727{
728 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
729 xmlTextReaderPtr reader = ctxt->_private;
730
731#ifdef DEBUG_CALLBACKS
732 printf("xmlTextReaderCharacters()\n");
733#endif
734 if ((reader != NULL) && (reader->characters != NULL)) {
735 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000736 }
737}
738
739/**
740 * xmlTextReaderCDataBlock:
741 * @ctx: the user data (XML parser context)
742 * @value: The pcdata content
743 * @len: the block length
744 *
745 * called when a pcdata block has been parsed
746 */
747static void
748xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
749{
750 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
751 xmlTextReaderPtr reader = ctxt->_private;
752
753#ifdef DEBUG_CALLBACKS
754 printf("xmlTextReaderCDataBlock()\n");
755#endif
756 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
757 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000758 }
759}
760
761/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000762 * xmlTextReaderPushData:
763 * @reader: the xmlTextReaderPtr used
764 *
765 * Push data down the progressive parser until a significant callback
766 * got raised.
767 *
768 * Returns -1 in case of failure, 0 otherwise
769 */
770static int
771xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000772 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000773 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000774 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000775
776 if ((reader->input == NULL) || (reader->input->buffer == NULL))
777 return(-1);
778
Daniel Veillardea7751d2002-12-20 00:16:24 +0000779 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000780 reader->state = XML_TEXTREADER_NONE;
781 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000782
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000783 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000784 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000785 /*
786 * Refill the buffer unless we are at the end of the stream
787 */
788 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
789 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000790 if ((val == 0) &&
791 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
792 if (inbuf->use == reader->cur) {
793 reader->mode = XML_TEXTREADER_MODE_EOF;
794 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000795 }
796 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000797 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000798 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000799 if ((oldstate != XML_TEXTREADER_START) ||
800 (reader->ctxt->myDoc != NULL))
801 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000802 } else if (val == 0) {
803 /* mark the end of the stream and process the remains */
804 reader->mode = XML_TEXTREADER_MODE_EOF;
805 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000806 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000807
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000808 } else
809 break;
810 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000811 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000812 * parse by block of CHUNK_SIZE bytes, various tests show that
813 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000814 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000815 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000816 val = xmlParseChunk(reader->ctxt,
817 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000818 CHUNK_SIZE, 0);
819 reader->cur += CHUNK_SIZE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000820 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000822 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000823 s = inbuf->use - reader->cur;
824 val = xmlParseChunk(reader->ctxt,
825 (const char *) &inbuf->content[reader->cur],
826 s, 0);
827 reader->cur += s;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000828 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000829 return(-1);
830 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000831 }
832 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000833
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000834 /*
835 * Discard the consumed input when needed and possible
836 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000837 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000838 if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
839 if ((reader->cur >= 4096) &&
840 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
841 val = xmlBufferShrink(inbuf, reader->cur);
842 if (val >= 0) {
843 reader->cur -= val;
844 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000845 }
846 }
847 }
848
849 /*
850 * At the end of the stream signal that the work is done to the Push
851 * parser.
852 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000853 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000854 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000855 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000856 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000857 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000858 s, 1);
859 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000860 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000861 if ((val != 0) && (reader->ctxt->wellFormed == 0))
862 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000863 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000864 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000865 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000866 return(0);
867}
868
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000869#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000870/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000871 * xmlTextReaderValidatePush:
872 * @reader: the xmlTextReaderPtr used
873 *
874 * Push the current node for validation
875 */
876static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000877xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000878 xmlNodePtr node = reader->node;
879
Daniel Veillardf4e55762003-04-15 23:32:22 +0000880 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
881 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
882 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
883 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
884 reader->ctxt->myDoc, node, node->name);
885 } else {
886 /* TODO use the BuildQName interface */
887 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000888
Daniel Veillardf4e55762003-04-15 23:32:22 +0000889 qname = xmlStrdup(node->ns->prefix);
890 qname = xmlStrcat(qname, BAD_CAST ":");
891 qname = xmlStrcat(qname, node->name);
892 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
893 reader->ctxt->myDoc, node, qname);
894 if (qname != NULL)
895 xmlFree(qname);
896 }
897#ifdef LIBXML_SCHEMAS_ENABLED
898 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
899 (reader->rngValidCtxt != NULL)) {
900 int ret;
901
902 if (reader->rngFullNode != NULL) return;
903 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
904 reader->ctxt->myDoc,
905 node);
906 if (ret == 0) {
907 /*
908 * this element requires a full tree
909 */
910 node = xmlTextReaderExpand(reader);
911 if (node == NULL) {
912printf("Expand failed !\n");
913 ret = -1;
914 } else {
915 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
916 reader->ctxt->myDoc,
917 node);
918 reader->rngFullNode = node;
919 }
920 }
921 if (ret != 1)
922 reader->rngValidErrors++;
923#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000924 }
925}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000926
927/**
928 * xmlTextReaderValidateCData:
929 * @reader: the xmlTextReaderPtr used
930 * @data: pointer to the CData
931 * @len: lenght of the CData block in bytes.
932 *
933 * Push some CData for validation
934 */
935static void
936xmlTextReaderValidateCData(xmlTextReaderPtr reader,
937 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000938 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
939 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
940 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
941 data, len);
942#ifdef LIBXML_SCHEMAS_ENABLED
943 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
944 (reader->rngValidCtxt != NULL)) {
945 int ret;
946
947 if (reader->rngFullNode != NULL) return;
948 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
949 if (ret != 1)
950 reader->rngValidErrors++;
951#endif
952 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000953}
954
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000955/**
956 * xmlTextReaderValidatePop:
957 * @reader: the xmlTextReaderPtr used
958 *
959 * Pop the current node from validation
960 */
961static void
962xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
963 xmlNodePtr node = reader->node;
964
Daniel Veillardf4e55762003-04-15 23:32:22 +0000965 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
966 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
967 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
968 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
969 reader->ctxt->myDoc, node, node->name);
970 } else {
971 /* TODO use the BuildQName interface */
972 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000973
Daniel Veillardf4e55762003-04-15 23:32:22 +0000974 qname = xmlStrdup(node->ns->prefix);
975 qname = xmlStrcat(qname, BAD_CAST ":");
976 qname = xmlStrcat(qname, node->name);
977 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
978 reader->ctxt->myDoc, node, qname);
979 if (qname != NULL)
980 xmlFree(qname);
981 }
982#ifdef LIBXML_SCHEMAS_ENABLED
983 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
984 (reader->rngValidCtxt != NULL)) {
985 int ret;
986
987 if (reader->rngFullNode != NULL) {
988 if (node == reader->rngFullNode)
989 reader->rngFullNode = NULL;
990 return;
991 }
992 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
993 reader->ctxt->myDoc,
994 node);
995 if (ret != 1)
996 reader->rngValidErrors++;
997#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000998 }
999}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001000
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001001/**
1002 * xmlTextReaderValidateEntity:
1003 * @reader: the xmlTextReaderPtr used
1004 *
1005 * Handle the validation when an entity reference is encountered and
1006 * entity substitution is not activated. As a result the parser interface
1007 * must walk through the entity and do the validation calls
1008 */
1009static void
1010xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1011 xmlNodePtr oldnode = reader->node;
1012 xmlNodePtr node = reader->node;
1013 xmlParserCtxtPtr ctxt = reader->ctxt;
1014
1015 do {
1016 if (node->type == XML_ENTITY_REF_NODE) {
1017 /*
1018 * Case where the underlying tree is not availble, lookup the entity
1019 * and walk it.
1020 */
1021 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1022 (ctxt->sax->getEntity != NULL)) {
1023 node->children = (xmlNodePtr)
1024 ctxt->sax->getEntity(ctxt, node->name);
1025 }
1026
1027 if ((node->children != NULL) &&
1028 (node->children->type == XML_ENTITY_DECL) &&
1029 (node->children->children != NULL)) {
1030 xmlTextReaderEntPush(reader, node);
1031 node = node->children->children;
1032 continue;
1033 } else {
1034 /*
1035 * The error has probably be raised already.
1036 */
1037 if (node == oldnode)
1038 break;
1039 node = node->next;
1040 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001041#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001042 } else if (node->type == XML_ELEMENT_NODE) {
1043 reader->node = node;
1044 xmlTextReaderValidatePush(reader);
1045 } else if ((node->type == XML_TEXT_NODE) ||
1046 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001047 xmlTextReaderValidateCData(reader, node->content,
1048 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001049#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001050 }
1051
1052 /*
1053 * go to next node
1054 */
1055 if (node->children != NULL) {
1056 node = node->children;
1057 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001058 } else if (node->type == XML_ELEMENT_NODE) {
1059 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001060 }
1061 if (node->next != NULL) {
1062 node = node->next;
1063 continue;
1064 }
1065 do {
1066 node = node->parent;
1067 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001068 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001069 if (reader->entNr == 0) {
1070 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001071 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001072 xmlUnlinkNode(tmp);
1073 xmlTextReaderFreeNode(reader, tmp);
1074 } else
1075 break;
1076 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001077 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001078 reader->node = node;
1079 xmlTextReaderValidatePop(reader);
1080 }
1081 if ((node->type == XML_ENTITY_DECL) &&
1082 (reader->ent != NULL) && (reader->ent->children == node)) {
1083 node = xmlTextReaderEntPop(reader);
1084 }
1085 if (node == oldnode)
1086 break;
1087 if (node->next != NULL) {
1088 node = node->next;
1089 break;
1090 }
1091 } while ((node != NULL) && (node != oldnode));
1092 } while ((node != NULL) && (node != oldnode));
1093 reader->node = oldnode;
1094}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001095#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001096
1097
1098/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001099 * xmlTextReaderGetSuccessor:
1100 * @cur: the current node
1101 *
1102 * Get the successor of a node if available.
1103 *
1104 * Returns the successor node or NULL
1105 */
1106static xmlNodePtr
1107xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1108 if (cur == NULL) return(NULL) ; /* ERROR */
1109 if (cur->next != NULL) return(cur->next) ;
1110 do {
1111 cur = cur->parent;
1112 if (cur == NULL) return(NULL);
1113 if (cur->next != NULL) return(cur->next);
1114 } while (cur != NULL);
1115 return(cur);
1116}
1117
1118/**
1119 * xmlTextReaderDoExpand:
1120 * @reader: the xmlTextReaderPtr used
1121 *
1122 * Makes sure that the current node is fully read as well as all its
1123 * descendant. It means the full DOM subtree must be available at the
1124 * end of the call.
1125 *
1126 * Returns 1 if the node was expanded successfully, 0 if there is no more
1127 * nodes to read, or -1 in case of error
1128 */
1129static int
1130xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1131 int val;
1132
1133 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1134 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001135 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001136 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1137
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001138 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1139 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001140 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001141 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001142 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1143 return(1);
1144 val = xmlTextReaderPushData(reader);
1145 if (val < 0)
1146 return(-1);
1147 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1148 return(1);
1149}
1150
1151/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001152 * xmlTextReaderRead:
1153 * @reader: the xmlTextReaderPtr used
1154 *
1155 * Moves the position of the current instance to the next node in
1156 * the stream, exposing its properties.
1157 *
1158 * Returns 1 if the node was read successfully, 0 if there is no more
1159 * nodes to read, or -1 in case of error
1160 */
1161int
1162xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001163 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001164 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001165 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001166
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001167
1168 if (reader == NULL)
1169 return(-1);
1170 if (reader->doc != NULL)
1171 return(xmlTextReaderReadTree(reader));
1172 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001173 return(-1);
1174 if (reader->ctxt->wellFormed != 1)
1175 return(-1);
1176
1177#ifdef DEBUG_READER
1178 fprintf(stderr, "\nREAD ");
1179 DUMP_READER
1180#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001181 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001182 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1183 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001184 /*
1185 * Initial state
1186 */
1187 do {
1188 val = xmlTextReaderPushData(reader);
1189 if (val < 0)
1190 return(-1);
1191 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001192 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1193 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001194 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001195 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001196 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001197 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001198 if (reader->node == NULL)
1199 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001200 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001201 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001202 if (reader->ctxt->myDoc != NULL) {
1203 reader->node = reader->ctxt->myDoc->children;
1204 }
1205 if (reader->node == NULL)
1206 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001207 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001208 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001209 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001210 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 }
1212 oldstate = reader->state;
1213 olddepth = reader->ctxt->nodeNr;
1214 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001215
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001216get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001217 /*
1218 * If we are not backtracking on ancestors or examined nodes,
1219 * that the parser didn't finished or that we arent at the end
1220 * of stream, continue processing.
1221 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001222 while ((reader->node->next == NULL) &&
1223 (reader->ctxt->nodeNr == olddepth) &&
1224 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001225 (reader->node->children == NULL) ||
1226 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001227 ((reader->node->children != NULL) &&
1228 (reader->node->children->type == XML_TEXT_NODE) &&
1229 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001230 (reader->node->type == XML_DTD_NODE) ||
1231 (reader->node->type == XML_DOCUMENT_NODE) ||
1232 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001233 ((reader->ctxt->node == NULL) ||
1234 (reader->ctxt->node == reader->node) ||
1235 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001236 (reader->ctxt->instate != XML_PARSER_EOF)) {
1237 val = xmlTextReaderPushData(reader);
1238 if (val < 0)
1239 return(-1);
1240 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001241 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001242 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001243 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001244 if ((reader->node->children != NULL) &&
1245 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001246 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001247 (reader->node->type != XML_DTD_NODE)) {
1248 reader->node = reader->node->children;
1249 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001250 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001251 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001252 }
1253 }
1254 if (reader->node->next != NULL) {
1255 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001256 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001257 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001258 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1259#ifdef LIBXML_XINCLUDE_ENABLED
1260 && (reader->in_xinclude <= 0)
1261#endif
1262 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001264 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001265 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001266#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001267 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001268 (reader->node->type == XML_ELEMENT_NODE))
1269 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001270#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001271 if ((reader->preserves > 0) &&
1272 (reader->node->extra & NODE_IS_SPRESERVED))
1273 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001274 reader->node = reader->node->next;
1275 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001276
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001277 /*
1278 * Cleanup of the old node
1279 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001280 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001281#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001282 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001283#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001284 (reader->entNr == 0) &&
1285 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001286 (reader->node->prev->type != XML_DTD_NODE) &&
1287 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001288 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001289 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001290 xmlUnlinkNode(tmp);
1291 xmlTextReaderFreeNode(reader, tmp);
1292 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001293 }
1294
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001295 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001296 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001297 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001298 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001299 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001300 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001301 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001302 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001303 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001304#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001305 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001306 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001307#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001308 if ((reader->preserves > 0) &&
1309 (reader->node->extra & NODE_IS_SPRESERVED))
1310 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001311 reader->node = reader->node->parent;
1312 if ((reader->node == NULL) ||
1313 (reader->node->type == XML_DOCUMENT_NODE) ||
1314#ifdef LIBXML_DOCB_ENABLED
1315 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1316#endif
1317 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001318 if (reader->mode != XML_TEXTREADER_DONE) {
1319 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1320 reader->mode = XML_TEXTREADER_DONE;
1321 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001322 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001323 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001324
1325 /*
1326 * Cleanup of the old node
1327 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001328 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001329#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001330 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001331#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001332 (reader->entNr == 0) &&
1333 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001334 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001335 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001336 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001337 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001338 }
1339
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001340 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001341 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001342 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001343#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001344 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001345#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001346 (reader->entNr == 0) &&
1347 (reader->node->last != NULL) &&
1348 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1349 xmlNodePtr tmp = reader->node->last;
1350 xmlUnlinkNode(tmp);
1351 xmlTextReaderFreeNode(reader, tmp);
1352 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001353 reader->depth--;
1354 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001355
1356node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001357 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001358
1359 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001360 * If we are in the middle of a piece of CDATA make sure it's finished
1361 */
1362 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001363 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001364 ((reader->node->type == XML_TEXT_NODE) ||
1365 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1366 xmlTextReaderExpand(reader);
1367 }
1368
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001369#ifdef LIBXML_XINCLUDE_ENABLED
1370 /*
1371 * Handle XInclude if asked for
1372 */
1373 if ((reader->xinclude) && (reader->node != NULL) &&
1374 (reader->node->type == XML_ELEMENT_NODE) &&
1375 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001376 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1377 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001378 if (reader->xincctxt == NULL) {
1379 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001380 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001381 }
1382 /*
1383 * expand that node and process it
1384 */
1385 xmlTextReaderExpand(reader);
1386 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1387 }
1388 if (reader->node->type == XML_XINCLUDE_START) {
1389 reader->in_xinclude++;
1390 goto get_next_node;
1391 }
1392 if (reader->node->type == XML_XINCLUDE_END) {
1393 reader->in_xinclude--;
1394 goto get_next_node;
1395 }
1396#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001397 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001398 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001399 */
1400 if ((reader->node != NULL) &&
1401 (reader->node->type == XML_ENTITY_REF_NODE) &&
1402 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1403 /*
1404 * Case where the underlying tree is not availble, lookup the entity
1405 * and walk it.
1406 */
1407 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1408 (reader->ctxt->sax->getEntity != NULL)) {
1409 reader->node->children = (xmlNodePtr)
1410 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1411 }
1412
1413 if ((reader->node->children != NULL) &&
1414 (reader->node->children->type == XML_ENTITY_DECL) &&
1415 (reader->node->children->children != NULL)) {
1416 xmlTextReaderEntPush(reader, reader->node);
1417 reader->node = reader->node->children->children;
1418 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001419#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001420 } else if ((reader->node != NULL) &&
1421 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001422 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001423 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001424#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001425 }
1426 if ((reader->node != NULL) &&
1427 (reader->node->type == XML_ENTITY_DECL) &&
1428 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1429 reader->node = xmlTextReaderEntPop(reader);
1430 reader->depth++;
1431 goto get_next_node;
1432 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001433#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001434 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001435 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001436
1437 if ((node->type == XML_ELEMENT_NODE) &&
1438 ((reader->state != XML_TEXTREADER_END) &&
1439 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1440 xmlTextReaderValidatePush(reader);
1441 } else if ((node->type == XML_TEXT_NODE) ||
1442 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001443 xmlTextReaderValidateCData(reader, node->content,
1444 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001445 }
1446 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001447#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001448#ifdef LIBXML_PATTERN_ENABLED
1449 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1450 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1451 int i;
1452 for (i = 0;i < reader->patternNr;i++) {
1453 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1454 xmlTextReaderPreserve(reader);
1455 break;
1456 }
1457 }
1458 }
1459#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001460 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001461node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001462 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001463 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001464}
1465
Daniel Veillard67df8092002-12-16 22:04:11 +00001466/**
1467 * xmlTextReaderReadState:
1468 * @reader: the xmlTextReaderPtr used
1469 *
1470 * Gets the read state of the reader.
1471 *
1472 * Returns the state value, or -1 in case of error
1473 */
1474int
1475xmlTextReaderReadState(xmlTextReaderPtr reader) {
1476 if (reader == NULL)
1477 return(-1);
1478 return(reader->mode);
1479}
1480
1481/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001482 * xmlTextReaderExpand:
1483 * @reader: the xmlTextReaderPtr used
1484 *
1485 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001486 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001487 *
1488 * Returns a node pointer valid until the next xmlTextReaderRead() call
1489 * or NULL in case of error.
1490 */
1491xmlNodePtr
1492xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001493 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001494 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001495 if (reader->doc != NULL)
1496 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001497 if (reader->ctxt == NULL)
1498 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001499 if (xmlTextReaderDoExpand(reader) < 0)
1500 return(NULL);
1501 return(reader->node);
1502}
1503
1504/**
1505 * xmlTextReaderNext:
1506 * @reader: the xmlTextReaderPtr used
1507 *
1508 * Skip to the node following the current one in document order while
1509 * avoiding the subtree if any.
1510 *
1511 * Returns 1 if the node was read successfully, 0 if there is no more
1512 * nodes to read, or -1 in case of error
1513 */
1514int
1515xmlTextReaderNext(xmlTextReaderPtr reader) {
1516 int ret;
1517 xmlNodePtr cur;
1518
1519 if (reader == NULL)
1520 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001521 if (reader->doc != NULL)
1522 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001523 cur = reader->node;
1524 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1525 return(xmlTextReaderRead(reader));
1526 if (reader->state == XML_TEXTREADER_END)
1527 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001528 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001529 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001530 do {
1531 ret = xmlTextReaderRead(reader);
1532 if (ret != 1)
1533 return(ret);
1534 } while (reader->node != cur);
1535 return(xmlTextReaderRead(reader));
1536}
1537
1538/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001539 * xmlTextReaderReadInnerXml:
1540 * @reader: the xmlTextReaderPtr used
1541 *
1542 * Reads the contents of the current node, including child nodes and markup.
1543 *
1544 * Returns a string containing the XML content, or NULL if the current node
1545 * is neither an element nor attribute, or has no child nodes. The
1546 * string must be deallocated by the caller.
1547 */
1548xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001549xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001550 TODO
1551 return(NULL);
1552}
1553
1554/**
1555 * xmlTextReaderReadOuterXml:
1556 * @reader: the xmlTextReaderPtr used
1557 *
1558 * Reads the contents of the current node, including child nodes and markup.
1559 *
1560 * Returns a string containing the XML content, or NULL if the current node
1561 * is neither an element nor attribute, or has no child nodes. The
1562 * string must be deallocated by the caller.
1563 */
1564xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001565xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001566 TODO
1567 return(NULL);
1568}
1569
1570/**
1571 * xmlTextReaderReadString:
1572 * @reader: the xmlTextReaderPtr used
1573 *
1574 * Reads the contents of an element or a text node as a string.
1575 *
1576 * Returns a string containing the contents of the Element or Text node,
1577 * or NULL if the reader is positioned on any other type of node.
1578 * The string must be deallocated by the caller.
1579 */
1580xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001581xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001582 TODO
1583 return(NULL);
1584}
1585
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001586#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001587/**
1588 * xmlTextReaderReadBase64:
1589 * @reader: the xmlTextReaderPtr used
1590 * @array: a byte array to store the content.
1591 * @offset: the zero-based index into array where the method should
1592 * begin to write.
1593 * @len: the number of bytes to write.
1594 *
1595 * Reads and decodes the Base64 encoded contents of an element and
1596 * stores the result in a byte buffer.
1597 *
1598 * Returns the number of bytes written to array, or zero if the current
1599 * instance is not positioned on an element or -1 in case of error.
1600 */
1601int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001602xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1603 unsigned char *array ATTRIBUTE_UNUSED,
1604 int offset ATTRIBUTE_UNUSED,
1605 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001606 if ((reader == NULL) || (reader->ctxt == NULL))
1607 return(-1);
1608 if (reader->ctxt->wellFormed != 1)
1609 return(-1);
1610
1611 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1612 return(0);
1613 TODO
1614 return(0);
1615}
1616
1617/**
1618 * xmlTextReaderReadBinHex:
1619 * @reader: the xmlTextReaderPtr used
1620 * @array: a byte array to store the content.
1621 * @offset: the zero-based index into array where the method should
1622 * begin to write.
1623 * @len: the number of bytes to write.
1624 *
1625 * Reads and decodes the BinHex encoded contents of an element and
1626 * stores the result in a byte buffer.
1627 *
1628 * Returns the number of bytes written to array, or zero if the current
1629 * instance is not positioned on an element or -1 in case of error.
1630 */
1631int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001632xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1633 unsigned char *array ATTRIBUTE_UNUSED,
1634 int offset ATTRIBUTE_UNUSED,
1635 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001636 if ((reader == NULL) || (reader->ctxt == NULL))
1637 return(-1);
1638 if (reader->ctxt->wellFormed != 1)
1639 return(-1);
1640
1641 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1642 return(0);
1643 TODO
1644 return(0);
1645}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001646#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001647
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001648/************************************************************************
1649 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001650 * Operating on a preparsed tree *
1651 * *
1652 ************************************************************************/
1653static int
1654xmlTextReaderNextTree(xmlTextReaderPtr reader)
1655{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001656 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001657 return(-1);
1658
1659 if (reader->state == XML_TEXTREADER_END)
1660 return(0);
1661
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001662 if (reader->node == NULL) {
1663 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001664 reader->state = XML_TEXTREADER_END;
1665 return(0);
1666 }
1667
1668 reader->node = reader->doc->children;
1669 reader->state = XML_TEXTREADER_START;
1670 return(1);
1671 }
1672
1673 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1674 if (reader->node->children != 0) {
1675 reader->node = reader->node->children;
1676 reader->depth++;
1677 reader->state = XML_TEXTREADER_START;
1678 return(1);
1679 }
1680
1681 if ((reader->node->type == XML_ELEMENT_NODE) ||
1682 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1683 reader->state = XML_TEXTREADER_BACKTRACK;
1684 return(1);
1685 }
1686 }
1687
1688 if (reader->node->next != 0) {
1689 reader->node = reader->node->next;
1690 reader->state = XML_TEXTREADER_START;
1691 return(1);
1692 }
1693
1694 if (reader->node->parent != 0) {
1695 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1696 reader->state = XML_TEXTREADER_END;
1697 return(0);
1698 }
1699
1700 reader->node = reader->node->parent;
1701 reader->depth--;
1702 reader->state = XML_TEXTREADER_BACKTRACK;
1703 return(1);
1704 }
1705
1706 reader->state = XML_TEXTREADER_END;
1707
1708 return(1);
1709}
1710
1711/**
1712 * xmlTextReaderReadTree:
1713 * @reader: the xmlTextReaderPtr used
1714 *
1715 * Moves the position of the current instance to the next node in
1716 * the stream, exposing its properties.
1717 *
1718 * Returns 1 if the node was read successfully, 0 if there is no more
1719 * nodes to read, or -1 in case of error
1720 */
1721static int
1722xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1723 if (reader->state == XML_TEXTREADER_END)
1724 return(0);
1725
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001726next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001727 if (reader->node == NULL) {
1728 if (reader->doc->children == NULL) {
1729 reader->state = XML_TEXTREADER_END;
1730 return(0);
1731 }
1732
1733 reader->node = reader->doc->children;
1734 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001735 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001736 }
1737
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001738 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1739 (reader->node->type != XML_DTD_NODE) &&
1740 (reader->node->type != XML_XINCLUDE_START) &&
1741 (reader->node->type != XML_ENTITY_REF_NODE)) {
1742 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001743 reader->node = reader->node->children;
1744 reader->depth++;
1745 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001746 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001747 }
1748
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001749 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001750 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001751 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001752 }
1753 }
1754
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001755 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001756 reader->node = reader->node->next;
1757 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001758 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001759 }
1760
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001761 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001762 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1763 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1764 reader->state = XML_TEXTREADER_END;
1765 return(0);
1766 }
1767
1768 reader->node = reader->node->parent;
1769 reader->depth--;
1770 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001771 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001772 }
1773
1774 reader->state = XML_TEXTREADER_END;
1775
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001776found_node:
1777 if ((reader->node->type == XML_XINCLUDE_START) ||
1778 (reader->node->type == XML_XINCLUDE_END))
1779 goto next_node;
1780
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001781 return(1);
1782}
1783
1784/**
William M. Brackb1d53162003-11-18 06:54:40 +00001785 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001786 * @reader: the xmlTextReaderPtr used
1787 *
1788 * Skip to the node following the current one in document order while
1789 * avoiding the subtree if any.
1790 * Currently implemented only for Readers built on a document
1791 *
1792 * Returns 1 if the node was read successfully, 0 if there is no more
1793 * nodes to read, or -1 in case of error
1794 */
1795int
1796xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1797 if (reader == NULL)
1798 return(-1);
1799 if (reader->doc == NULL) {
1800 TODO
1801 return(-1);
1802 }
1803
1804 if (reader->state == XML_TEXTREADER_END)
1805 return(0);
1806
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001807 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001808 return(xmlTextReaderNextTree(reader));
1809
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001810 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001811 reader->node = reader->node->next;
1812 reader->state = XML_TEXTREADER_START;
1813 return(1);
1814 }
1815
1816 return(0);
1817}
1818
1819/************************************************************************
1820 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001821 * Constructor and destructors *
1822 * *
1823 ************************************************************************/
1824/**
1825 * xmlNewTextReader:
1826 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001827 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001828 *
1829 * Create an xmlTextReader structure fed with @input
1830 *
1831 * Returns the new xmlTextReaderPtr or NULL in case of error
1832 */
1833xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001834xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001835 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001836
1837 if (input == NULL)
1838 return(NULL);
1839 ret = xmlMalloc(sizeof(xmlTextReader));
1840 if (ret == NULL) {
1841 xmlGenericError(xmlGenericErrorContext,
1842 "xmlNewTextReader : malloc failed\n");
1843 return(NULL);
1844 }
1845 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001846 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001847 ret->entTab = NULL;
1848 ret->entMax = 0;
1849 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001850 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001851 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001852 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1853 if (ret->sax == NULL) {
1854 xmlFree(ret);
1855 xmlGenericError(xmlGenericErrorContext,
1856 "xmlNewTextReader : malloc failed\n");
1857 return(NULL);
1858 }
Daniel Veillard81273902003-09-30 00:43:48 +00001859 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001860 ret->startElement = ret->sax->startElement;
1861 ret->sax->startElement = xmlTextReaderStartElement;
1862 ret->endElement = ret->sax->endElement;
1863 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001864#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001865 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001866#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001867 ret->startElementNs = ret->sax->startElementNs;
1868 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1869 ret->endElementNs = ret->sax->endElementNs;
1870 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001871#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001872 } else {
1873 ret->startElementNs = NULL;
1874 ret->endElementNs = NULL;
1875 }
Daniel Veillard81273902003-09-30 00:43:48 +00001876#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001877 ret->characters = ret->sax->characters;
1878 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001879 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001880 ret->cdataBlock = ret->sax->cdataBlock;
1881 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001882
Daniel Veillard67df8092002-12-16 22:04:11 +00001883 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001884 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001885 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001886 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001887 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001888 }
1889 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001890 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001891 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001892 ret->base = 0;
1893 ret->cur = 4;
1894 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001895 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001896 ret->base = 0;
1897 ret->cur = 0;
1898 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001899 if (ret->ctxt == NULL) {
1900 xmlGenericError(xmlGenericErrorContext,
1901 "xmlNewTextReader : malloc failed\n");
1902 xmlFree(ret->sax);
1903 xmlFree(ret);
1904 return(NULL);
1905 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001906 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001907 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001908 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001909 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001910 /*
1911 * use the parser dictionnary to allocate all elements and attributes names
1912 */
1913 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001914 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001915#ifdef LIBXML_XINCLUDE_ENABLED
1916 ret->xinclude = 0;
1917#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001918#ifdef LIBXML_PATTERN_ENABLED
1919 ret->patternMax = 0;
1920 ret->patternTab = NULL;
1921#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001922 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001923}
1924
1925/**
1926 * xmlNewTextReaderFilename:
1927 * @URI: the URI of the resource to process
1928 *
1929 * Create an xmlTextReader structure fed with the resource at @URI
1930 *
1931 * Returns the new xmlTextReaderPtr or NULL in case of error
1932 */
1933xmlTextReaderPtr
1934xmlNewTextReaderFilename(const char *URI) {
1935 xmlParserInputBufferPtr input;
1936 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001937 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001938
1939 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1940 if (input == NULL)
1941 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001942 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001943 if (ret == NULL) {
1944 xmlFreeParserInputBuffer(input);
1945 return(NULL);
1946 }
1947 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001948 if (ret->ctxt->directory == NULL)
1949 directory = xmlParserGetDirectory(URI);
1950 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1951 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1952 if (directory != NULL)
1953 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001954 return(ret);
1955}
1956
1957/**
1958 * xmlFreeTextReader:
1959 * @reader: the xmlTextReaderPtr
1960 *
1961 * Deallocate all the resources associated to the reader
1962 */
1963void
1964xmlFreeTextReader(xmlTextReaderPtr reader) {
1965 if (reader == NULL)
1966 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001967#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001968 if (reader->rngSchemas != NULL) {
1969 xmlRelaxNGFree(reader->rngSchemas);
1970 reader->rngSchemas = NULL;
1971 }
1972 if (reader->rngValidCtxt != NULL) {
1973 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1974 reader->rngValidCtxt = NULL;
1975 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001976#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001977#ifdef LIBXML_XINCLUDE_ENABLED
1978 if (reader->xincctxt != NULL)
1979 xmlXIncludeFreeContext(reader->xincctxt);
1980#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001981#ifdef LIBXML_PATTERN_ENABLED
1982 if (reader->patternTab != NULL) {
1983 int i;
1984 for (i = 0;i < reader->patternNr;i++) {
1985 if (reader->patternTab[i] != NULL)
1986 xmlFreePattern(reader->patternTab[i]);
1987 }
1988 xmlFree(reader->patternTab);
1989 }
1990#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001991 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001992 if (reader->dict == reader->ctxt->dict)
1993 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001994 if (reader->ctxt->myDoc != NULL) {
1995 if (reader->preserve == 0)
1996 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1997 reader->ctxt->myDoc = NULL;
1998 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001999 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2000 (reader->ctxt->vctxt.vstateMax > 0)){
2001 xmlFree(reader->ctxt->vctxt.vstateTab);
2002 reader->ctxt->vctxt.vstateTab = 0;
2003 reader->ctxt->vctxt.vstateMax = 0;
2004 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002005 if (reader->allocs & XML_TEXTREADER_CTXT)
2006 xmlFreeParserCtxt(reader->ctxt);
2007 }
2008 if (reader->sax != NULL)
2009 xmlFree(reader->sax);
2010 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2011 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002012 if (reader->faketext != NULL) {
2013 xmlFreeNode(reader->faketext);
2014 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002015 if (reader->buffer != NULL)
2016 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002017 if (reader->entTab != NULL)
2018 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002019 if (reader->dict != NULL)
2020 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002021 xmlFree(reader);
2022}
2023
2024/************************************************************************
2025 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002026 * Methods for XmlTextReader *
2027 * *
2028 ************************************************************************/
2029/**
2030 * xmlTextReaderClose:
2031 * @reader: the xmlTextReaderPtr used
2032 *
2033 * This method releases any resources allocated by the current instance
2034 * changes the state to Closed and close any underlying input.
2035 *
2036 * Returns 0 or -1 in case of error
2037 */
2038int
2039xmlTextReaderClose(xmlTextReaderPtr reader) {
2040 if (reader == NULL)
2041 return(-1);
2042 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002043 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002044 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2045 if (reader->ctxt != NULL) {
2046 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002047 if (reader->preserve == 0)
2048 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002049 reader->ctxt->myDoc = NULL;
2050 }
2051 if (reader->allocs & XML_TEXTREADER_CTXT) {
2052 xmlFreeParserCtxt(reader->ctxt);
2053 reader->allocs -= XML_TEXTREADER_CTXT;
2054 }
2055 }
2056 if (reader->sax != NULL) {
2057 xmlFree(reader->sax);
2058 reader->sax = NULL;
2059 }
2060 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2061 xmlFreeParserInputBuffer(reader->input);
2062 reader->allocs -= XML_TEXTREADER_INPUT;
2063 }
2064 return(0);
2065}
2066
2067/**
2068 * xmlTextReaderGetAttributeNo:
2069 * @reader: the xmlTextReaderPtr used
2070 * @no: the zero-based index of the attribute relative to the containing element
2071 *
2072 * Provides the value of the attribute with the specified index relative
2073 * to the containing element.
2074 *
2075 * Returns a string containing the value of the specified attribute, or NULL
2076 * in case of error. The string must be deallocated by the caller.
2077 */
2078xmlChar *
2079xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2080 xmlChar *ret;
2081 int i;
2082 xmlAttrPtr cur;
2083 xmlNsPtr ns;
2084
2085 if (reader == NULL)
2086 return(NULL);
2087 if (reader->node == NULL)
2088 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002089 if (reader->curnode != NULL)
2090 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002091 /* TODO: handle the xmlDecl */
2092 if (reader->node->type != XML_ELEMENT_NODE)
2093 return(NULL);
2094
2095 ns = reader->node->nsDef;
2096 for (i = 0;(i < no) && (ns != NULL);i++) {
2097 ns = ns->next;
2098 }
2099 if (ns != NULL)
2100 return(xmlStrdup(ns->href));
2101
2102 cur = reader->node->properties;
2103 if (cur == NULL)
2104 return(NULL);
2105 for (;i < no;i++) {
2106 cur = cur->next;
2107 if (cur == NULL)
2108 return(NULL);
2109 }
2110 /* TODO walk the DTD if present */
2111
2112 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2113 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2114 return(ret);
2115}
2116
2117/**
2118 * xmlTextReaderGetAttribute:
2119 * @reader: the xmlTextReaderPtr used
2120 * @name: the qualified name of the attribute.
2121 *
2122 * Provides the value of the attribute with the specified qualified name.
2123 *
2124 * Returns a string containing the value of the specified attribute, or NULL
2125 * in case of error. The string must be deallocated by the caller.
2126 */
2127xmlChar *
2128xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2129 xmlChar *prefix = NULL;
2130 xmlChar *localname;
2131 xmlNsPtr ns;
2132 xmlChar *ret = NULL;
2133
2134 if ((reader == NULL) || (name == NULL))
2135 return(NULL);
2136 if (reader->node == NULL)
2137 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002138 if (reader->curnode != NULL)
2139 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002140
2141 /* TODO: handle the xmlDecl */
2142 if (reader->node->type != XML_ELEMENT_NODE)
2143 return(NULL);
2144
2145 localname = xmlSplitQName2(name, &prefix);
2146 if (localname == NULL)
2147 return(xmlGetProp(reader->node, name));
2148
2149 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2150 if (ns != NULL)
2151 ret = xmlGetNsProp(reader->node, localname, ns->href);
2152
2153 if (localname != NULL)
2154 xmlFree(localname);
2155 if (prefix != NULL)
2156 xmlFree(prefix);
2157 return(ret);
2158}
2159
2160
2161/**
2162 * xmlTextReaderGetAttributeNs:
2163 * @reader: the xmlTextReaderPtr used
2164 * @localName: the local name of the attribute.
2165 * @namespaceURI: the namespace URI of the attribute.
2166 *
2167 * Provides the value of the specified attribute
2168 *
2169 * Returns a string containing the value of the specified attribute, or NULL
2170 * in case of error. The string must be deallocated by the caller.
2171 */
2172xmlChar *
2173xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2174 const xmlChar *namespaceURI) {
2175 if ((reader == NULL) || (localName == NULL))
2176 return(NULL);
2177 if (reader->node == NULL)
2178 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002179 if (reader->curnode != NULL)
2180 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002181
2182 /* TODO: handle the xmlDecl */
2183 if (reader->node->type != XML_ELEMENT_NODE)
2184 return(NULL);
2185
2186 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2187}
2188
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002189/**
2190 * xmlTextReaderGetRemainder:
2191 * @reader: the xmlTextReaderPtr used
2192 *
2193 * Method to get the remainder of the buffered XML. this method stops the
2194 * parser, set its state to End Of File and return the input stream with
2195 * what is left that the parser did not use.
2196 *
2197 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2198 * in case of error.
2199 */
2200xmlParserInputBufferPtr
2201xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2202 xmlParserInputBufferPtr ret = NULL;
2203
2204 if (reader == NULL)
2205 return(NULL);
2206 if (reader->node == NULL)
2207 return(NULL);
2208
2209 reader->node = NULL;
2210 reader->curnode = NULL;
2211 reader->mode = XML_TEXTREADER_MODE_EOF;
2212 if (reader->ctxt != NULL) {
2213 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002214 if (reader->preserve == 0)
2215 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002216 reader->ctxt->myDoc = NULL;
2217 }
2218 if (reader->allocs & XML_TEXTREADER_CTXT) {
2219 xmlFreeParserCtxt(reader->ctxt);
2220 reader->allocs -= XML_TEXTREADER_CTXT;
2221 }
2222 }
2223 if (reader->sax != NULL) {
2224 xmlFree(reader->sax);
2225 reader->sax = NULL;
2226 }
2227 if (reader->allocs & XML_TEXTREADER_INPUT) {
2228 ret = reader->input;
2229 reader->allocs -= XML_TEXTREADER_INPUT;
2230 } else {
2231 /*
2232 * Hum, one may need to duplicate the data structure because
2233 * without reference counting the input may be freed twice:
2234 * - by the layer which allocated it.
2235 * - by the layer to which would have been returned to.
2236 */
2237 TODO
2238 return(NULL);
2239 }
2240 return(ret);
2241}
2242
2243/**
2244 * xmlTextReaderLookupNamespace:
2245 * @reader: the xmlTextReaderPtr used
2246 * @prefix: the prefix whose namespace URI is to be resolved. To return
2247 * the default namespace, specify NULL
2248 *
2249 * Resolves a namespace prefix in the scope of the current element.
2250 *
2251 * Returns a string containing the namespace URI to which the prefix maps
2252 * or NULL in case of error. The string must be deallocated by the caller.
2253 */
2254xmlChar *
2255xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2256 xmlNsPtr ns;
2257
2258 if (reader == NULL)
2259 return(NULL);
2260 if (reader->node == NULL)
2261 return(NULL);
2262
2263 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2264 if (ns == NULL)
2265 return(NULL);
2266 return(xmlStrdup(ns->href));
2267}
2268
2269/**
2270 * xmlTextReaderMoveToAttributeNo:
2271 * @reader: the xmlTextReaderPtr used
2272 * @no: the zero-based index of the attribute relative to the containing
2273 * element.
2274 *
2275 * Moves the position of the current instance to the attribute with
2276 * the specified index relative to the containing element.
2277 *
2278 * Returns 1 in case of success, -1 in case of error, 0 if not found
2279 */
2280int
2281xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2282 int i;
2283 xmlAttrPtr cur;
2284 xmlNsPtr ns;
2285
2286 if (reader == NULL)
2287 return(-1);
2288 if (reader->node == NULL)
2289 return(-1);
2290 /* TODO: handle the xmlDecl */
2291 if (reader->node->type != XML_ELEMENT_NODE)
2292 return(-1);
2293
2294 reader->curnode = NULL;
2295
2296 ns = reader->node->nsDef;
2297 for (i = 0;(i < no) && (ns != NULL);i++) {
2298 ns = ns->next;
2299 }
2300 if (ns != NULL) {
2301 reader->curnode = (xmlNodePtr) ns;
2302 return(1);
2303 }
2304
2305 cur = reader->node->properties;
2306 if (cur == NULL)
2307 return(0);
2308 for (;i < no;i++) {
2309 cur = cur->next;
2310 if (cur == NULL)
2311 return(0);
2312 }
2313 /* TODO walk the DTD if present */
2314
2315 reader->curnode = (xmlNodePtr) cur;
2316 return(1);
2317}
2318
2319/**
2320 * xmlTextReaderMoveToAttribute:
2321 * @reader: the xmlTextReaderPtr used
2322 * @name: the qualified name of the attribute.
2323 *
2324 * Moves the position of the current instance to the attribute with
2325 * the specified qualified name.
2326 *
2327 * Returns 1 in case of success, -1 in case of error, 0 if not found
2328 */
2329int
2330xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2331 xmlChar *prefix = NULL;
2332 xmlChar *localname;
2333 xmlNsPtr ns;
2334 xmlAttrPtr prop;
2335
2336 if ((reader == NULL) || (name == NULL))
2337 return(-1);
2338 if (reader->node == NULL)
2339 return(-1);
2340
2341 /* TODO: handle the xmlDecl */
2342 if (reader->node->type != XML_ELEMENT_NODE)
2343 return(0);
2344
2345 localname = xmlSplitQName2(name, &prefix);
2346 if (localname == NULL) {
2347 /*
2348 * Namespace default decl
2349 */
2350 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2351 ns = reader->node->nsDef;
2352 while (ns != NULL) {
2353 if (ns->prefix == NULL) {
2354 reader->curnode = (xmlNodePtr) ns;
2355 return(1);
2356 }
2357 ns = ns->next;
2358 }
2359 return(0);
2360 }
2361
2362 prop = reader->node->properties;
2363 while (prop != NULL) {
2364 /*
2365 * One need to have
2366 * - same attribute names
2367 * - and the attribute carrying that namespace
2368 */
2369 if ((xmlStrEqual(prop->name, name)) &&
2370 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2371 reader->curnode = (xmlNodePtr) prop;
2372 return(1);
2373 }
2374 prop = prop->next;
2375 }
2376 return(0);
2377 }
2378
2379 /*
2380 * Namespace default decl
2381 */
2382 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2383 ns = reader->node->nsDef;
2384 while (ns != NULL) {
2385 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2386 reader->curnode = (xmlNodePtr) ns;
2387 goto found;
2388 }
2389 ns = ns->next;
2390 }
2391 goto not_found;
2392 }
2393 prop = reader->node->properties;
2394 while (prop != NULL) {
2395 /*
2396 * One need to have
2397 * - same attribute names
2398 * - and the attribute carrying that namespace
2399 */
2400 if ((xmlStrEqual(prop->name, localname)) &&
2401 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2402 reader->curnode = (xmlNodePtr) prop;
2403 goto found;
2404 }
2405 prop = prop->next;
2406 }
2407not_found:
2408 if (localname != NULL)
2409 xmlFree(localname);
2410 if (prefix != NULL)
2411 xmlFree(prefix);
2412 return(0);
2413
2414found:
2415 if (localname != NULL)
2416 xmlFree(localname);
2417 if (prefix != NULL)
2418 xmlFree(prefix);
2419 return(1);
2420}
2421
2422/**
2423 * xmlTextReaderMoveToAttributeNs:
2424 * @reader: the xmlTextReaderPtr used
2425 * @localName: the local name of the attribute.
2426 * @namespaceURI: the namespace URI of the attribute.
2427 *
2428 * Moves the position of the current instance to the attribute with the
2429 * specified local name and namespace URI.
2430 *
2431 * Returns 1 in case of success, -1 in case of error, 0 if not found
2432 */
2433int
2434xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2435 const xmlChar *localName, const xmlChar *namespaceURI) {
2436 xmlAttrPtr prop;
2437 xmlNodePtr node;
2438
2439 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2440 return(-1);
2441 if (reader->node == NULL)
2442 return(-1);
2443 if (reader->node->type != XML_ELEMENT_NODE)
2444 return(0);
2445 node = reader->node;
2446
2447 /*
2448 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2449 * namespace name associated to "xmlns"
2450 */
2451 prop = node->properties;
2452 while (prop != NULL) {
2453 /*
2454 * One need to have
2455 * - same attribute names
2456 * - and the attribute carrying that namespace
2457 */
2458 if (xmlStrEqual(prop->name, localName) &&
2459 ((prop->ns != NULL) &&
2460 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2461 reader->curnode = (xmlNodePtr) prop;
2462 return(1);
2463 }
2464 prop = prop->next;
2465 }
2466 return(0);
2467}
2468
2469/**
2470 * xmlTextReaderMoveToFirstAttribute:
2471 * @reader: the xmlTextReaderPtr used
2472 *
2473 * Moves the position of the current instance to the first attribute
2474 * associated with the current node.
2475 *
2476 * Returns 1 in case of success, -1 in case of error, 0 if not found
2477 */
2478int
2479xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2480 if (reader == NULL)
2481 return(-1);
2482 if (reader->node == NULL)
2483 return(-1);
2484 if (reader->node->type != XML_ELEMENT_NODE)
2485 return(0);
2486
2487 if (reader->node->nsDef != NULL) {
2488 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2489 return(1);
2490 }
2491 if (reader->node->properties != NULL) {
2492 reader->curnode = (xmlNodePtr) reader->node->properties;
2493 return(1);
2494 }
2495 return(0);
2496}
2497
2498/**
2499 * xmlTextReaderMoveToNextAttribute:
2500 * @reader: the xmlTextReaderPtr used
2501 *
2502 * Moves the position of the current instance to the next attribute
2503 * associated with the current node.
2504 *
2505 * Returns 1 in case of success, -1 in case of error, 0 if not found
2506 */
2507int
2508xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2509 if (reader == NULL)
2510 return(-1);
2511 if (reader->node == NULL)
2512 return(-1);
2513 if (reader->node->type != XML_ELEMENT_NODE)
2514 return(0);
2515 if (reader->curnode == NULL)
2516 return(xmlTextReaderMoveToFirstAttribute(reader));
2517
2518 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2519 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2520 if (ns->next != NULL) {
2521 reader->curnode = (xmlNodePtr) ns->next;
2522 return(1);
2523 }
2524 if (reader->node->properties != NULL) {
2525 reader->curnode = (xmlNodePtr) reader->node->properties;
2526 return(1);
2527 }
2528 return(0);
2529 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2530 (reader->curnode->next != NULL)) {
2531 reader->curnode = reader->curnode->next;
2532 return(1);
2533 }
2534 return(0);
2535}
2536
2537/**
2538 * xmlTextReaderMoveToElement:
2539 * @reader: the xmlTextReaderPtr used
2540 *
2541 * Moves the position of the current instance to the node that
2542 * contains the current Attribute node.
2543 *
2544 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2545 */
2546int
2547xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2548 if (reader == NULL)
2549 return(-1);
2550 if (reader->node == NULL)
2551 return(-1);
2552 if (reader->node->type != XML_ELEMENT_NODE)
2553 return(0);
2554 if (reader->curnode != NULL) {
2555 reader->curnode = NULL;
2556 return(1);
2557 }
2558 return(0);
2559}
2560
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002561/**
2562 * xmlTextReaderReadAttributeValue:
2563 * @reader: the xmlTextReaderPtr used
2564 *
2565 * Parses an attribute value into one or more Text and EntityReference nodes.
2566 *
2567 * Returns 1 in case of success, 0 if the reader was not positionned on an
2568 * ttribute node or all the attribute values have been read, or -1
2569 * in case of error.
2570 */
2571int
2572xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2573 if (reader == NULL)
2574 return(-1);
2575 if (reader->node == NULL)
2576 return(-1);
2577 if (reader->curnode == NULL)
2578 return(0);
2579 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2580 if (reader->curnode->children == NULL)
2581 return(0);
2582 reader->curnode = reader->curnode->children;
2583 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2584 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2585
2586 if (reader->faketext == NULL) {
2587 reader->faketext = xmlNewDocText(reader->node->doc,
2588 ns->href);
2589 } else {
2590 if (reader->faketext->content != NULL)
2591 xmlFree(reader->faketext->content);
2592 reader->faketext->content = xmlStrdup(ns->href);
2593 }
2594 reader->curnode = reader->faketext;
2595 } else {
2596 if (reader->curnode->next == NULL)
2597 return(0);
2598 reader->curnode = reader->curnode->next;
2599 }
2600 return(1);
2601}
2602
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002603/************************************************************************
2604 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002605 * Acces API to the current node *
2606 * *
2607 ************************************************************************/
2608/**
2609 * xmlTextReaderAttributeCount:
2610 * @reader: the xmlTextReaderPtr used
2611 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002612 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002613 *
2614 * Returns 0 i no attributes, -1 in case of error or the attribute count
2615 */
2616int
2617xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2618 int ret;
2619 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002620 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002621 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002622
2623 if (reader == NULL)
2624 return(-1);
2625 if (reader->node == NULL)
2626 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002627
2628 if (reader->curnode != NULL)
2629 node = reader->curnode;
2630 else
2631 node = reader->node;
2632
2633 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002634 return(0);
2635 if ((reader->state == XML_TEXTREADER_END) ||
2636 (reader->state == XML_TEXTREADER_BACKTRACK))
2637 return(0);
2638 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002639 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002640 while (attr != NULL) {
2641 ret++;
2642 attr = attr->next;
2643 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002644 ns = node->nsDef;
2645 while (ns != NULL) {
2646 ret++;
2647 ns = ns->next;
2648 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002649 return(ret);
2650}
2651
2652/**
2653 * xmlTextReaderNodeType:
2654 * @reader: the xmlTextReaderPtr used
2655 *
2656 * Get the node type of the current node
2657 * Reference:
2658 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2659 *
2660 * Returns the xmlNodeType of the current node or -1 in case of error
2661 */
2662int
2663xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002664 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002665
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002666 if (reader == NULL)
2667 return(-1);
2668 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002669 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002670 if (reader->curnode != NULL)
2671 node = reader->curnode;
2672 else
2673 node = reader->node;
2674 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002675 case XML_ELEMENT_NODE:
2676 if ((reader->state == XML_TEXTREADER_END) ||
2677 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002678 return(XML_READER_TYPE_END_ELEMENT);
2679 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002680 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002681 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002682 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002683 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002684 if (xmlIsBlankNode(reader->node)) {
2685 if (xmlNodeGetSpacePreserve(reader->node))
2686 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2687 else
2688 return(XML_READER_TYPE_WHITESPACE);
2689 } else {
2690 return(XML_READER_TYPE_TEXT);
2691 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002692 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002693 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002694 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002695 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002696 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002697 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002698 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002699 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002700 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002701 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002702 case XML_DOCUMENT_NODE:
2703 case XML_HTML_DOCUMENT_NODE:
2704#ifdef LIBXML_DOCB_ENABLED
2705 case XML_DOCB_DOCUMENT_NODE:
2706#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002707 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002708 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002709 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002710 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002711 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002712 case XML_DOCUMENT_TYPE_NODE:
2713 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002714 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002715
2716 case XML_ELEMENT_DECL:
2717 case XML_ATTRIBUTE_DECL:
2718 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002719 case XML_XINCLUDE_START:
2720 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002721 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002722 }
2723 return(-1);
2724}
2725
2726/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002727 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002728 * @reader: the xmlTextReaderPtr used
2729 *
2730 * Check if the current node is empty
2731 *
2732 * Returns 1 if empty, 0 if not and -1 in case of error
2733 */
2734int
2735xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2736 if ((reader == NULL) || (reader->node == NULL))
2737 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002738 if (reader->node->type != XML_ELEMENT_NODE)
2739 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002740 if (reader->curnode != NULL)
2741 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002742 if (reader->node->children != NULL)
2743 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002744 if (reader->state == XML_TEXTREADER_END)
2745 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002746 if (reader->doc != NULL)
2747 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002748#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002749 if (reader->in_xinclude > 0)
2750 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002751#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002752 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002753}
2754
2755/**
2756 * xmlTextReaderLocalName:
2757 * @reader: the xmlTextReaderPtr used
2758 *
2759 * The local name of the node.
2760 *
2761 * Returns the local name or NULL if not available
2762 */
2763xmlChar *
2764xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002765 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002766 if ((reader == NULL) || (reader->node == NULL))
2767 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002768 if (reader->curnode != NULL)
2769 node = reader->curnode;
2770 else
2771 node = reader->node;
2772 if (node->type == XML_NAMESPACE_DECL) {
2773 xmlNsPtr ns = (xmlNsPtr) node;
2774 if (ns->prefix == NULL)
2775 return(xmlStrdup(BAD_CAST "xmlns"));
2776 else
2777 return(xmlStrdup(ns->prefix));
2778 }
2779 if ((node->type != XML_ELEMENT_NODE) &&
2780 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002781 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002782 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002783}
2784
2785/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002786 * xmlTextReaderConstLocalName:
2787 * @reader: the xmlTextReaderPtr used
2788 *
2789 * The local name of the node.
2790 *
2791 * Returns the local name or NULL if not available, the
2792 * string will be deallocated with the reader.
2793 */
2794const xmlChar *
2795xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2796 xmlNodePtr node;
2797 if ((reader == NULL) || (reader->node == NULL))
2798 return(NULL);
2799 if (reader->curnode != NULL)
2800 node = reader->curnode;
2801 else
2802 node = reader->node;
2803 if (node->type == XML_NAMESPACE_DECL) {
2804 xmlNsPtr ns = (xmlNsPtr) node;
2805 if (ns->prefix == NULL)
2806 return(CONSTSTR(BAD_CAST "xmlns"));
2807 else
2808 return(ns->prefix);
2809 }
2810 if ((node->type != XML_ELEMENT_NODE) &&
2811 (node->type != XML_ATTRIBUTE_NODE))
2812 return(xmlTextReaderConstName(reader));
2813 return(node->name);
2814}
2815
2816/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002817 * xmlTextReaderName:
2818 * @reader: the xmlTextReaderPtr used
2819 *
2820 * The qualified name of the node, equal to Prefix :LocalName.
2821 *
2822 * Returns the local name or NULL if not available
2823 */
2824xmlChar *
2825xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002826 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002827 xmlChar *ret;
2828
2829 if ((reader == NULL) || (reader->node == NULL))
2830 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002831 if (reader->curnode != NULL)
2832 node = reader->curnode;
2833 else
2834 node = reader->node;
2835 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002836 case XML_ELEMENT_NODE:
2837 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002838 if ((node->ns == NULL) ||
2839 (node->ns->prefix == NULL))
2840 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002841
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002842 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002843 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002844 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002845 return(ret);
2846 case XML_TEXT_NODE:
2847 return(xmlStrdup(BAD_CAST "#text"));
2848 case XML_CDATA_SECTION_NODE:
2849 return(xmlStrdup(BAD_CAST "#cdata-section"));
2850 case XML_ENTITY_NODE:
2851 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002852 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002853 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002854 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002855 case XML_COMMENT_NODE:
2856 return(xmlStrdup(BAD_CAST "#comment"));
2857 case XML_DOCUMENT_NODE:
2858 case XML_HTML_DOCUMENT_NODE:
2859#ifdef LIBXML_DOCB_ENABLED
2860 case XML_DOCB_DOCUMENT_NODE:
2861#endif
2862 return(xmlStrdup(BAD_CAST "#document"));
2863 case XML_DOCUMENT_FRAG_NODE:
2864 return(xmlStrdup(BAD_CAST "#document-fragment"));
2865 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002866 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002867 case XML_DOCUMENT_TYPE_NODE:
2868 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002869 return(xmlStrdup(node->name));
2870 case XML_NAMESPACE_DECL: {
2871 xmlNsPtr ns = (xmlNsPtr) node;
2872
2873 ret = xmlStrdup(BAD_CAST "xmlns");
2874 if (ns->prefix == NULL)
2875 return(ret);
2876 ret = xmlStrcat(ret, BAD_CAST ":");
2877 ret = xmlStrcat(ret, ns->prefix);
2878 return(ret);
2879 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002880
2881 case XML_ELEMENT_DECL:
2882 case XML_ATTRIBUTE_DECL:
2883 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002884 case XML_XINCLUDE_START:
2885 case XML_XINCLUDE_END:
2886 return(NULL);
2887 }
2888 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002889}
2890
2891/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002892 * xmlTextReaderConstName:
2893 * @reader: the xmlTextReaderPtr used
2894 *
2895 * The qualified name of the node, equal to Prefix :LocalName.
2896 *
2897 * Returns the local name or NULL if not available, the string is
2898 * deallocated with the reader.
2899 */
2900const xmlChar *
2901xmlTextReaderConstName(xmlTextReaderPtr reader) {
2902 xmlNodePtr node;
2903
2904 if ((reader == NULL) || (reader->node == NULL))
2905 return(NULL);
2906 if (reader->curnode != NULL)
2907 node = reader->curnode;
2908 else
2909 node = reader->node;
2910 switch (node->type) {
2911 case XML_ELEMENT_NODE:
2912 case XML_ATTRIBUTE_NODE:
2913 if ((node->ns == NULL) ||
2914 (node->ns->prefix == NULL))
2915 return(node->name);
2916 return(CONSTQSTR(node->ns->prefix, node->name));
2917 case XML_TEXT_NODE:
2918 return(CONSTSTR(BAD_CAST "#text"));
2919 case XML_CDATA_SECTION_NODE:
2920 return(CONSTSTR(BAD_CAST "#cdata-section"));
2921 case XML_ENTITY_NODE:
2922 case XML_ENTITY_REF_NODE:
2923 return(CONSTSTR(node->name));
2924 case XML_PI_NODE:
2925 return(CONSTSTR(node->name));
2926 case XML_COMMENT_NODE:
2927 return(CONSTSTR(BAD_CAST "#comment"));
2928 case XML_DOCUMENT_NODE:
2929 case XML_HTML_DOCUMENT_NODE:
2930#ifdef LIBXML_DOCB_ENABLED
2931 case XML_DOCB_DOCUMENT_NODE:
2932#endif
2933 return(CONSTSTR(BAD_CAST "#document"));
2934 case XML_DOCUMENT_FRAG_NODE:
2935 return(CONSTSTR(BAD_CAST "#document-fragment"));
2936 case XML_NOTATION_NODE:
2937 return(CONSTSTR(node->name));
2938 case XML_DOCUMENT_TYPE_NODE:
2939 case XML_DTD_NODE:
2940 return(CONSTSTR(node->name));
2941 case XML_NAMESPACE_DECL: {
2942 xmlNsPtr ns = (xmlNsPtr) node;
2943
2944 if (ns->prefix == NULL)
2945 return(CONSTSTR(BAD_CAST "xmlns"));
2946 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2947 }
2948
2949 case XML_ELEMENT_DECL:
2950 case XML_ATTRIBUTE_DECL:
2951 case XML_ENTITY_DECL:
2952 case XML_XINCLUDE_START:
2953 case XML_XINCLUDE_END:
2954 return(NULL);
2955 }
2956 return(NULL);
2957}
2958
2959/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002960 * xmlTextReaderPrefix:
2961 * @reader: the xmlTextReaderPtr used
2962 *
2963 * A shorthand reference to the namespace associated with the node.
2964 *
2965 * Returns the prefix or NULL if not available
2966 */
2967xmlChar *
2968xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002969 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002970 if ((reader == NULL) || (reader->node == NULL))
2971 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002972 if (reader->curnode != NULL)
2973 node = reader->curnode;
2974 else
2975 node = reader->node;
2976 if (node->type == XML_NAMESPACE_DECL) {
2977 xmlNsPtr ns = (xmlNsPtr) node;
2978 if (ns->prefix == NULL)
2979 return(NULL);
2980 return(xmlStrdup(BAD_CAST "xmlns"));
2981 }
2982 if ((node->type != XML_ELEMENT_NODE) &&
2983 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002984 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002985 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002986 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002987 return(NULL);
2988}
2989
2990/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002991 * xmlTextReaderConstPrefix:
2992 * @reader: the xmlTextReaderPtr used
2993 *
2994 * A shorthand reference to the namespace associated with the node.
2995 *
2996 * Returns the prefix or NULL if not available, the string is deallocated
2997 * with the reader.
2998 */
2999const xmlChar *
3000xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3001 xmlNodePtr node;
3002 if ((reader == NULL) || (reader->node == NULL))
3003 return(NULL);
3004 if (reader->curnode != NULL)
3005 node = reader->curnode;
3006 else
3007 node = reader->node;
3008 if (node->type == XML_NAMESPACE_DECL) {
3009 xmlNsPtr ns = (xmlNsPtr) node;
3010 if (ns->prefix == NULL)
3011 return(NULL);
3012 return(CONSTSTR(BAD_CAST "xmlns"));
3013 }
3014 if ((node->type != XML_ELEMENT_NODE) &&
3015 (node->type != XML_ATTRIBUTE_NODE))
3016 return(NULL);
3017 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3018 return(CONSTSTR(node->ns->prefix));
3019 return(NULL);
3020}
3021
3022/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023 * xmlTextReaderNamespaceUri:
3024 * @reader: the xmlTextReaderPtr used
3025 *
3026 * The URI defining the namespace associated with the node.
3027 *
3028 * Returns the namespace URI or NULL if not available
3029 */
3030xmlChar *
3031xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003032 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003033 if ((reader == NULL) || (reader->node == NULL))
3034 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003035 if (reader->curnode != NULL)
3036 node = reader->curnode;
3037 else
3038 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003039 if (node->type == XML_NAMESPACE_DECL)
3040 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003041 if ((node->type != XML_ELEMENT_NODE) &&
3042 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003043 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003044 if (node->ns != NULL)
3045 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046 return(NULL);
3047}
3048
3049/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003050 * xmlTextReaderConstNamespaceUri:
3051 * @reader: the xmlTextReaderPtr used
3052 *
3053 * The URI defining the namespace associated with the node.
3054 *
3055 * Returns the namespace URI or NULL if not available, the string
3056 * will be deallocated with the reader
3057 */
3058const xmlChar *
3059xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3060 xmlNodePtr node;
3061 if ((reader == NULL) || (reader->node == NULL))
3062 return(NULL);
3063 if (reader->curnode != NULL)
3064 node = reader->curnode;
3065 else
3066 node = reader->node;
3067 if (node->type == XML_NAMESPACE_DECL)
3068 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3069 if ((node->type != XML_ELEMENT_NODE) &&
3070 (node->type != XML_ATTRIBUTE_NODE))
3071 return(NULL);
3072 if (node->ns != NULL)
3073 return(CONSTSTR(node->ns->href));
3074 return(NULL);
3075}
3076
3077/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003078 * xmlTextReaderBaseUri:
3079 * @reader: the xmlTextReaderPtr used
3080 *
3081 * The base URI of the node.
3082 *
3083 * Returns the base URI or NULL if not available
3084 */
3085xmlChar *
3086xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3087 if ((reader == NULL) || (reader->node == NULL))
3088 return(NULL);
3089 return(xmlNodeGetBase(NULL, reader->node));
3090}
3091
3092/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003093 * xmlTextReaderConstBaseUri:
3094 * @reader: the xmlTextReaderPtr used
3095 *
3096 * The base URI of the node.
3097 *
3098 * Returns the base URI or NULL if not available, the string
3099 * will be deallocated with the reader
3100 */
3101const xmlChar *
3102xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3103 xmlChar *tmp;
3104 const xmlChar *ret;
3105
3106 if ((reader == NULL) || (reader->node == NULL))
3107 return(NULL);
3108 tmp = xmlNodeGetBase(NULL, reader->node);
3109 if (tmp == NULL)
3110 return(NULL);
3111 ret = CONSTSTR(tmp);
3112 xmlFree(tmp);
3113 return(ret);
3114}
3115
3116/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003117 * xmlTextReaderDepth:
3118 * @reader: the xmlTextReaderPtr used
3119 *
3120 * The depth of the node in the tree.
3121 *
3122 * Returns the depth or -1 in case of error
3123 */
3124int
3125xmlTextReaderDepth(xmlTextReaderPtr reader) {
3126 if (reader == NULL)
3127 return(-1);
3128 if (reader->node == NULL)
3129 return(0);
3130
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003131 if (reader->curnode != NULL) {
3132 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3133 (reader->curnode->type == XML_NAMESPACE_DECL))
3134 return(reader->depth + 1);
3135 return(reader->depth + 2);
3136 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003137 return(reader->depth);
3138}
3139
3140/**
3141 * xmlTextReaderHasAttributes:
3142 * @reader: the xmlTextReaderPtr used
3143 *
3144 * Whether the node has attributes.
3145 *
3146 * Returns 1 if true, 0 if false, and -1 in case or error
3147 */
3148int
3149xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003150 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003151 if (reader == NULL)
3152 return(-1);
3153 if (reader->node == NULL)
3154 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003155 if (reader->curnode != NULL)
3156 node = reader->curnode;
3157 else
3158 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003159
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003160 if ((node->type == XML_ELEMENT_NODE) &&
3161 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003162 return(1);
3163 /* TODO: handle the xmlDecl */
3164 return(0);
3165}
3166
3167/**
3168 * xmlTextReaderHasValue:
3169 * @reader: the xmlTextReaderPtr used
3170 *
3171 * Whether the node can have a text value.
3172 *
3173 * Returns 1 if true, 0 if false, and -1 in case or error
3174 */
3175int
3176xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003177 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003178 if (reader == NULL)
3179 return(-1);
3180 if (reader->node == NULL)
3181 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003182 if (reader->curnode != NULL)
3183 node = reader->curnode;
3184 else
3185 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003186
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003187 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003188 case XML_ATTRIBUTE_NODE:
3189 case XML_TEXT_NODE:
3190 case XML_CDATA_SECTION_NODE:
3191 case XML_PI_NODE:
3192 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003193 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003194 return(1);
3195 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003196 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003197 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003198 return(0);
3199}
3200
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003201/**
3202 * xmlTextReaderValue:
3203 * @reader: the xmlTextReaderPtr used
3204 *
3205 * Provides the text value of the node if present
3206 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003207 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003208 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003209 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003210xmlChar *
3211xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003212 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003213 if (reader == NULL)
3214 return(NULL);
3215 if (reader->node == NULL)
3216 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003217 if (reader->curnode != NULL)
3218 node = reader->curnode;
3219 else
3220 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003221
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003222 switch (node->type) {
3223 case XML_NAMESPACE_DECL:
3224 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003225 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003226 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003227
3228 if (attr->parent != NULL)
3229 return (xmlNodeListGetString
3230 (attr->parent->doc, attr->children, 1));
3231 else
3232 return (xmlNodeListGetString(NULL, attr->children, 1));
3233 break;
3234 }
3235 case XML_TEXT_NODE:
3236 case XML_CDATA_SECTION_NODE:
3237 case XML_PI_NODE:
3238 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003239 if (node->content != NULL)
3240 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003241 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003242 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003243 }
3244 return(NULL);
3245}
3246
3247/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003248 * xmlTextReaderConstValue:
3249 * @reader: the xmlTextReaderPtr used
3250 *
3251 * Provides the text value of the node if present
3252 *
3253 * Returns the string or NULL if not available. The result will be
3254 * deallocated on the next Read() operation.
3255 */
3256const xmlChar *
3257xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3258 xmlNodePtr node;
3259 if (reader == NULL)
3260 return(NULL);
3261 if (reader->node == NULL)
3262 return(NULL);
3263 if (reader->curnode != NULL)
3264 node = reader->curnode;
3265 else
3266 node = reader->node;
3267
3268 switch (node->type) {
3269 case XML_NAMESPACE_DECL:
3270 return(((xmlNsPtr) node)->href);
3271 case XML_ATTRIBUTE_NODE:{
3272 xmlAttrPtr attr = (xmlAttrPtr) node;
3273
3274 if ((attr->children != NULL) &&
3275 (attr->children->type == XML_TEXT_NODE) &&
3276 (attr->children->next == NULL))
3277 return(attr->children->content);
3278 else {
3279 reader->buffer->use = 0;
3280 xmlNodeBufGetContent(reader->buffer, node);
3281 return(reader->buffer->content);
3282 }
3283 break;
3284 }
3285 case XML_TEXT_NODE:
3286 case XML_CDATA_SECTION_NODE:
3287 case XML_PI_NODE:
3288 case XML_COMMENT_NODE:
3289 return(node->content);
3290 default:
3291 break;
3292 }
3293 return(NULL);
3294}
3295
3296/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003297 * xmlTextReaderIsDefault:
3298 * @reader: the xmlTextReaderPtr used
3299 *
3300 * Whether an Attribute node was generated from the default value
3301 * defined in the DTD or schema.
3302 *
3303 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3304 */
3305int
3306xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3307 if (reader == NULL)
3308 return(-1);
3309 return(0);
3310}
3311
3312/**
3313 * xmlTextReaderQuoteChar:
3314 * @reader: the xmlTextReaderPtr used
3315 *
3316 * The quotation mark character used to enclose the value of an attribute.
3317 *
3318 * Returns " or ' and -1 in case of error
3319 */
3320int
3321xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3322 if (reader == NULL)
3323 return(-1);
3324 /* TODO maybe lookup the attribute value for " first */
3325 return((int) '"');
3326}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003327
3328/**
3329 * xmlTextReaderXmlLang:
3330 * @reader: the xmlTextReaderPtr used
3331 *
3332 * The xml:lang scope within which the node resides.
3333 *
3334 * Returns the xml:lang value or NULL if none exists.
3335 */
3336xmlChar *
3337xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3338 if (reader == NULL)
3339 return(NULL);
3340 if (reader->node == NULL)
3341 return(NULL);
3342 return(xmlNodeGetLang(reader->node));
3343}
3344
Daniel Veillard67df8092002-12-16 22:04:11 +00003345/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003346 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003347 * @reader: the xmlTextReaderPtr used
3348 *
3349 * The xml:lang scope within which the node resides.
3350 *
3351 * Returns the xml:lang value or NULL if none exists.
3352 */
3353const xmlChar *
3354xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3355 xmlChar *tmp;
3356 const xmlChar *ret;
3357
3358 if (reader == NULL)
3359 return(NULL);
3360 if (reader->node == NULL)
3361 return(NULL);
3362 tmp = xmlNodeGetLang(reader->node);
3363 if (tmp == NULL)
3364 return(NULL);
3365 ret = CONSTSTR(tmp);
3366 xmlFree(tmp);
3367 return(ret);
3368}
3369
3370/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003371 * xmlTextReaderConstString:
3372 * @reader: the xmlTextReaderPtr used
3373 * @str: the string to intern.
3374 *
3375 * Get an interned string from the reader, allows for example to
3376 * speedup string name comparisons
3377 *
3378 * Returns an interned copy of the string or NULL in case of error. The
3379 * string will be deallocated with the reader.
3380 */
3381const xmlChar *
3382xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3383 if (reader == NULL)
3384 return(NULL);
3385 return(CONSTSTR(str));
3386}
3387
3388/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003389 * xmlTextReaderNormalization:
3390 * @reader: the xmlTextReaderPtr used
3391 *
3392 * The value indicating whether to normalize white space and attribute values.
3393 * Since attribute value and end of line normalizations are a MUST in the XML
3394 * specification only the value true is accepted. The broken bahaviour of
3395 * accepting out of range character entities like &#0; is of course not
3396 * supported either.
3397 *
3398 * Returns 1 or -1 in case of error.
3399 */
3400int
3401xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3402 if (reader == NULL)
3403 return(-1);
3404 return(1);
3405}
3406
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003407/************************************************************************
3408 * *
3409 * Extensions to the base APIs *
3410 * *
3411 ************************************************************************/
3412
3413/**
3414 * xmlTextReaderSetParserProp:
3415 * @reader: the xmlTextReaderPtr used
3416 * @prop: the xmlParserProperties to set
3417 * @value: usually 0 or 1 to (de)activate it
3418 *
3419 * Change the parser processing behaviour by changing some of its internal
3420 * properties. Note that some properties can only be changed before any
3421 * read has been done.
3422 *
3423 * Returns 0 if the call was successful, or -1 in case of error
3424 */
3425int
3426xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3427 xmlParserProperties p = (xmlParserProperties) prop;
3428 xmlParserCtxtPtr ctxt;
3429
3430 if ((reader == NULL) || (reader->ctxt == NULL))
3431 return(-1);
3432 ctxt = reader->ctxt;
3433
3434 switch (p) {
3435 case XML_PARSER_LOADDTD:
3436 if (value != 0) {
3437 if (ctxt->loadsubset == 0) {
3438 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3439 return(-1);
3440 ctxt->loadsubset = XML_DETECT_IDS;
3441 }
3442 } else {
3443 ctxt->loadsubset = 0;
3444 }
3445 return(0);
3446 case XML_PARSER_DEFAULTATTRS:
3447 if (value != 0) {
3448 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3449 } else {
3450 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3451 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3452 }
3453 return(0);
3454 case XML_PARSER_VALIDATE:
3455 if (value != 0) {
3456 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003457 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003458 } else {
3459 ctxt->validate = 0;
3460 }
3461 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003462 case XML_PARSER_SUBST_ENTITIES:
3463 if (value != 0) {
3464 ctxt->replaceEntities = 1;
3465 } else {
3466 ctxt->replaceEntities = 0;
3467 }
3468 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003469 }
3470 return(-1);
3471}
3472
3473/**
3474 * xmlTextReaderGetParserProp:
3475 * @reader: the xmlTextReaderPtr used
3476 * @prop: the xmlParserProperties to get
3477 *
3478 * Read the parser internal property.
3479 *
3480 * Returns the value, usually 0 or 1, or -1 in case of error.
3481 */
3482int
3483xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3484 xmlParserProperties p = (xmlParserProperties) prop;
3485 xmlParserCtxtPtr ctxt;
3486
3487 if ((reader == NULL) || (reader->ctxt == NULL))
3488 return(-1);
3489 ctxt = reader->ctxt;
3490
3491 switch (p) {
3492 case XML_PARSER_LOADDTD:
3493 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3494 return(1);
3495 return(0);
3496 case XML_PARSER_DEFAULTATTRS:
3497 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3498 return(1);
3499 return(0);
3500 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003501 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003502 case XML_PARSER_SUBST_ENTITIES:
3503 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003504 }
3505 return(-1);
3506}
3507
Daniel Veillarde18fc182002-12-28 22:56:33 +00003508/**
3509 * xmlTextReaderCurrentNode:
3510 * @reader: the xmlTextReaderPtr used
3511 *
3512 * Hacking interface allowing to get the xmlNodePtr correponding to the
3513 * current node being accessed by the xmlTextReader. This is dangerous
3514 * because the underlying node may be destroyed on the next Reads.
3515 *
3516 * Returns the xmlNodePtr or NULL in case of error.
3517 */
3518xmlNodePtr
3519xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3520 if (reader == NULL)
3521 return(NULL);
3522
3523 if (reader->curnode != NULL)
3524 return(reader->curnode);
3525 return(reader->node);
3526}
3527
3528/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003529 * xmlTextReaderPreserve:
3530 * @reader: the xmlTextReaderPtr used
3531 *
3532 *
3533 * current node being accessed by the xmlTextReader. This is dangerous
3534 * because the underlying node may be destroyed on the next Reads.
3535 *
3536 * Returns the xmlNodePtr or NULL in case of error.
3537 */
3538xmlNodePtr
3539xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3540 xmlNodePtr cur, parent;
3541
3542 if (reader == NULL)
3543 return(NULL);
3544
3545 if (reader->curnode != NULL)
3546 cur = reader->curnode;
3547 else
3548 cur = reader->node;
3549 if (cur == NULL)
3550 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003551
3552 if (cur->type != XML_DOCUMENT_NODE) {
3553 cur->extra |= NODE_IS_PRESERVED;
3554 cur->extra |= NODE_IS_SPRESERVED;
3555 }
3556 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003557
3558 parent = cur->parent;;
3559 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003560 if (parent->type == XML_ELEMENT_NODE)
3561 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003562 parent = parent->parent;
3563 }
3564 return(cur);
3565}
3566
Daniel Veillard1e906612003-12-05 14:57:46 +00003567#ifdef LIBXML_PATTERN_ENABLED
3568/**
3569 * xmlTextReaderPreservePattern:
3570 * @reader: the xmlTextReaderPtr used
3571 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003572 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003573 *
3574 * This tells the XML Reader to preserve all nodes matched by the
3575 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3576 * keep an handle on the resulting document once parsing has finished
3577 *
3578 * Returns a positive number in case of success and -1 in case of error
3579 */
3580int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003581xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3582 const xmlChar **namespaces)
3583{
Daniel Veillard1e906612003-12-05 14:57:46 +00003584 xmlPatternPtr comp;
3585
3586 if ((reader == NULL) || (pattern == NULL))
3587 return(-1);
3588
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003589 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003590 if (comp == NULL)
3591 return(-1);
3592
3593 if (reader->patternMax <= 0) {
3594 reader->patternMax = 4;
3595 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3596 sizeof(reader->patternTab[0]));
3597 if (reader->patternTab == NULL) {
3598 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3599 return (-1);
3600 }
3601 }
3602 if (reader->patternNr >= reader->patternMax) {
3603 xmlPatternPtr *tmp;
3604 reader->patternMax *= 2;
3605 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3606 reader->patternMax *
3607 sizeof(reader->patternTab[0]));
3608 if (tmp == NULL) {
3609 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3610 reader->patternMax /= 2;
3611 return (-1);
3612 }
3613 reader->patternTab = tmp;
3614 }
3615 reader->patternTab[reader->patternNr] = comp;
3616 return(reader->patternNr++);
3617}
3618#endif
3619
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003620/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003621 * xmlTextReaderCurrentDoc:
3622 * @reader: the xmlTextReaderPtr used
3623 *
3624 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003625 * current document being accessed by the xmlTextReader.
3626 * NOTE: as a result of this call, the reader will not destroy the
3627 * associated XML document and calling xmlFreeDoc() on the result
3628 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003629 *
3630 * Returns the xmlDocPtr or NULL in case of error.
3631 */
3632xmlDocPtr
3633xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003634 if (reader == NULL)
3635 return(NULL);
3636 if (reader->doc != NULL)
3637 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003638 if ((reader == NULL) || (reader->ctxt == NULL) ||
3639 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003640 return(NULL);
3641
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003642 reader->preserve = 1;
3643 if ((reader->ctxt->myDoc->dict != NULL) &&
3644 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3645 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003646 return(reader->ctxt->myDoc);
3647}
3648
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003649#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003650/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003651 * xmlTextReaderRelaxNGSetSchema:
3652 * @reader: the xmlTextReaderPtr used
3653 * @schema: a precompiled RelaxNG schema
3654 *
3655 * Use RelaxNG to validate the document as it is processed.
3656 * Activation is only possible before the first Read().
3657 * if @schema is NULL, then RelaxNG validation is desactivated.
3658 @ The @schema should not be freed until the reader is deallocated
3659 * or its use has been deactivated.
3660 *
3661 * Returns 0 in case the RelaxNG validation could be (des)activated and
3662 * -1 in case of error.
3663 */
3664int
3665xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3666 if (schema == NULL) {
3667 if (reader->rngSchemas != NULL) {
3668 xmlRelaxNGFree(reader->rngSchemas);
3669 reader->rngSchemas = NULL;
3670 }
3671 if (reader->rngValidCtxt != NULL) {
3672 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3673 reader->rngValidCtxt = NULL;
3674 }
3675 return(0);
3676 }
3677 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3678 return(-1);
3679 if (reader->rngSchemas != NULL) {
3680 xmlRelaxNGFree(reader->rngSchemas);
3681 reader->rngSchemas = NULL;
3682 }
3683 if (reader->rngValidCtxt != NULL) {
3684 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3685 reader->rngValidCtxt = NULL;
3686 }
3687 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3688 if (reader->rngValidCtxt == NULL)
3689 return(-1);
3690 if (reader->errorFunc != NULL) {
3691 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3692 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3693 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3694 reader->errorFuncArg);
3695 }
3696 reader->rngValidErrors = 0;
3697 reader->rngFullNode = NULL;
3698 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3699 return(0);
3700}
3701
3702/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003703 * xmlTextReaderRelaxNGValidate:
3704 * @reader: the xmlTextReaderPtr used
3705 * @rng: the path to a RelaxNG schema or NULL
3706 *
3707 * Use RelaxNG to validate the document as it is processed.
3708 * Activation is only possible before the first Read().
3709 * if @rng is NULL, then RelaxNG validation is desactivated.
3710 *
3711 * Returns 0 in case the RelaxNG validation could be (des)activated and
3712 * -1 in case of error.
3713 */
3714int
3715xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3716 xmlRelaxNGParserCtxtPtr ctxt;
3717
3718 if (reader == NULL)
3719 return(-1);
3720
3721 if (rng == NULL) {
3722 if (reader->rngSchemas != NULL) {
3723 xmlRelaxNGFree(reader->rngSchemas);
3724 reader->rngSchemas = NULL;
3725 }
3726 if (reader->rngValidCtxt != NULL) {
3727 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3728 reader->rngValidCtxt = NULL;
3729 }
3730 return(0);
3731 }
3732 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3733 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003734 if (reader->rngSchemas != NULL) {
3735 xmlRelaxNGFree(reader->rngSchemas);
3736 reader->rngSchemas = NULL;
3737 }
3738 if (reader->rngValidCtxt != NULL) {
3739 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3740 reader->rngValidCtxt = NULL;
3741 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003742 ctxt = xmlRelaxNGNewParserCtxt(rng);
3743 if (reader->errorFunc != NULL) {
3744 xmlRelaxNGSetParserErrors(ctxt,
3745 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3746 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3747 reader->errorFuncArg);
3748 }
3749 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3750 xmlRelaxNGFreeParserCtxt(ctxt);
3751 if (reader->rngSchemas == NULL)
3752 return(-1);
3753 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3754 if (reader->rngValidCtxt == NULL)
3755 return(-1);
3756 if (reader->errorFunc != NULL) {
3757 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3758 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3759 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3760 reader->errorFuncArg);
3761 }
3762 reader->rngValidErrors = 0;
3763 reader->rngFullNode = NULL;
3764 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3765 return(0);
3766}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003767#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003768
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003769/************************************************************************
3770 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003771 * Error Handling Extensions *
3772 * *
3773 ************************************************************************/
3774
3775/* helper to build a xmlMalloc'ed string from a format and va_list */
3776static char *
3777xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3778 int size;
3779 int chars;
3780 char *larger;
3781 char *str;
3782
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003783 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003784 if (str == NULL) {
3785 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3786 return NULL;
3787 }
3788
3789 size = 150;
3790
3791 while (1) {
3792 chars = vsnprintf(str, size, msg, ap);
3793 if ((chars > -1) && (chars < size))
3794 break;
3795 if (chars > -1)
3796 size += chars + 1;
3797 else
3798 size += 100;
3799 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3800 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3801 xmlFree(str);
3802 return NULL;
3803 }
3804 str = larger;
3805 }
3806
3807 return str;
3808}
3809
Daniel Veillard417be3a2003-01-20 21:26:34 +00003810/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003811 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003812 * @locator: the xmlTextReaderLocatorPtr used
3813 *
3814 * Obtain the line number for the given locator.
3815 *
3816 * Returns the line number or -1 in case of error.
3817 */
3818int
3819xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3820 /* we know that locator is a xmlParserCtxtPtr */
3821 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3822 int ret = -1;
3823
3824 if (ctx->node != NULL) {
3825 ret = xmlGetLineNo(ctx->node);
3826 }
3827 else {
3828 /* inspired from error.c */
3829 xmlParserInputPtr input;
3830 input = ctx->input;
3831 if ((input->filename == NULL) && (ctx->inputNr > 1))
3832 input = ctx->inputTab[ctx->inputNr - 2];
3833 if (input != NULL) {
3834 ret = input->line;
3835 }
3836 else {
3837 ret = -1;
3838 }
3839 }
3840
3841 return ret;
3842}
3843
3844/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003845 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003846 * @locator: the xmlTextReaderLocatorPtr used
3847 *
3848 * Obtain the base URI for the given locator.
3849 *
3850 * Returns the base URI or NULL in case of error.
3851 */
3852xmlChar *
3853xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3854 /* we know that locator is a xmlParserCtxtPtr */
3855 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3856 xmlChar *ret = NULL;
3857
3858 if (ctx->node != NULL) {
3859 ret = xmlNodeGetBase(NULL,ctx->node);
3860 }
3861 else {
3862 /* inspired from error.c */
3863 xmlParserInputPtr input;
3864 input = ctx->input;
3865 if ((input->filename == NULL) && (ctx->inputNr > 1))
3866 input = ctx->inputTab[ctx->inputNr - 2];
3867 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003868 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003869 }
3870 else {
3871 ret = NULL;
3872 }
3873 }
3874
3875 return ret;
3876}
3877
Daniel Veillard26f70262003-01-16 22:45:08 +00003878static void
William M. Brack899e64a2003-09-26 18:03:42 +00003879xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003880 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3881 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3882
3883 if (str != NULL) {
3884 reader->errorFunc(reader->errorFuncArg,
3885 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003886 severity,
3887 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003888 xmlFree(str);
3889 }
3890}
3891
3892static void
William M. Brack93d004f2004-02-03 00:14:10 +00003893xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3894 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3895 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3896
3897 if (error && reader->sErrorFunc) {
3898 reader->sErrorFunc(reader->errorFuncArg,
3899 (xmlErrorPtr) error);
3900 }
3901}
3902
3903static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003904xmlTextReaderError(void *ctxt, const char *msg, ...) {
3905 va_list ap;
3906
3907 va_start(ap,msg);
3908 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003909 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003910 xmlTextReaderBuildMessage(msg,ap));
3911 va_end(ap);
3912
3913}
3914
3915static void
3916xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3917 va_list ap;
3918
3919 va_start(ap,msg);
3920 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003921 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003922 xmlTextReaderBuildMessage(msg,ap));
3923 va_end(ap);
3924}
3925
3926static void
3927xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3928 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003929 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003930
Daniel Veillard417be3a2003-01-20 21:26:34 +00003931 if ((len > 1) && (msg[len - 2] != ':')) {
3932 /*
3933 * some callbacks only report locator information:
3934 * skip them (mimicking behaviour in error.c)
3935 */
3936 va_start(ap,msg);
3937 xmlTextReaderGenericError(ctxt,
3938 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3939 xmlTextReaderBuildMessage(msg,ap));
3940 va_end(ap);
3941 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003942}
3943
3944static void
3945xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3946 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003947 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003948
Daniel Veillard417be3a2003-01-20 21:26:34 +00003949 if ((len != 0) && (msg[len - 1] != ':')) {
3950 /*
3951 * some callbacks only report locator information:
3952 * skip them (mimicking behaviour in error.c)
3953 */
3954 va_start(ap,msg);
3955 xmlTextReaderGenericError(ctxt,
3956 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3957 xmlTextReaderBuildMessage(msg,ap));
3958 va_end(ap);
3959 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003960}
3961
3962/**
3963 * xmlTextReaderSetErrorHandler:
3964 * @reader: the xmlTextReaderPtr used
3965 * @f: the callback function to call on error and warnings
3966 * @arg: a user argument to pass to the callback function
3967 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003968 * Register a callback function that will be called on error and warnings.
3969 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003970 * If @f is NULL, the default error and warning handlers are restored.
3971 */
3972void
3973xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3974 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003975 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003976 if (f != NULL) {
3977 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003978 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003979 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3980 reader->ctxt->sax->warning = xmlTextReaderWarning;
3981 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3982 reader->errorFunc = f;
3983 reader->errorFuncArg = arg;
3984 }
3985 else {
3986 /* restore defaults */
3987 reader->ctxt->sax->error = xmlParserError;
3988 reader->ctxt->vctxt.error = xmlParserValidityError;
3989 reader->ctxt->sax->warning = xmlParserWarning;
3990 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3991 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00003992 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003993 reader->errorFuncArg = NULL;
3994 }
3995}
3996
Daniel Veillard417be3a2003-01-20 21:26:34 +00003997/**
William M. Brack93d004f2004-02-03 00:14:10 +00003998* xmlTextReaderSetStructuredErrorHandler:
3999 * @reader: the xmlTextReaderPtr used
4000 * @f: the callback function to call on error and warnings
4001 * @arg: a user argument to pass to the callback function
4002 *
4003 * Register a callback function that will be called on error and warnings.
4004 *
4005 * If @f is NULL, the default error and warning handlers are restored.
4006 */
4007void
4008xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4009 xmlStructuredErrorFunc f,
4010 void *arg) {
4011 if (f != NULL) {
4012 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4013 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4014 reader->ctxt->sax->warning = xmlTextReaderWarning;
4015 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4016 reader->sErrorFunc = f;
4017 reader->errorFunc = NULL;
4018 reader->errorFuncArg = arg;
4019 }
4020 else {
4021 /* restore defaults */
4022 reader->ctxt->sax->error = xmlParserError;
4023 reader->ctxt->sax->serror = NULL;
4024 reader->ctxt->vctxt.error = xmlParserValidityError;
4025 reader->ctxt->sax->warning = xmlParserWarning;
4026 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4027 reader->errorFunc = NULL;
4028 reader->sErrorFunc = NULL;
4029 reader->errorFuncArg = NULL;
4030 }
4031}
4032
4033/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004034 * xmlTextReaderIsValid:
4035 * @reader: the xmlTextReaderPtr used
4036 *
4037 * Retrieve the validity status from the parser context
4038 *
4039 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4040 */
4041int
4042xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004043 if (reader == NULL) return(-1);
4044#ifdef LIBXML_SCHEMAS_ENABLED
4045 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4046 return(reader->rngValidErrors == 0);
4047#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004048 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004049 return(reader->ctxt->valid);
4050 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004051}
4052
4053/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004054 * xmlTextReaderGetErrorHandler:
4055 * @reader: the xmlTextReaderPtr used
4056 * @f: the callback function or NULL is no callback has been registered
4057 * @arg: a user argument
4058 *
4059 * Retrieve the error callback function and user argument.
4060 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004061void
4062xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4063 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004064 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004065 *f = reader->errorFunc;
4066 *arg = reader->errorFuncArg;
4067}
4068
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004069
4070/************************************************************************
4071 * *
4072 * New set (2.6.0) of simpler and more flexible APIs *
4073 * *
4074 ************************************************************************/
4075
4076/**
4077 * xmlTextReaderSetup:
4078 * @reader: an XML reader
4079 * @URL: the base URL to use for the document
4080 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004081 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004082 * @reuse: keep the context for reuse
4083 *
4084 * Setup an XML reader with new options
4085 *
4086 * Returns 0 in case of success and -1 in case of error.
4087 */
4088static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004089xmlTextReaderSetup(xmlTextReaderPtr reader,
4090 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004091 const char *encoding, int options)
4092{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004093 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004094 return (-1);
4095
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004096 reader->doc = NULL;
4097 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004098 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004099 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004100 if ((input != NULL) && (reader->input != NULL) &&
4101 (reader->allocs & XML_TEXTREADER_INPUT)) {
4102 xmlFreeParserInputBuffer(reader->input);
4103 reader->input = NULL;
4104 reader->allocs -= XML_TEXTREADER_INPUT;
4105 }
4106 if (input != NULL) {
4107 reader->input = input;
4108 reader->allocs |= XML_TEXTREADER_INPUT;
4109 }
4110 if (reader->buffer == NULL)
4111 reader->buffer = xmlBufferCreateSize(100);
4112 if (reader->buffer == NULL) {
4113 xmlGenericError(xmlGenericErrorContext,
4114 "xmlTextReaderSetup : malloc failed\n");
4115 return (-1);
4116 }
4117 if (reader->sax == NULL)
4118 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4119 if (reader->sax == NULL) {
4120 xmlGenericError(xmlGenericErrorContext,
4121 "xmlTextReaderSetup : malloc failed\n");
4122 return (-1);
4123 }
4124 xmlSAXVersion(reader->sax, 2);
4125 reader->startElement = reader->sax->startElement;
4126 reader->sax->startElement = xmlTextReaderStartElement;
4127 reader->endElement = reader->sax->endElement;
4128 reader->sax->endElement = xmlTextReaderEndElement;
4129#ifdef LIBXML_SAX1_ENABLED
4130 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4131#endif /* LIBXML_SAX1_ENABLED */
4132 reader->startElementNs = reader->sax->startElementNs;
4133 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4134 reader->endElementNs = reader->sax->endElementNs;
4135 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4136#ifdef LIBXML_SAX1_ENABLED
4137 } else {
4138 reader->startElementNs = NULL;
4139 reader->endElementNs = NULL;
4140 }
4141#endif /* LIBXML_SAX1_ENABLED */
4142 reader->characters = reader->sax->characters;
4143 reader->sax->characters = xmlTextReaderCharacters;
4144 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4145 reader->cdataBlock = reader->sax->cdataBlock;
4146 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4147
4148 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4149 reader->node = NULL;
4150 reader->curnode = NULL;
4151 if (input != NULL) {
4152 if (reader->input->buffer->use < 4) {
4153 xmlParserInputBufferRead(input, 4);
4154 }
4155 if (reader->ctxt == NULL) {
4156 if (reader->input->buffer->use >= 4) {
4157 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4158 (const char *) reader->input->buffer->content, 4, URL);
4159 reader->base = 0;
4160 reader->cur = 4;
4161 } else {
4162 reader->ctxt =
4163 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4164 reader->base = 0;
4165 reader->cur = 0;
4166 }
4167 } else {
4168 xmlParserInputPtr inputStream;
4169 xmlParserInputBufferPtr buf;
4170 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4171
4172 if (reader->ctxt->myDoc != NULL)
4173 xmlDictReference(reader->ctxt->myDoc->dict);
4174 xmlCtxtReset(reader->ctxt);
4175 buf = xmlAllocParserInputBuffer(enc);
4176 if (buf == NULL) return(-1);
4177 inputStream = xmlNewInputStream(reader->ctxt);
4178 if (inputStream == NULL) {
4179 xmlFreeParserInputBuffer(buf);
4180 return(-1);
4181 }
4182
4183 if (URL == NULL)
4184 inputStream->filename = NULL;
4185 else
4186 inputStream->filename = (char *)
4187 xmlCanonicPath((const xmlChar *) URL);
4188 inputStream->buf = buf;
4189 inputStream->base = inputStream->buf->buffer->content;
4190 inputStream->cur = inputStream->buf->buffer->content;
4191 inputStream->end =
4192 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4193
4194 inputPush(reader->ctxt, inputStream);
4195 reader->cur = 0;
4196 }
4197 if (reader->ctxt == NULL) {
4198 xmlGenericError(xmlGenericErrorContext,
4199 "xmlTextReaderSetup : malloc failed\n");
4200 return (-1);
4201 }
4202 }
4203 if (reader->dict != NULL) {
4204 if (reader->ctxt->dict != NULL) {
4205 if (reader->dict != reader->ctxt->dict) {
4206 xmlDictFree(reader->dict);
4207 reader->dict = reader->ctxt->dict;
4208 }
4209 } else {
4210 reader->ctxt->dict = reader->dict;
4211 }
4212 } else {
4213 if (reader->ctxt->dict == NULL)
4214 reader->ctxt->dict = xmlDictCreate();
4215 reader->dict = reader->ctxt->dict;
4216 }
4217 reader->ctxt->_private = reader;
4218 reader->ctxt->linenumbers = 1;
4219 reader->ctxt->dictNames = 1;
4220 /*
4221 * use the parser dictionnary to allocate all elements and attributes names
4222 */
4223 reader->ctxt->docdict = 1;
4224
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004225#ifdef LIBXML_XINCLUDE_ENABLED
4226 if (reader->xincctxt != NULL) {
4227 xmlXIncludeFreeContext(reader->xincctxt);
4228 reader->xincctxt = NULL;
4229 }
4230 if (options & XML_PARSE_XINCLUDE) {
4231 reader->xinclude = 1;
4232 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4233 options -= XML_PARSE_XINCLUDE;
4234 } else
4235 reader->xinclude = 0;
4236 reader->in_xinclude = 0;
4237#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004238#ifdef LIBXML_PATTERN_ENABLED
4239 if (reader->patternTab == NULL) {
4240 reader->patternNr = 0;
4241 reader->patternMax = 0;
4242 }
4243 while (reader->patternNr > 0) {
4244 reader->patternNr--;
4245 if (reader->patternTab[reader->patternNr] != NULL) {
4246 xmlFreePattern(reader->patternTab[reader->patternNr]);
4247 reader->patternTab[reader->patternNr] = NULL;
4248 }
4249 }
4250#endif
4251
Daniel Veillardc36965d2003-12-02 10:28:48 +00004252 if (options & XML_PARSE_DTDVALID)
4253 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4254
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004255 xmlCtxtUseOptions(reader->ctxt, options);
4256 if (encoding != NULL) {
4257 xmlCharEncodingHandlerPtr hdlr;
4258
4259 hdlr = xmlFindCharEncodingHandler(encoding);
4260 if (hdlr != NULL)
4261 xmlSwitchToEncoding(reader->ctxt, hdlr);
4262 }
4263 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4264 (reader->ctxt->input->filename == NULL))
4265 reader->ctxt->input->filename = (char *)
4266 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004267
4268 reader->doc = NULL;
4269
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004270 return (0);
4271}
4272
4273/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004274 * xmlReaderWalker:
4275 * @doc: a preparsed document
4276 *
4277 * Create an xmltextReader for a preparsed document.
4278 *
4279 * Returns the new reader or NULL in case of error.
4280 */
4281xmlTextReaderPtr
4282xmlReaderWalker(xmlDocPtr doc)
4283{
4284 xmlTextReaderPtr ret;
4285
4286 if (doc == NULL)
4287 return(NULL);
4288
4289 ret = xmlMalloc(sizeof(xmlTextReader));
4290 if (ret == NULL) {
4291 xmlGenericError(xmlGenericErrorContext,
4292 "xmlNewTextReader : malloc failed\n");
4293 return(NULL);
4294 }
4295 memset(ret, 0, sizeof(xmlTextReader));
4296 ret->entNr = 0;
4297 ret->input = NULL;
4298 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4299 ret->node = NULL;
4300 ret->curnode = NULL;
4301 ret->base = 0;
4302 ret->cur = 0;
4303 ret->allocs = XML_TEXTREADER_CTXT;
4304 ret->doc = doc;
4305 ret->state = XML_TEXTREADER_START;
4306 ret->dict = xmlDictCreate();
4307 return(ret);
4308}
4309
4310/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004311 * xmlReaderForDoc:
4312 * @cur: a pointer to a zero terminated string
4313 * @URL: the base URL to use for the document
4314 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004315 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004316 *
4317 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004318 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004319 *
4320 * Returns the new reader or NULL in case of error.
4321 */
4322xmlTextReaderPtr
4323xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4324 int options)
4325{
4326 int len;
4327
4328 if (cur == NULL)
4329 return (NULL);
4330 len = xmlStrlen(cur);
4331
4332 return (xmlReaderForMemory
4333 ((const char *) cur, len, URL, encoding, options));
4334}
4335
4336/**
4337 * xmlReaderForFile:
4338 * @filename: a file or URL
4339 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004340 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004341 *
4342 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004343 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004344 *
4345 * Returns the new reader or NULL in case of error.
4346 */
4347xmlTextReaderPtr
4348xmlReaderForFile(const char *filename, const char *encoding, int options)
4349{
4350 xmlTextReaderPtr reader;
4351
4352 reader = xmlNewTextReaderFilename(filename);
4353 if (reader == NULL)
4354 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004355 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004356 return (reader);
4357}
4358
4359/**
4360 * xmlReaderForMemory:
4361 * @buffer: a pointer to a char array
4362 * @size: the size of the array
4363 * @URL: the base URL to use for the document
4364 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004365 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004366 *
4367 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004368 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004369 *
4370 * Returns the new reader or NULL in case of error.
4371 */
4372xmlTextReaderPtr
4373xmlReaderForMemory(const char *buffer, int size, const char *URL,
4374 const char *encoding, int options)
4375{
4376 xmlTextReaderPtr reader;
4377 xmlParserInputBufferPtr buf;
4378
Daniel Veillard21924522004-02-19 16:37:07 +00004379 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004380 XML_CHAR_ENCODING_NONE);
4381 if (buf == NULL) {
4382 return (NULL);
4383 }
4384 reader = xmlNewTextReader(buf, URL);
4385 if (reader == NULL) {
4386 xmlFreeParserInputBuffer(buf);
4387 return (NULL);
4388 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004389 reader->allocs |= XML_TEXTREADER_INPUT;
4390 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004391 return (reader);
4392}
4393
4394/**
4395 * xmlReaderForFd:
4396 * @fd: an open file descriptor
4397 * @URL: the base URL to use for the document
4398 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004399 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004400 *
4401 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004402 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004403 * NOTE that the file descriptor will not be closed when the
4404 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004405 *
4406 * Returns the new reader or NULL in case of error.
4407 */
4408xmlTextReaderPtr
4409xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4410{
4411 xmlTextReaderPtr reader;
4412 xmlParserInputBufferPtr input;
4413
4414 if (fd < 0)
4415 return (NULL);
4416
4417 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4418 if (input == NULL)
4419 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004420 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004421 reader = xmlNewTextReader(input, URL);
4422 if (reader == NULL) {
4423 xmlFreeParserInputBuffer(input);
4424 return (NULL);
4425 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004426 reader->allocs |= XML_TEXTREADER_INPUT;
4427 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004428 return (reader);
4429}
4430
4431/**
4432 * xmlReaderForIO:
4433 * @ioread: an I/O read function
4434 * @ioclose: an I/O close function
4435 * @ioctx: an I/O handler
4436 * @URL: the base URL to use for the document
4437 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004438 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004439 *
4440 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004441 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004442 *
4443 * Returns the new reader or NULL in case of error.
4444 */
4445xmlTextReaderPtr
4446xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4447 void *ioctx, const char *URL, const char *encoding,
4448 int options)
4449{
4450 xmlTextReaderPtr reader;
4451 xmlParserInputBufferPtr input;
4452
4453 if (ioread == NULL)
4454 return (NULL);
4455
4456 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4457 XML_CHAR_ENCODING_NONE);
4458 if (input == NULL)
4459 return (NULL);
4460 reader = xmlNewTextReader(input, URL);
4461 if (reader == NULL) {
4462 xmlFreeParserInputBuffer(input);
4463 return (NULL);
4464 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004465 reader->allocs |= XML_TEXTREADER_INPUT;
4466 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004467 return (reader);
4468}
4469
4470/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004471 * xmlReaderNewWalker:
4472 * @reader: an XML reader
4473 * @doc: a preparsed document
4474 *
4475 * Setup an xmltextReader to parse a preparsed XML document.
4476 * This reuses the existing @reader xmlTextReader.
4477 *
4478 * Returns 0 in case of success and -1 in case of error
4479 */
4480int
4481xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4482{
4483 if (doc == NULL)
4484 return (-1);
4485 if (reader == NULL)
4486 return (-1);
4487
4488 if (reader->ctxt != NULL) {
4489 xmlCtxtReset(reader->ctxt);
4490 }
4491
4492 reader->entNr = 0;
4493 reader->input = NULL;
4494 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4495 reader->node = NULL;
4496 reader->curnode = NULL;
4497 reader->base = 0;
4498 reader->cur = 0;
4499 reader->allocs = XML_TEXTREADER_CTXT;
4500 reader->doc = doc;
4501 reader->state = XML_TEXTREADER_START;
4502 if (reader->dict == NULL) {
4503 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4504 reader->dict = reader->ctxt->dict;
4505 else
4506 reader->dict = xmlDictCreate();
4507 }
4508 return(0);
4509}
4510
4511/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004512 * xmlReaderNewDoc:
4513 * @reader: an XML reader
4514 * @cur: a pointer to a zero terminated string
4515 * @URL: the base URL to use for the document
4516 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004517 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004518 *
4519 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004520 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004521 * This reuses the existing @reader xmlTextReader.
4522 *
4523 * Returns 0 in case of success and -1 in case of error
4524 */
4525int
4526xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4527 const char *URL, const char *encoding, int options)
4528{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004529
4530 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004531
4532 if (cur == NULL)
4533 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004534 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004535 return (-1);
4536
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004537 len = xmlStrlen(cur);
4538 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4539 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004540}
4541
4542/**
4543 * xmlReaderNewFile:
4544 * @reader: an XML reader
4545 * @filename: a file or URL
4546 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004547 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004548 *
4549 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004550 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004551 * This reuses the existing @reader xmlTextReader.
4552 *
4553 * Returns 0 in case of success and -1 in case of error
4554 */
4555int
4556xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4557 const char *encoding, int options)
4558{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004559 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004560
4561 if (filename == NULL)
4562 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004563 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004564 return (-1);
4565
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004566 input =
4567 xmlParserInputBufferCreateFilename(filename,
4568 XML_CHAR_ENCODING_NONE);
4569 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004570 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004571 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004572}
4573
4574/**
4575 * xmlReaderNewMemory:
4576 * @reader: an XML reader
4577 * @buffer: a pointer to a char array
4578 * @size: the size of the array
4579 * @URL: the base URL to use for the document
4580 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004581 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004582 *
4583 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004584 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004585 * This reuses the existing @reader xmlTextReader.
4586 *
4587 * Returns 0 in case of success and -1 in case of error
4588 */
4589int
4590xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4591 const char *URL, const char *encoding, int options)
4592{
4593 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004594
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004595 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004596 return (-1);
4597 if (buffer == NULL)
4598 return (-1);
4599
Daniel Veillard21924522004-02-19 16:37:07 +00004600 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004601 XML_CHAR_ENCODING_NONE);
4602 if (input == NULL) {
4603 return (-1);
4604 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004605 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004606}
4607
4608/**
4609 * xmlReaderNewFd:
4610 * @reader: an XML reader
4611 * @fd: an open file descriptor
4612 * @URL: the base URL to use for the document
4613 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004614 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004615 *
4616 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004617 * NOTE that the file descriptor will not be closed when the
4618 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004619 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004620 * This reuses the existing @reader xmlTextReader.
4621 *
4622 * Returns 0 in case of success and -1 in case of error
4623 */
4624int
4625xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4626 const char *URL, const char *encoding, int options)
4627{
4628 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004629
4630 if (fd < 0)
4631 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004632 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004633 return (-1);
4634
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004635 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4636 if (input == NULL)
4637 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004638 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004639 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004640}
4641
4642/**
4643 * xmlReaderNewIO:
4644 * @reader: an XML reader
4645 * @ioread: an I/O read function
4646 * @ioclose: an I/O close function
4647 * @ioctx: an I/O handler
4648 * @URL: the base URL to use for the document
4649 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004650 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004651 *
4652 * Setup an xmltextReader to parse an XML document from I/O functions
4653 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004654 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004655 * This reuses the existing @reader xmlTextReader.
4656 *
4657 * Returns 0 in case of success and -1 in case of error
4658 */
4659int
4660xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4661 xmlInputCloseCallback ioclose, void *ioctx,
4662 const char *URL, const char *encoding, int options)
4663{
4664 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004665
4666 if (ioread == NULL)
4667 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004668 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004669 return (-1);
4670
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004671 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4672 XML_CHAR_ENCODING_NONE);
4673 if (input == NULL)
4674 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004675 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004676}
Daniel Veillard26f70262003-01-16 22:45:08 +00004677/************************************************************************
4678 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004679 * Utilities *
4680 * *
4681 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004682#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004683/**
4684 * xmlBase64Decode:
4685 * @in: the input buffer
4686 * @inlen: the size of the input (in), the size read from it (out)
4687 * @to: the output buffer
4688 * @tolen: the size of the output (in), the size written to (out)
4689 *
4690 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004691 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004692 *
4693 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4694 * 2 if there wasn't enough space on the output or -1 in case of error.
4695 */
4696static int
4697xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4698 unsigned char *to, unsigned long *tolen) {
4699 unsigned long incur; /* current index in in[] */
4700 unsigned long inblk; /* last block index in in[] */
4701 unsigned long outcur; /* current index in out[] */
4702 unsigned long inmax; /* size of in[] */
4703 unsigned long outmax; /* size of out[] */
4704 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004705 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004706 int nbintmp; /* number of byte in intmp[] */
4707 int is_ignore; /* cur should be ignored */
4708 int is_end = 0; /* the end of the base64 was found */
4709 int retval = 1;
4710 int i;
4711
4712 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4713 return(-1);
4714
4715 incur = 0;
4716 inblk = 0;
4717 outcur = 0;
4718 inmax = *inlen;
4719 outmax = *tolen;
4720 nbintmp = 0;
4721
4722 while (1) {
4723 if (incur >= inmax)
4724 break;
4725 cur = in[incur++];
4726 is_ignore = 0;
4727 if ((cur >= 'A') && (cur <= 'Z'))
4728 cur = cur - 'A';
4729 else if ((cur >= 'a') && (cur <= 'z'))
4730 cur = cur - 'a' + 26;
4731 else if ((cur >= '0') && (cur <= '9'))
4732 cur = cur - '0' + 52;
4733 else if (cur == '+')
4734 cur = 62;
4735 else if (cur == '/')
4736 cur = 63;
4737 else if (cur == '.')
4738 cur = 0;
4739 else if (cur == '=') /*no op , end of the base64 stream */
4740 is_end = 1;
4741 else {
4742 is_ignore = 1;
4743 if (nbintmp == 0)
4744 inblk = incur;
4745 }
4746
4747 if (!is_ignore) {
4748 int nbouttmp = 3;
4749 int is_break = 0;
4750
4751 if (is_end) {
4752 if (nbintmp == 0)
4753 break;
4754 if ((nbintmp == 1) || (nbintmp == 2))
4755 nbouttmp = 1;
4756 else
4757 nbouttmp = 2;
4758 nbintmp = 3;
4759 is_break = 1;
4760 }
4761 intmp[nbintmp++] = cur;
4762 /*
4763 * if intmp is full, push the 4byte sequence as a 3 byte
4764 * sequence out
4765 */
4766 if (nbintmp == 4) {
4767 nbintmp = 0;
4768 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4769 outtmp[1] =
4770 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4771 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4772 if (outcur + 3 >= outmax) {
4773 retval = 2;
4774 break;
4775 }
4776
4777 for (i = 0; i < nbouttmp; i++)
4778 to[outcur++] = outtmp[i];
4779 inblk = incur;
4780 }
4781
4782 if (is_break) {
4783 retval = 0;
4784 break;
4785 }
4786 }
4787 }
4788
4789 *tolen = outcur;
4790 *inlen = inblk;
4791 return (retval);
4792}
4793
4794/*
4795 * Test routine for the xmlBase64Decode function
4796 */
4797#if 0
4798int main(int argc, char **argv) {
4799 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4800 char output[100];
4801 char output2[100];
4802 char output3[100];
4803 unsigned long inlen = strlen(input);
4804 unsigned long outlen = 100;
4805 int ret;
4806 unsigned long cons, tmp, tmp2, prod;
4807
4808 /*
4809 * Direct
4810 */
4811 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4812
4813 output[outlen] = 0;
4814 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4815
4816 /*
4817 * output chunking
4818 */
4819 cons = 0;
4820 prod = 0;
4821 while (cons < inlen) {
4822 tmp = 5;
4823 tmp2 = inlen - cons;
4824
4825 printf("%ld %ld\n", cons, prod);
4826 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4827 cons += tmp2;
4828 prod += tmp;
4829 printf("%ld %ld\n", cons, prod);
4830 }
4831 output2[outlen] = 0;
4832 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4833
4834 /*
4835 * input chunking
4836 */
4837 cons = 0;
4838 prod = 0;
4839 while (cons < inlen) {
4840 tmp = 100 - prod;
4841 tmp2 = inlen - cons;
4842 if (tmp2 > 5)
4843 tmp2 = 5;
4844
4845 printf("%ld %ld\n", cons, prod);
4846 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4847 cons += tmp2;
4848 prod += tmp;
4849 printf("%ld %ld\n", cons, prod);
4850 }
4851 output3[outlen] = 0;
4852 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4853 return(0);
4854
4855}
4856#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004857#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004858#endif /* LIBXML_READER_ENABLED */