blob: 8a533a2892ac5a8960f44171c2d28491d1a3afb9 [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 Veillardf54cd532004-02-25 11:52:31 +0000880#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000881 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
882 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
883 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
884 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
885 reader->ctxt->myDoc, node, node->name);
886 } else {
887 /* TODO use the BuildQName interface */
888 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000889
Daniel Veillardf4e55762003-04-15 23:32:22 +0000890 qname = xmlStrdup(node->ns->prefix);
891 qname = xmlStrcat(qname, BAD_CAST ":");
892 qname = xmlStrcat(qname, node->name);
893 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
894 reader->ctxt->myDoc, node, qname);
895 if (qname != NULL)
896 xmlFree(qname);
897 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000898 }
899#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000900#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000901 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000902 (reader->rngValidCtxt != NULL)) {
903 int ret;
904
905 if (reader->rngFullNode != NULL) return;
906 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
907 reader->ctxt->myDoc,
908 node);
909 if (ret == 0) {
910 /*
911 * this element requires a full tree
912 */
913 node = xmlTextReaderExpand(reader);
914 if (node == NULL) {
915printf("Expand failed !\n");
916 ret = -1;
917 } else {
918 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
919 reader->ctxt->myDoc,
920 node);
921 reader->rngFullNode = node;
922 }
923 }
924 if (ret != 1)
925 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000926 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000927#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000928}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000929
930/**
931 * xmlTextReaderValidateCData:
932 * @reader: the xmlTextReaderPtr used
933 * @data: pointer to the CData
934 * @len: lenght of the CData block in bytes.
935 *
936 * Push some CData for validation
937 */
938static void
939xmlTextReaderValidateCData(xmlTextReaderPtr reader,
940 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000941#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000942 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
943 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
944 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
945 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000946 }
947#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000948#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000949 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000950 (reader->rngValidCtxt != NULL)) {
951 int ret;
952
953 if (reader->rngFullNode != NULL) return;
954 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
955 if (ret != 1)
956 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +0000957 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000958#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +0000959}
960
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000961/**
962 * xmlTextReaderValidatePop:
963 * @reader: the xmlTextReaderPtr used
964 *
965 * Pop the current node from validation
966 */
967static void
968xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
969 xmlNodePtr node = reader->node;
970
Daniel Veillardf54cd532004-02-25 11:52:31 +0000971#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000972 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
973 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
974 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
975 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
976 reader->ctxt->myDoc, node, node->name);
977 } else {
978 /* TODO use the BuildQName interface */
979 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000980
Daniel Veillardf4e55762003-04-15 23:32:22 +0000981 qname = xmlStrdup(node->ns->prefix);
982 qname = xmlStrcat(qname, BAD_CAST ":");
983 qname = xmlStrcat(qname, node->name);
984 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
985 reader->ctxt->myDoc, node, qname);
986 if (qname != NULL)
987 xmlFree(qname);
988 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000989 }
990#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000991#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000992 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000993 (reader->rngValidCtxt != NULL)) {
994 int ret;
995
996 if (reader->rngFullNode != NULL) {
997 if (node == reader->rngFullNode)
998 reader->rngFullNode = NULL;
999 return;
1000 }
1001 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1002 reader->ctxt->myDoc,
1003 node);
1004 if (ret != 1)
1005 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001006 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001007#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001008}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001009
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001010/**
1011 * xmlTextReaderValidateEntity:
1012 * @reader: the xmlTextReaderPtr used
1013 *
1014 * Handle the validation when an entity reference is encountered and
1015 * entity substitution is not activated. As a result the parser interface
1016 * must walk through the entity and do the validation calls
1017 */
1018static void
1019xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1020 xmlNodePtr oldnode = reader->node;
1021 xmlNodePtr node = reader->node;
1022 xmlParserCtxtPtr ctxt = reader->ctxt;
1023
1024 do {
1025 if (node->type == XML_ENTITY_REF_NODE) {
1026 /*
1027 * Case where the underlying tree is not availble, lookup the entity
1028 * and walk it.
1029 */
1030 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1031 (ctxt->sax->getEntity != NULL)) {
1032 node->children = (xmlNodePtr)
1033 ctxt->sax->getEntity(ctxt, node->name);
1034 }
1035
1036 if ((node->children != NULL) &&
1037 (node->children->type == XML_ENTITY_DECL) &&
1038 (node->children->children != NULL)) {
1039 xmlTextReaderEntPush(reader, node);
1040 node = node->children->children;
1041 continue;
1042 } else {
1043 /*
1044 * The error has probably be raised already.
1045 */
1046 if (node == oldnode)
1047 break;
1048 node = node->next;
1049 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001050#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001051 } else if (node->type == XML_ELEMENT_NODE) {
1052 reader->node = node;
1053 xmlTextReaderValidatePush(reader);
1054 } else if ((node->type == XML_TEXT_NODE) ||
1055 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001056 xmlTextReaderValidateCData(reader, node->content,
1057 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001058#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001059 }
1060
1061 /*
1062 * go to next node
1063 */
1064 if (node->children != NULL) {
1065 node = node->children;
1066 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001067 } else if (node->type == XML_ELEMENT_NODE) {
1068 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001069 }
1070 if (node->next != NULL) {
1071 node = node->next;
1072 continue;
1073 }
1074 do {
1075 node = node->parent;
1076 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001077 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001078 if (reader->entNr == 0) {
1079 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001080 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001081 xmlUnlinkNode(tmp);
1082 xmlTextReaderFreeNode(reader, tmp);
1083 } else
1084 break;
1085 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001086 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001087 reader->node = node;
1088 xmlTextReaderValidatePop(reader);
1089 }
1090 if ((node->type == XML_ENTITY_DECL) &&
1091 (reader->ent != NULL) && (reader->ent->children == node)) {
1092 node = xmlTextReaderEntPop(reader);
1093 }
1094 if (node == oldnode)
1095 break;
1096 if (node->next != NULL) {
1097 node = node->next;
1098 break;
1099 }
1100 } while ((node != NULL) && (node != oldnode));
1101 } while ((node != NULL) && (node != oldnode));
1102 reader->node = oldnode;
1103}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001104#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001105
1106
1107/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001108 * xmlTextReaderGetSuccessor:
1109 * @cur: the current node
1110 *
1111 * Get the successor of a node if available.
1112 *
1113 * Returns the successor node or NULL
1114 */
1115static xmlNodePtr
1116xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1117 if (cur == NULL) return(NULL) ; /* ERROR */
1118 if (cur->next != NULL) return(cur->next) ;
1119 do {
1120 cur = cur->parent;
1121 if (cur == NULL) return(NULL);
1122 if (cur->next != NULL) return(cur->next);
1123 } while (cur != NULL);
1124 return(cur);
1125}
1126
1127/**
1128 * xmlTextReaderDoExpand:
1129 * @reader: the xmlTextReaderPtr used
1130 *
1131 * Makes sure that the current node is fully read as well as all its
1132 * descendant. It means the full DOM subtree must be available at the
1133 * end of the call.
1134 *
1135 * Returns 1 if the node was expanded successfully, 0 if there is no more
1136 * nodes to read, or -1 in case of error
1137 */
1138static int
1139xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1140 int val;
1141
1142 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1143 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001144 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001145 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1146
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001147 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1148 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001149 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001150 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001151 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1152 return(1);
1153 val = xmlTextReaderPushData(reader);
1154 if (val < 0)
1155 return(-1);
1156 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1157 return(1);
1158}
1159
1160/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001161 * xmlTextReaderRead:
1162 * @reader: the xmlTextReaderPtr used
1163 *
1164 * Moves the position of the current instance to the next node in
1165 * the stream, exposing its properties.
1166 *
1167 * Returns 1 if the node was read successfully, 0 if there is no more
1168 * nodes to read, or -1 in case of error
1169 */
1170int
1171xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001172 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001173 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001174 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001175
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001176
1177 if (reader == NULL)
1178 return(-1);
1179 if (reader->doc != NULL)
1180 return(xmlTextReaderReadTree(reader));
1181 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001182 return(-1);
1183 if (reader->ctxt->wellFormed != 1)
1184 return(-1);
1185
1186#ifdef DEBUG_READER
1187 fprintf(stderr, "\nREAD ");
1188 DUMP_READER
1189#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001190 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001191 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1192 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001193 /*
1194 * Initial state
1195 */
1196 do {
1197 val = xmlTextReaderPushData(reader);
1198 if (val < 0)
1199 return(-1);
1200 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001201 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1202 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001203 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001204 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001205 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001206 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001207 if (reader->node == NULL)
1208 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001209 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001210 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001211 if (reader->ctxt->myDoc != NULL) {
1212 reader->node = reader->ctxt->myDoc->children;
1213 }
1214 if (reader->node == NULL)
1215 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001216 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001217 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001218 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001219 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001220 }
1221 oldstate = reader->state;
1222 olddepth = reader->ctxt->nodeNr;
1223 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001224
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001225get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001226 /*
1227 * If we are not backtracking on ancestors or examined nodes,
1228 * that the parser didn't finished or that we arent at the end
1229 * of stream, continue processing.
1230 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001231 while ((reader->node->next == NULL) &&
1232 (reader->ctxt->nodeNr == olddepth) &&
1233 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001234 (reader->node->children == NULL) ||
1235 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001236 ((reader->node->children != NULL) &&
1237 (reader->node->children->type == XML_TEXT_NODE) &&
1238 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001239 (reader->node->type == XML_DTD_NODE) ||
1240 (reader->node->type == XML_DOCUMENT_NODE) ||
1241 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001242 ((reader->ctxt->node == NULL) ||
1243 (reader->ctxt->node == reader->node) ||
1244 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001245 (reader->ctxt->instate != XML_PARSER_EOF)) {
1246 val = xmlTextReaderPushData(reader);
1247 if (val < 0)
1248 return(-1);
1249 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001250 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001251 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001252 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001253 if ((reader->node->children != NULL) &&
1254 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001255 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001256 (reader->node->type != XML_DTD_NODE)) {
1257 reader->node = reader->node->children;
1258 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001259 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001260 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001261 }
1262 }
1263 if (reader->node->next != NULL) {
1264 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001265 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001266 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001267 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1268#ifdef LIBXML_XINCLUDE_ENABLED
1269 && (reader->in_xinclude <= 0)
1270#endif
1271 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001273 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001274 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001275#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001276 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001277 (reader->node->type == XML_ELEMENT_NODE))
1278 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001279#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001280 if ((reader->preserves > 0) &&
1281 (reader->node->extra & NODE_IS_SPRESERVED))
1282 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001283 reader->node = reader->node->next;
1284 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001285
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001286 /*
1287 * Cleanup of the old node
1288 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001289 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001290#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001291 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001292#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001293 (reader->entNr == 0) &&
1294 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001295 (reader->node->prev->type != XML_DTD_NODE) &&
1296 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001297 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001298 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001299 xmlUnlinkNode(tmp);
1300 xmlTextReaderFreeNode(reader, tmp);
1301 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001302 }
1303
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001304 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001305 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001306 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001307 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001308 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001309 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001310 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001311 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001312 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001313#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001314 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001315 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001316#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001317 if ((reader->preserves > 0) &&
1318 (reader->node->extra & NODE_IS_SPRESERVED))
1319 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001320 reader->node = reader->node->parent;
1321 if ((reader->node == NULL) ||
1322 (reader->node->type == XML_DOCUMENT_NODE) ||
1323#ifdef LIBXML_DOCB_ENABLED
1324 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1325#endif
1326 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001327 if (reader->mode != XML_TEXTREADER_DONE) {
1328 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1329 reader->mode = XML_TEXTREADER_DONE;
1330 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001332 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001333
1334 /*
1335 * Cleanup of the old node
1336 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001337 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001338#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001339 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001340#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001341 (reader->entNr == 0) &&
1342 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001343 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001344 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001345 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001346 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001347 }
1348
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001349 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001350 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001351 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001352#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001353 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001354#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001355 (reader->entNr == 0) &&
1356 (reader->node->last != NULL) &&
1357 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1358 xmlNodePtr tmp = reader->node->last;
1359 xmlUnlinkNode(tmp);
1360 xmlTextReaderFreeNode(reader, tmp);
1361 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001362 reader->depth--;
1363 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001364
1365node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001366 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001367
1368 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001369 * If we are in the middle of a piece of CDATA make sure it's finished
1370 */
1371 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001372 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001373 ((reader->node->type == XML_TEXT_NODE) ||
1374 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1375 xmlTextReaderExpand(reader);
1376 }
1377
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001378#ifdef LIBXML_XINCLUDE_ENABLED
1379 /*
1380 * Handle XInclude if asked for
1381 */
1382 if ((reader->xinclude) && (reader->node != NULL) &&
1383 (reader->node->type == XML_ELEMENT_NODE) &&
1384 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001385 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1386 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001387 if (reader->xincctxt == NULL) {
1388 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001389 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001390 }
1391 /*
1392 * expand that node and process it
1393 */
1394 xmlTextReaderExpand(reader);
1395 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1396 }
1397 if (reader->node->type == XML_XINCLUDE_START) {
1398 reader->in_xinclude++;
1399 goto get_next_node;
1400 }
1401 if (reader->node->type == XML_XINCLUDE_END) {
1402 reader->in_xinclude--;
1403 goto get_next_node;
1404 }
1405#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001406 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001407 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001408 */
1409 if ((reader->node != NULL) &&
1410 (reader->node->type == XML_ENTITY_REF_NODE) &&
1411 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1412 /*
1413 * Case where the underlying tree is not availble, lookup the entity
1414 * and walk it.
1415 */
1416 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1417 (reader->ctxt->sax->getEntity != NULL)) {
1418 reader->node->children = (xmlNodePtr)
1419 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1420 }
1421
1422 if ((reader->node->children != NULL) &&
1423 (reader->node->children->type == XML_ENTITY_DECL) &&
1424 (reader->node->children->children != NULL)) {
1425 xmlTextReaderEntPush(reader, reader->node);
1426 reader->node = reader->node->children->children;
1427 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001428#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001429 } else if ((reader->node != NULL) &&
1430 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001431 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001432 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001433#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001434 }
1435 if ((reader->node != NULL) &&
1436 (reader->node->type == XML_ENTITY_DECL) &&
1437 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1438 reader->node = xmlTextReaderEntPop(reader);
1439 reader->depth++;
1440 goto get_next_node;
1441 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001442#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001443 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001444 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001445
1446 if ((node->type == XML_ELEMENT_NODE) &&
1447 ((reader->state != XML_TEXTREADER_END) &&
1448 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1449 xmlTextReaderValidatePush(reader);
1450 } else if ((node->type == XML_TEXT_NODE) ||
1451 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001452 xmlTextReaderValidateCData(reader, node->content,
1453 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001454 }
1455 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001456#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001457#ifdef LIBXML_PATTERN_ENABLED
1458 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1459 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1460 int i;
1461 for (i = 0;i < reader->patternNr;i++) {
1462 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1463 xmlTextReaderPreserve(reader);
1464 break;
1465 }
1466 }
1467 }
1468#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001469 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001470node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001471 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001472 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001473}
1474
Daniel Veillard67df8092002-12-16 22:04:11 +00001475/**
1476 * xmlTextReaderReadState:
1477 * @reader: the xmlTextReaderPtr used
1478 *
1479 * Gets the read state of the reader.
1480 *
1481 * Returns the state value, or -1 in case of error
1482 */
1483int
1484xmlTextReaderReadState(xmlTextReaderPtr reader) {
1485 if (reader == NULL)
1486 return(-1);
1487 return(reader->mode);
1488}
1489
1490/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001491 * xmlTextReaderExpand:
1492 * @reader: the xmlTextReaderPtr used
1493 *
1494 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001495 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001496 *
1497 * Returns a node pointer valid until the next xmlTextReaderRead() call
1498 * or NULL in case of error.
1499 */
1500xmlNodePtr
1501xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001502 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001503 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001504 if (reader->doc != NULL)
1505 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001506 if (reader->ctxt == NULL)
1507 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001508 if (xmlTextReaderDoExpand(reader) < 0)
1509 return(NULL);
1510 return(reader->node);
1511}
1512
1513/**
1514 * xmlTextReaderNext:
1515 * @reader: the xmlTextReaderPtr used
1516 *
1517 * Skip to the node following the current one in document order while
1518 * avoiding the subtree if any.
1519 *
1520 * Returns 1 if the node was read successfully, 0 if there is no more
1521 * nodes to read, or -1 in case of error
1522 */
1523int
1524xmlTextReaderNext(xmlTextReaderPtr reader) {
1525 int ret;
1526 xmlNodePtr cur;
1527
1528 if (reader == NULL)
1529 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001530 if (reader->doc != NULL)
1531 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001532 cur = reader->node;
1533 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1534 return(xmlTextReaderRead(reader));
1535 if (reader->state == XML_TEXTREADER_END)
1536 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001537 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001538 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001539 do {
1540 ret = xmlTextReaderRead(reader);
1541 if (ret != 1)
1542 return(ret);
1543 } while (reader->node != cur);
1544 return(xmlTextReaderRead(reader));
1545}
1546
1547/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001548 * xmlTextReaderReadInnerXml:
1549 * @reader: the xmlTextReaderPtr used
1550 *
1551 * Reads the contents of the current node, including child nodes and markup.
1552 *
1553 * Returns a string containing the XML content, or NULL if the current node
1554 * is neither an element nor attribute, or has no child nodes. The
1555 * string must be deallocated by the caller.
1556 */
1557xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001558xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001559 TODO
1560 return(NULL);
1561}
1562
1563/**
1564 * xmlTextReaderReadOuterXml:
1565 * @reader: the xmlTextReaderPtr used
1566 *
1567 * Reads the contents of the current node, including child nodes and markup.
1568 *
1569 * Returns a string containing the XML content, or NULL if the current node
1570 * is neither an element nor attribute, or has no child nodes. The
1571 * string must be deallocated by the caller.
1572 */
1573xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001574xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001575 TODO
1576 return(NULL);
1577}
1578
1579/**
1580 * xmlTextReaderReadString:
1581 * @reader: the xmlTextReaderPtr used
1582 *
1583 * Reads the contents of an element or a text node as a string.
1584 *
1585 * Returns a string containing the contents of the Element or Text node,
1586 * or NULL if the reader is positioned on any other type of node.
1587 * The string must be deallocated by the caller.
1588 */
1589xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001590xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001591 TODO
1592 return(NULL);
1593}
1594
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001595#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001596/**
1597 * xmlTextReaderReadBase64:
1598 * @reader: the xmlTextReaderPtr used
1599 * @array: a byte array to store the content.
1600 * @offset: the zero-based index into array where the method should
1601 * begin to write.
1602 * @len: the number of bytes to write.
1603 *
1604 * Reads and decodes the Base64 encoded contents of an element and
1605 * stores the result in a byte buffer.
1606 *
1607 * Returns the number of bytes written to array, or zero if the current
1608 * instance is not positioned on an element or -1 in case of error.
1609 */
1610int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001611xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1612 unsigned char *array ATTRIBUTE_UNUSED,
1613 int offset ATTRIBUTE_UNUSED,
1614 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001615 if ((reader == NULL) || (reader->ctxt == NULL))
1616 return(-1);
1617 if (reader->ctxt->wellFormed != 1)
1618 return(-1);
1619
1620 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1621 return(0);
1622 TODO
1623 return(0);
1624}
1625
1626/**
1627 * xmlTextReaderReadBinHex:
1628 * @reader: the xmlTextReaderPtr used
1629 * @array: a byte array to store the content.
1630 * @offset: the zero-based index into array where the method should
1631 * begin to write.
1632 * @len: the number of bytes to write.
1633 *
1634 * Reads and decodes the BinHex encoded contents of an element and
1635 * stores the result in a byte buffer.
1636 *
1637 * Returns the number of bytes written to array, or zero if the current
1638 * instance is not positioned on an element or -1 in case of error.
1639 */
1640int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001641xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1642 unsigned char *array ATTRIBUTE_UNUSED,
1643 int offset ATTRIBUTE_UNUSED,
1644 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001645 if ((reader == NULL) || (reader->ctxt == NULL))
1646 return(-1);
1647 if (reader->ctxt->wellFormed != 1)
1648 return(-1);
1649
1650 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1651 return(0);
1652 TODO
1653 return(0);
1654}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001655#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001656
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001657/************************************************************************
1658 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001659 * Operating on a preparsed tree *
1660 * *
1661 ************************************************************************/
1662static int
1663xmlTextReaderNextTree(xmlTextReaderPtr reader)
1664{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001665 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001666 return(-1);
1667
1668 if (reader->state == XML_TEXTREADER_END)
1669 return(0);
1670
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001671 if (reader->node == NULL) {
1672 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001673 reader->state = XML_TEXTREADER_END;
1674 return(0);
1675 }
1676
1677 reader->node = reader->doc->children;
1678 reader->state = XML_TEXTREADER_START;
1679 return(1);
1680 }
1681
1682 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1683 if (reader->node->children != 0) {
1684 reader->node = reader->node->children;
1685 reader->depth++;
1686 reader->state = XML_TEXTREADER_START;
1687 return(1);
1688 }
1689
1690 if ((reader->node->type == XML_ELEMENT_NODE) ||
1691 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1692 reader->state = XML_TEXTREADER_BACKTRACK;
1693 return(1);
1694 }
1695 }
1696
1697 if (reader->node->next != 0) {
1698 reader->node = reader->node->next;
1699 reader->state = XML_TEXTREADER_START;
1700 return(1);
1701 }
1702
1703 if (reader->node->parent != 0) {
1704 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1705 reader->state = XML_TEXTREADER_END;
1706 return(0);
1707 }
1708
1709 reader->node = reader->node->parent;
1710 reader->depth--;
1711 reader->state = XML_TEXTREADER_BACKTRACK;
1712 return(1);
1713 }
1714
1715 reader->state = XML_TEXTREADER_END;
1716
1717 return(1);
1718}
1719
1720/**
1721 * xmlTextReaderReadTree:
1722 * @reader: the xmlTextReaderPtr used
1723 *
1724 * Moves the position of the current instance to the next node in
1725 * the stream, exposing its properties.
1726 *
1727 * Returns 1 if the node was read successfully, 0 if there is no more
1728 * nodes to read, or -1 in case of error
1729 */
1730static int
1731xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1732 if (reader->state == XML_TEXTREADER_END)
1733 return(0);
1734
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001735next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001736 if (reader->node == NULL) {
1737 if (reader->doc->children == NULL) {
1738 reader->state = XML_TEXTREADER_END;
1739 return(0);
1740 }
1741
1742 reader->node = reader->doc->children;
1743 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001744 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001745 }
1746
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001747 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1748 (reader->node->type != XML_DTD_NODE) &&
1749 (reader->node->type != XML_XINCLUDE_START) &&
1750 (reader->node->type != XML_ENTITY_REF_NODE)) {
1751 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001752 reader->node = reader->node->children;
1753 reader->depth++;
1754 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001755 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001756 }
1757
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001758 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001759 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001760 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001761 }
1762 }
1763
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001764 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001765 reader->node = reader->node->next;
1766 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001767 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001768 }
1769
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001770 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001771 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1772 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1773 reader->state = XML_TEXTREADER_END;
1774 return(0);
1775 }
1776
1777 reader->node = reader->node->parent;
1778 reader->depth--;
1779 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001780 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001781 }
1782
1783 reader->state = XML_TEXTREADER_END;
1784
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001785found_node:
1786 if ((reader->node->type == XML_XINCLUDE_START) ||
1787 (reader->node->type == XML_XINCLUDE_END))
1788 goto next_node;
1789
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001790 return(1);
1791}
1792
1793/**
William M. Brackb1d53162003-11-18 06:54:40 +00001794 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001795 * @reader: the xmlTextReaderPtr used
1796 *
1797 * Skip to the node following the current one in document order while
1798 * avoiding the subtree if any.
1799 * Currently implemented only for Readers built on a document
1800 *
1801 * Returns 1 if the node was read successfully, 0 if there is no more
1802 * nodes to read, or -1 in case of error
1803 */
1804int
1805xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1806 if (reader == NULL)
1807 return(-1);
1808 if (reader->doc == NULL) {
1809 TODO
1810 return(-1);
1811 }
1812
1813 if (reader->state == XML_TEXTREADER_END)
1814 return(0);
1815
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001816 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001817 return(xmlTextReaderNextTree(reader));
1818
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001819 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001820 reader->node = reader->node->next;
1821 reader->state = XML_TEXTREADER_START;
1822 return(1);
1823 }
1824
1825 return(0);
1826}
1827
1828/************************************************************************
1829 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001830 * Constructor and destructors *
1831 * *
1832 ************************************************************************/
1833/**
1834 * xmlNewTextReader:
1835 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001836 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001837 *
1838 * Create an xmlTextReader structure fed with @input
1839 *
1840 * Returns the new xmlTextReaderPtr or NULL in case of error
1841 */
1842xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001843xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001844 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001845
1846 if (input == NULL)
1847 return(NULL);
1848 ret = xmlMalloc(sizeof(xmlTextReader));
1849 if (ret == NULL) {
1850 xmlGenericError(xmlGenericErrorContext,
1851 "xmlNewTextReader : malloc failed\n");
1852 return(NULL);
1853 }
1854 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001855 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001856 ret->entTab = NULL;
1857 ret->entMax = 0;
1858 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001859 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001860 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001861 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1862 if (ret->sax == NULL) {
1863 xmlFree(ret);
1864 xmlGenericError(xmlGenericErrorContext,
1865 "xmlNewTextReader : malloc failed\n");
1866 return(NULL);
1867 }
Daniel Veillard81273902003-09-30 00:43:48 +00001868 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001869 ret->startElement = ret->sax->startElement;
1870 ret->sax->startElement = xmlTextReaderStartElement;
1871 ret->endElement = ret->sax->endElement;
1872 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001873#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001874 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001875#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001876 ret->startElementNs = ret->sax->startElementNs;
1877 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1878 ret->endElementNs = ret->sax->endElementNs;
1879 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001880#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001881 } else {
1882 ret->startElementNs = NULL;
1883 ret->endElementNs = NULL;
1884 }
Daniel Veillard81273902003-09-30 00:43:48 +00001885#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001886 ret->characters = ret->sax->characters;
1887 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001888 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001889 ret->cdataBlock = ret->sax->cdataBlock;
1890 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001891
Daniel Veillard67df8092002-12-16 22:04:11 +00001892 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001893 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001894 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001895 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001896 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001897 }
1898 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001899 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001900 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001901 ret->base = 0;
1902 ret->cur = 4;
1903 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001904 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001905 ret->base = 0;
1906 ret->cur = 0;
1907 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001908 if (ret->ctxt == NULL) {
1909 xmlGenericError(xmlGenericErrorContext,
1910 "xmlNewTextReader : malloc failed\n");
1911 xmlFree(ret->sax);
1912 xmlFree(ret);
1913 return(NULL);
1914 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001915 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001916 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001917 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001918 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001919 /*
1920 * use the parser dictionnary to allocate all elements and attributes names
1921 */
1922 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001923 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001924#ifdef LIBXML_XINCLUDE_ENABLED
1925 ret->xinclude = 0;
1926#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001927#ifdef LIBXML_PATTERN_ENABLED
1928 ret->patternMax = 0;
1929 ret->patternTab = NULL;
1930#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001931 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001932}
1933
1934/**
1935 * xmlNewTextReaderFilename:
1936 * @URI: the URI of the resource to process
1937 *
1938 * Create an xmlTextReader structure fed with the resource at @URI
1939 *
1940 * Returns the new xmlTextReaderPtr or NULL in case of error
1941 */
1942xmlTextReaderPtr
1943xmlNewTextReaderFilename(const char *URI) {
1944 xmlParserInputBufferPtr input;
1945 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001946 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001947
1948 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1949 if (input == NULL)
1950 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001951 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001952 if (ret == NULL) {
1953 xmlFreeParserInputBuffer(input);
1954 return(NULL);
1955 }
1956 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001957 if (ret->ctxt->directory == NULL)
1958 directory = xmlParserGetDirectory(URI);
1959 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1960 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1961 if (directory != NULL)
1962 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001963 return(ret);
1964}
1965
1966/**
1967 * xmlFreeTextReader:
1968 * @reader: the xmlTextReaderPtr
1969 *
1970 * Deallocate all the resources associated to the reader
1971 */
1972void
1973xmlFreeTextReader(xmlTextReaderPtr reader) {
1974 if (reader == NULL)
1975 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001976#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001977 if (reader->rngSchemas != NULL) {
1978 xmlRelaxNGFree(reader->rngSchemas);
1979 reader->rngSchemas = NULL;
1980 }
1981 if (reader->rngValidCtxt != NULL) {
1982 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1983 reader->rngValidCtxt = NULL;
1984 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001985#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001986#ifdef LIBXML_XINCLUDE_ENABLED
1987 if (reader->xincctxt != NULL)
1988 xmlXIncludeFreeContext(reader->xincctxt);
1989#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001990#ifdef LIBXML_PATTERN_ENABLED
1991 if (reader->patternTab != NULL) {
1992 int i;
1993 for (i = 0;i < reader->patternNr;i++) {
1994 if (reader->patternTab[i] != NULL)
1995 xmlFreePattern(reader->patternTab[i]);
1996 }
1997 xmlFree(reader->patternTab);
1998 }
1999#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002000 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002001 if (reader->dict == reader->ctxt->dict)
2002 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002003 if (reader->ctxt->myDoc != NULL) {
2004 if (reader->preserve == 0)
2005 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2006 reader->ctxt->myDoc = NULL;
2007 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002008 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2009 (reader->ctxt->vctxt.vstateMax > 0)){
2010 xmlFree(reader->ctxt->vctxt.vstateTab);
2011 reader->ctxt->vctxt.vstateTab = 0;
2012 reader->ctxt->vctxt.vstateMax = 0;
2013 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002014 if (reader->allocs & XML_TEXTREADER_CTXT)
2015 xmlFreeParserCtxt(reader->ctxt);
2016 }
2017 if (reader->sax != NULL)
2018 xmlFree(reader->sax);
2019 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2020 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002021 if (reader->faketext != NULL) {
2022 xmlFreeNode(reader->faketext);
2023 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002024 if (reader->buffer != NULL)
2025 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002026 if (reader->entTab != NULL)
2027 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002028 if (reader->dict != NULL)
2029 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002030 xmlFree(reader);
2031}
2032
2033/************************************************************************
2034 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002035 * Methods for XmlTextReader *
2036 * *
2037 ************************************************************************/
2038/**
2039 * xmlTextReaderClose:
2040 * @reader: the xmlTextReaderPtr used
2041 *
2042 * This method releases any resources allocated by the current instance
2043 * changes the state to Closed and close any underlying input.
2044 *
2045 * Returns 0 or -1 in case of error
2046 */
2047int
2048xmlTextReaderClose(xmlTextReaderPtr reader) {
2049 if (reader == NULL)
2050 return(-1);
2051 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002052 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002053 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2054 if (reader->ctxt != NULL) {
2055 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002056 if (reader->preserve == 0)
2057 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002058 reader->ctxt->myDoc = NULL;
2059 }
2060 if (reader->allocs & XML_TEXTREADER_CTXT) {
2061 xmlFreeParserCtxt(reader->ctxt);
2062 reader->allocs -= XML_TEXTREADER_CTXT;
2063 }
2064 }
2065 if (reader->sax != NULL) {
2066 xmlFree(reader->sax);
2067 reader->sax = NULL;
2068 }
2069 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2070 xmlFreeParserInputBuffer(reader->input);
2071 reader->allocs -= XML_TEXTREADER_INPUT;
2072 }
2073 return(0);
2074}
2075
2076/**
2077 * xmlTextReaderGetAttributeNo:
2078 * @reader: the xmlTextReaderPtr used
2079 * @no: the zero-based index of the attribute relative to the containing element
2080 *
2081 * Provides the value of the attribute with the specified index relative
2082 * to the containing element.
2083 *
2084 * Returns a string containing the value of the specified attribute, or NULL
2085 * in case of error. The string must be deallocated by the caller.
2086 */
2087xmlChar *
2088xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2089 xmlChar *ret;
2090 int i;
2091 xmlAttrPtr cur;
2092 xmlNsPtr ns;
2093
2094 if (reader == NULL)
2095 return(NULL);
2096 if (reader->node == NULL)
2097 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002098 if (reader->curnode != NULL)
2099 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002100 /* TODO: handle the xmlDecl */
2101 if (reader->node->type != XML_ELEMENT_NODE)
2102 return(NULL);
2103
2104 ns = reader->node->nsDef;
2105 for (i = 0;(i < no) && (ns != NULL);i++) {
2106 ns = ns->next;
2107 }
2108 if (ns != NULL)
2109 return(xmlStrdup(ns->href));
2110
2111 cur = reader->node->properties;
2112 if (cur == NULL)
2113 return(NULL);
2114 for (;i < no;i++) {
2115 cur = cur->next;
2116 if (cur == NULL)
2117 return(NULL);
2118 }
2119 /* TODO walk the DTD if present */
2120
2121 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2122 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2123 return(ret);
2124}
2125
2126/**
2127 * xmlTextReaderGetAttribute:
2128 * @reader: the xmlTextReaderPtr used
2129 * @name: the qualified name of the attribute.
2130 *
2131 * Provides the value of the attribute with the specified qualified name.
2132 *
2133 * Returns a string containing the value of the specified attribute, or NULL
2134 * in case of error. The string must be deallocated by the caller.
2135 */
2136xmlChar *
2137xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2138 xmlChar *prefix = NULL;
2139 xmlChar *localname;
2140 xmlNsPtr ns;
2141 xmlChar *ret = NULL;
2142
2143 if ((reader == NULL) || (name == NULL))
2144 return(NULL);
2145 if (reader->node == NULL)
2146 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002147 if (reader->curnode != NULL)
2148 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002149
2150 /* TODO: handle the xmlDecl */
2151 if (reader->node->type != XML_ELEMENT_NODE)
2152 return(NULL);
2153
2154 localname = xmlSplitQName2(name, &prefix);
2155 if (localname == NULL)
2156 return(xmlGetProp(reader->node, name));
2157
2158 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2159 if (ns != NULL)
2160 ret = xmlGetNsProp(reader->node, localname, ns->href);
2161
2162 if (localname != NULL)
2163 xmlFree(localname);
2164 if (prefix != NULL)
2165 xmlFree(prefix);
2166 return(ret);
2167}
2168
2169
2170/**
2171 * xmlTextReaderGetAttributeNs:
2172 * @reader: the xmlTextReaderPtr used
2173 * @localName: the local name of the attribute.
2174 * @namespaceURI: the namespace URI of the attribute.
2175 *
2176 * Provides the value of the specified attribute
2177 *
2178 * Returns a string containing the value of the specified attribute, or NULL
2179 * in case of error. The string must be deallocated by the caller.
2180 */
2181xmlChar *
2182xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2183 const xmlChar *namespaceURI) {
2184 if ((reader == NULL) || (localName == NULL))
2185 return(NULL);
2186 if (reader->node == NULL)
2187 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002188 if (reader->curnode != NULL)
2189 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002190
2191 /* TODO: handle the xmlDecl */
2192 if (reader->node->type != XML_ELEMENT_NODE)
2193 return(NULL);
2194
2195 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2196}
2197
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002198/**
2199 * xmlTextReaderGetRemainder:
2200 * @reader: the xmlTextReaderPtr used
2201 *
2202 * Method to get the remainder of the buffered XML. this method stops the
2203 * parser, set its state to End Of File and return the input stream with
2204 * what is left that the parser did not use.
2205 *
2206 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2207 * in case of error.
2208 */
2209xmlParserInputBufferPtr
2210xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2211 xmlParserInputBufferPtr ret = NULL;
2212
2213 if (reader == NULL)
2214 return(NULL);
2215 if (reader->node == NULL)
2216 return(NULL);
2217
2218 reader->node = NULL;
2219 reader->curnode = NULL;
2220 reader->mode = XML_TEXTREADER_MODE_EOF;
2221 if (reader->ctxt != NULL) {
2222 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002223 if (reader->preserve == 0)
2224 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002225 reader->ctxt->myDoc = NULL;
2226 }
2227 if (reader->allocs & XML_TEXTREADER_CTXT) {
2228 xmlFreeParserCtxt(reader->ctxt);
2229 reader->allocs -= XML_TEXTREADER_CTXT;
2230 }
2231 }
2232 if (reader->sax != NULL) {
2233 xmlFree(reader->sax);
2234 reader->sax = NULL;
2235 }
2236 if (reader->allocs & XML_TEXTREADER_INPUT) {
2237 ret = reader->input;
2238 reader->allocs -= XML_TEXTREADER_INPUT;
2239 } else {
2240 /*
2241 * Hum, one may need to duplicate the data structure because
2242 * without reference counting the input may be freed twice:
2243 * - by the layer which allocated it.
2244 * - by the layer to which would have been returned to.
2245 */
2246 TODO
2247 return(NULL);
2248 }
2249 return(ret);
2250}
2251
2252/**
2253 * xmlTextReaderLookupNamespace:
2254 * @reader: the xmlTextReaderPtr used
2255 * @prefix: the prefix whose namespace URI is to be resolved. To return
2256 * the default namespace, specify NULL
2257 *
2258 * Resolves a namespace prefix in the scope of the current element.
2259 *
2260 * Returns a string containing the namespace URI to which the prefix maps
2261 * or NULL in case of error. The string must be deallocated by the caller.
2262 */
2263xmlChar *
2264xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2265 xmlNsPtr ns;
2266
2267 if (reader == NULL)
2268 return(NULL);
2269 if (reader->node == NULL)
2270 return(NULL);
2271
2272 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2273 if (ns == NULL)
2274 return(NULL);
2275 return(xmlStrdup(ns->href));
2276}
2277
2278/**
2279 * xmlTextReaderMoveToAttributeNo:
2280 * @reader: the xmlTextReaderPtr used
2281 * @no: the zero-based index of the attribute relative to the containing
2282 * element.
2283 *
2284 * Moves the position of the current instance to the attribute with
2285 * the specified index relative to the containing element.
2286 *
2287 * Returns 1 in case of success, -1 in case of error, 0 if not found
2288 */
2289int
2290xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2291 int i;
2292 xmlAttrPtr cur;
2293 xmlNsPtr ns;
2294
2295 if (reader == NULL)
2296 return(-1);
2297 if (reader->node == NULL)
2298 return(-1);
2299 /* TODO: handle the xmlDecl */
2300 if (reader->node->type != XML_ELEMENT_NODE)
2301 return(-1);
2302
2303 reader->curnode = NULL;
2304
2305 ns = reader->node->nsDef;
2306 for (i = 0;(i < no) && (ns != NULL);i++) {
2307 ns = ns->next;
2308 }
2309 if (ns != NULL) {
2310 reader->curnode = (xmlNodePtr) ns;
2311 return(1);
2312 }
2313
2314 cur = reader->node->properties;
2315 if (cur == NULL)
2316 return(0);
2317 for (;i < no;i++) {
2318 cur = cur->next;
2319 if (cur == NULL)
2320 return(0);
2321 }
2322 /* TODO walk the DTD if present */
2323
2324 reader->curnode = (xmlNodePtr) cur;
2325 return(1);
2326}
2327
2328/**
2329 * xmlTextReaderMoveToAttribute:
2330 * @reader: the xmlTextReaderPtr used
2331 * @name: the qualified name of the attribute.
2332 *
2333 * Moves the position of the current instance to the attribute with
2334 * the specified qualified name.
2335 *
2336 * Returns 1 in case of success, -1 in case of error, 0 if not found
2337 */
2338int
2339xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2340 xmlChar *prefix = NULL;
2341 xmlChar *localname;
2342 xmlNsPtr ns;
2343 xmlAttrPtr prop;
2344
2345 if ((reader == NULL) || (name == NULL))
2346 return(-1);
2347 if (reader->node == NULL)
2348 return(-1);
2349
2350 /* TODO: handle the xmlDecl */
2351 if (reader->node->type != XML_ELEMENT_NODE)
2352 return(0);
2353
2354 localname = xmlSplitQName2(name, &prefix);
2355 if (localname == NULL) {
2356 /*
2357 * Namespace default decl
2358 */
2359 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2360 ns = reader->node->nsDef;
2361 while (ns != NULL) {
2362 if (ns->prefix == NULL) {
2363 reader->curnode = (xmlNodePtr) ns;
2364 return(1);
2365 }
2366 ns = ns->next;
2367 }
2368 return(0);
2369 }
2370
2371 prop = reader->node->properties;
2372 while (prop != NULL) {
2373 /*
2374 * One need to have
2375 * - same attribute names
2376 * - and the attribute carrying that namespace
2377 */
2378 if ((xmlStrEqual(prop->name, name)) &&
2379 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2380 reader->curnode = (xmlNodePtr) prop;
2381 return(1);
2382 }
2383 prop = prop->next;
2384 }
2385 return(0);
2386 }
2387
2388 /*
2389 * Namespace default decl
2390 */
2391 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2392 ns = reader->node->nsDef;
2393 while (ns != NULL) {
2394 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2395 reader->curnode = (xmlNodePtr) ns;
2396 goto found;
2397 }
2398 ns = ns->next;
2399 }
2400 goto not_found;
2401 }
2402 prop = reader->node->properties;
2403 while (prop != NULL) {
2404 /*
2405 * One need to have
2406 * - same attribute names
2407 * - and the attribute carrying that namespace
2408 */
2409 if ((xmlStrEqual(prop->name, localname)) &&
2410 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2411 reader->curnode = (xmlNodePtr) prop;
2412 goto found;
2413 }
2414 prop = prop->next;
2415 }
2416not_found:
2417 if (localname != NULL)
2418 xmlFree(localname);
2419 if (prefix != NULL)
2420 xmlFree(prefix);
2421 return(0);
2422
2423found:
2424 if (localname != NULL)
2425 xmlFree(localname);
2426 if (prefix != NULL)
2427 xmlFree(prefix);
2428 return(1);
2429}
2430
2431/**
2432 * xmlTextReaderMoveToAttributeNs:
2433 * @reader: the xmlTextReaderPtr used
2434 * @localName: the local name of the attribute.
2435 * @namespaceURI: the namespace URI of the attribute.
2436 *
2437 * Moves the position of the current instance to the attribute with the
2438 * specified local name and namespace URI.
2439 *
2440 * Returns 1 in case of success, -1 in case of error, 0 if not found
2441 */
2442int
2443xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2444 const xmlChar *localName, const xmlChar *namespaceURI) {
2445 xmlAttrPtr prop;
2446 xmlNodePtr node;
2447
2448 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2449 return(-1);
2450 if (reader->node == NULL)
2451 return(-1);
2452 if (reader->node->type != XML_ELEMENT_NODE)
2453 return(0);
2454 node = reader->node;
2455
2456 /*
2457 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2458 * namespace name associated to "xmlns"
2459 */
2460 prop = node->properties;
2461 while (prop != NULL) {
2462 /*
2463 * One need to have
2464 * - same attribute names
2465 * - and the attribute carrying that namespace
2466 */
2467 if (xmlStrEqual(prop->name, localName) &&
2468 ((prop->ns != NULL) &&
2469 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2470 reader->curnode = (xmlNodePtr) prop;
2471 return(1);
2472 }
2473 prop = prop->next;
2474 }
2475 return(0);
2476}
2477
2478/**
2479 * xmlTextReaderMoveToFirstAttribute:
2480 * @reader: the xmlTextReaderPtr used
2481 *
2482 * Moves the position of the current instance to the first attribute
2483 * associated with the current node.
2484 *
2485 * Returns 1 in case of success, -1 in case of error, 0 if not found
2486 */
2487int
2488xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2489 if (reader == NULL)
2490 return(-1);
2491 if (reader->node == NULL)
2492 return(-1);
2493 if (reader->node->type != XML_ELEMENT_NODE)
2494 return(0);
2495
2496 if (reader->node->nsDef != NULL) {
2497 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2498 return(1);
2499 }
2500 if (reader->node->properties != NULL) {
2501 reader->curnode = (xmlNodePtr) reader->node->properties;
2502 return(1);
2503 }
2504 return(0);
2505}
2506
2507/**
2508 * xmlTextReaderMoveToNextAttribute:
2509 * @reader: the xmlTextReaderPtr used
2510 *
2511 * Moves the position of the current instance to the next attribute
2512 * associated with the current node.
2513 *
2514 * Returns 1 in case of success, -1 in case of error, 0 if not found
2515 */
2516int
2517xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2518 if (reader == NULL)
2519 return(-1);
2520 if (reader->node == NULL)
2521 return(-1);
2522 if (reader->node->type != XML_ELEMENT_NODE)
2523 return(0);
2524 if (reader->curnode == NULL)
2525 return(xmlTextReaderMoveToFirstAttribute(reader));
2526
2527 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2528 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2529 if (ns->next != NULL) {
2530 reader->curnode = (xmlNodePtr) ns->next;
2531 return(1);
2532 }
2533 if (reader->node->properties != NULL) {
2534 reader->curnode = (xmlNodePtr) reader->node->properties;
2535 return(1);
2536 }
2537 return(0);
2538 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2539 (reader->curnode->next != NULL)) {
2540 reader->curnode = reader->curnode->next;
2541 return(1);
2542 }
2543 return(0);
2544}
2545
2546/**
2547 * xmlTextReaderMoveToElement:
2548 * @reader: the xmlTextReaderPtr used
2549 *
2550 * Moves the position of the current instance to the node that
2551 * contains the current Attribute node.
2552 *
2553 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2554 */
2555int
2556xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2557 if (reader == NULL)
2558 return(-1);
2559 if (reader->node == NULL)
2560 return(-1);
2561 if (reader->node->type != XML_ELEMENT_NODE)
2562 return(0);
2563 if (reader->curnode != NULL) {
2564 reader->curnode = NULL;
2565 return(1);
2566 }
2567 return(0);
2568}
2569
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002570/**
2571 * xmlTextReaderReadAttributeValue:
2572 * @reader: the xmlTextReaderPtr used
2573 *
2574 * Parses an attribute value into one or more Text and EntityReference nodes.
2575 *
2576 * Returns 1 in case of success, 0 if the reader was not positionned on an
2577 * ttribute node or all the attribute values have been read, or -1
2578 * in case of error.
2579 */
2580int
2581xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2582 if (reader == NULL)
2583 return(-1);
2584 if (reader->node == NULL)
2585 return(-1);
2586 if (reader->curnode == NULL)
2587 return(0);
2588 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2589 if (reader->curnode->children == NULL)
2590 return(0);
2591 reader->curnode = reader->curnode->children;
2592 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2593 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2594
2595 if (reader->faketext == NULL) {
2596 reader->faketext = xmlNewDocText(reader->node->doc,
2597 ns->href);
2598 } else {
2599 if (reader->faketext->content != NULL)
2600 xmlFree(reader->faketext->content);
2601 reader->faketext->content = xmlStrdup(ns->href);
2602 }
2603 reader->curnode = reader->faketext;
2604 } else {
2605 if (reader->curnode->next == NULL)
2606 return(0);
2607 reader->curnode = reader->curnode->next;
2608 }
2609 return(1);
2610}
2611
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002612/************************************************************************
2613 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002614 * Acces API to the current node *
2615 * *
2616 ************************************************************************/
2617/**
2618 * xmlTextReaderAttributeCount:
2619 * @reader: the xmlTextReaderPtr used
2620 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002621 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002622 *
2623 * Returns 0 i no attributes, -1 in case of error or the attribute count
2624 */
2625int
2626xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2627 int ret;
2628 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002629 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002630 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002631
2632 if (reader == NULL)
2633 return(-1);
2634 if (reader->node == NULL)
2635 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002636
2637 if (reader->curnode != NULL)
2638 node = reader->curnode;
2639 else
2640 node = reader->node;
2641
2642 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002643 return(0);
2644 if ((reader->state == XML_TEXTREADER_END) ||
2645 (reader->state == XML_TEXTREADER_BACKTRACK))
2646 return(0);
2647 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002648 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002649 while (attr != NULL) {
2650 ret++;
2651 attr = attr->next;
2652 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002653 ns = node->nsDef;
2654 while (ns != NULL) {
2655 ret++;
2656 ns = ns->next;
2657 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002658 return(ret);
2659}
2660
2661/**
2662 * xmlTextReaderNodeType:
2663 * @reader: the xmlTextReaderPtr used
2664 *
2665 * Get the node type of the current node
2666 * Reference:
2667 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2668 *
2669 * Returns the xmlNodeType of the current node or -1 in case of error
2670 */
2671int
2672xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002673 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002674
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002675 if (reader == NULL)
2676 return(-1);
2677 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002678 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002679 if (reader->curnode != NULL)
2680 node = reader->curnode;
2681 else
2682 node = reader->node;
2683 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002684 case XML_ELEMENT_NODE:
2685 if ((reader->state == XML_TEXTREADER_END) ||
2686 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002687 return(XML_READER_TYPE_END_ELEMENT);
2688 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002689 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002690 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002691 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002692 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002693 if (xmlIsBlankNode(reader->node)) {
2694 if (xmlNodeGetSpacePreserve(reader->node))
2695 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2696 else
2697 return(XML_READER_TYPE_WHITESPACE);
2698 } else {
2699 return(XML_READER_TYPE_TEXT);
2700 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002701 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002702 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002703 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002704 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002705 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002706 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002707 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002708 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002709 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002710 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002711 case XML_DOCUMENT_NODE:
2712 case XML_HTML_DOCUMENT_NODE:
2713#ifdef LIBXML_DOCB_ENABLED
2714 case XML_DOCB_DOCUMENT_NODE:
2715#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002716 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002717 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002718 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002719 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002720 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002721 case XML_DOCUMENT_TYPE_NODE:
2722 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002723 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002724
2725 case XML_ELEMENT_DECL:
2726 case XML_ATTRIBUTE_DECL:
2727 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002728 case XML_XINCLUDE_START:
2729 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002730 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002731 }
2732 return(-1);
2733}
2734
2735/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002736 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002737 * @reader: the xmlTextReaderPtr used
2738 *
2739 * Check if the current node is empty
2740 *
2741 * Returns 1 if empty, 0 if not and -1 in case of error
2742 */
2743int
2744xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2745 if ((reader == NULL) || (reader->node == NULL))
2746 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002747 if (reader->node->type != XML_ELEMENT_NODE)
2748 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002749 if (reader->curnode != NULL)
2750 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002751 if (reader->node->children != NULL)
2752 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002753 if (reader->state == XML_TEXTREADER_END)
2754 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002755 if (reader->doc != NULL)
2756 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002757#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002758 if (reader->in_xinclude > 0)
2759 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00002760#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00002761 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002762}
2763
2764/**
2765 * xmlTextReaderLocalName:
2766 * @reader: the xmlTextReaderPtr used
2767 *
2768 * The local name of the node.
2769 *
2770 * Returns the local name or NULL if not available
2771 */
2772xmlChar *
2773xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002774 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002775 if ((reader == NULL) || (reader->node == NULL))
2776 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002777 if (reader->curnode != NULL)
2778 node = reader->curnode;
2779 else
2780 node = reader->node;
2781 if (node->type == XML_NAMESPACE_DECL) {
2782 xmlNsPtr ns = (xmlNsPtr) node;
2783 if (ns->prefix == NULL)
2784 return(xmlStrdup(BAD_CAST "xmlns"));
2785 else
2786 return(xmlStrdup(ns->prefix));
2787 }
2788 if ((node->type != XML_ELEMENT_NODE) &&
2789 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002790 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002791 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002792}
2793
2794/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002795 * xmlTextReaderConstLocalName:
2796 * @reader: the xmlTextReaderPtr used
2797 *
2798 * The local name of the node.
2799 *
2800 * Returns the local name or NULL if not available, the
2801 * string will be deallocated with the reader.
2802 */
2803const xmlChar *
2804xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2805 xmlNodePtr node;
2806 if ((reader == NULL) || (reader->node == NULL))
2807 return(NULL);
2808 if (reader->curnode != NULL)
2809 node = reader->curnode;
2810 else
2811 node = reader->node;
2812 if (node->type == XML_NAMESPACE_DECL) {
2813 xmlNsPtr ns = (xmlNsPtr) node;
2814 if (ns->prefix == NULL)
2815 return(CONSTSTR(BAD_CAST "xmlns"));
2816 else
2817 return(ns->prefix);
2818 }
2819 if ((node->type != XML_ELEMENT_NODE) &&
2820 (node->type != XML_ATTRIBUTE_NODE))
2821 return(xmlTextReaderConstName(reader));
2822 return(node->name);
2823}
2824
2825/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002826 * xmlTextReaderName:
2827 * @reader: the xmlTextReaderPtr used
2828 *
2829 * The qualified name of the node, equal to Prefix :LocalName.
2830 *
2831 * Returns the local name or NULL if not available
2832 */
2833xmlChar *
2834xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002835 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002836 xmlChar *ret;
2837
2838 if ((reader == NULL) || (reader->node == NULL))
2839 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002840 if (reader->curnode != NULL)
2841 node = reader->curnode;
2842 else
2843 node = reader->node;
2844 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002845 case XML_ELEMENT_NODE:
2846 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002847 if ((node->ns == NULL) ||
2848 (node->ns->prefix == NULL))
2849 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002850
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002851 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002852 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002853 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002854 return(ret);
2855 case XML_TEXT_NODE:
2856 return(xmlStrdup(BAD_CAST "#text"));
2857 case XML_CDATA_SECTION_NODE:
2858 return(xmlStrdup(BAD_CAST "#cdata-section"));
2859 case XML_ENTITY_NODE:
2860 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002861 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002862 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002863 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002864 case XML_COMMENT_NODE:
2865 return(xmlStrdup(BAD_CAST "#comment"));
2866 case XML_DOCUMENT_NODE:
2867 case XML_HTML_DOCUMENT_NODE:
2868#ifdef LIBXML_DOCB_ENABLED
2869 case XML_DOCB_DOCUMENT_NODE:
2870#endif
2871 return(xmlStrdup(BAD_CAST "#document"));
2872 case XML_DOCUMENT_FRAG_NODE:
2873 return(xmlStrdup(BAD_CAST "#document-fragment"));
2874 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002875 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002876 case XML_DOCUMENT_TYPE_NODE:
2877 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002878 return(xmlStrdup(node->name));
2879 case XML_NAMESPACE_DECL: {
2880 xmlNsPtr ns = (xmlNsPtr) node;
2881
2882 ret = xmlStrdup(BAD_CAST "xmlns");
2883 if (ns->prefix == NULL)
2884 return(ret);
2885 ret = xmlStrcat(ret, BAD_CAST ":");
2886 ret = xmlStrcat(ret, ns->prefix);
2887 return(ret);
2888 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002889
2890 case XML_ELEMENT_DECL:
2891 case XML_ATTRIBUTE_DECL:
2892 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002893 case XML_XINCLUDE_START:
2894 case XML_XINCLUDE_END:
2895 return(NULL);
2896 }
2897 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002898}
2899
2900/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002901 * xmlTextReaderConstName:
2902 * @reader: the xmlTextReaderPtr used
2903 *
2904 * The qualified name of the node, equal to Prefix :LocalName.
2905 *
2906 * Returns the local name or NULL if not available, the string is
2907 * deallocated with the reader.
2908 */
2909const xmlChar *
2910xmlTextReaderConstName(xmlTextReaderPtr reader) {
2911 xmlNodePtr node;
2912
2913 if ((reader == NULL) || (reader->node == NULL))
2914 return(NULL);
2915 if (reader->curnode != NULL)
2916 node = reader->curnode;
2917 else
2918 node = reader->node;
2919 switch (node->type) {
2920 case XML_ELEMENT_NODE:
2921 case XML_ATTRIBUTE_NODE:
2922 if ((node->ns == NULL) ||
2923 (node->ns->prefix == NULL))
2924 return(node->name);
2925 return(CONSTQSTR(node->ns->prefix, node->name));
2926 case XML_TEXT_NODE:
2927 return(CONSTSTR(BAD_CAST "#text"));
2928 case XML_CDATA_SECTION_NODE:
2929 return(CONSTSTR(BAD_CAST "#cdata-section"));
2930 case XML_ENTITY_NODE:
2931 case XML_ENTITY_REF_NODE:
2932 return(CONSTSTR(node->name));
2933 case XML_PI_NODE:
2934 return(CONSTSTR(node->name));
2935 case XML_COMMENT_NODE:
2936 return(CONSTSTR(BAD_CAST "#comment"));
2937 case XML_DOCUMENT_NODE:
2938 case XML_HTML_DOCUMENT_NODE:
2939#ifdef LIBXML_DOCB_ENABLED
2940 case XML_DOCB_DOCUMENT_NODE:
2941#endif
2942 return(CONSTSTR(BAD_CAST "#document"));
2943 case XML_DOCUMENT_FRAG_NODE:
2944 return(CONSTSTR(BAD_CAST "#document-fragment"));
2945 case XML_NOTATION_NODE:
2946 return(CONSTSTR(node->name));
2947 case XML_DOCUMENT_TYPE_NODE:
2948 case XML_DTD_NODE:
2949 return(CONSTSTR(node->name));
2950 case XML_NAMESPACE_DECL: {
2951 xmlNsPtr ns = (xmlNsPtr) node;
2952
2953 if (ns->prefix == NULL)
2954 return(CONSTSTR(BAD_CAST "xmlns"));
2955 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2956 }
2957
2958 case XML_ELEMENT_DECL:
2959 case XML_ATTRIBUTE_DECL:
2960 case XML_ENTITY_DECL:
2961 case XML_XINCLUDE_START:
2962 case XML_XINCLUDE_END:
2963 return(NULL);
2964 }
2965 return(NULL);
2966}
2967
2968/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002969 * xmlTextReaderPrefix:
2970 * @reader: the xmlTextReaderPtr used
2971 *
2972 * A shorthand reference to the namespace associated with the node.
2973 *
2974 * Returns the prefix or NULL if not available
2975 */
2976xmlChar *
2977xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002978 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002979 if ((reader == NULL) || (reader->node == NULL))
2980 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002981 if (reader->curnode != NULL)
2982 node = reader->curnode;
2983 else
2984 node = reader->node;
2985 if (node->type == XML_NAMESPACE_DECL) {
2986 xmlNsPtr ns = (xmlNsPtr) node;
2987 if (ns->prefix == NULL)
2988 return(NULL);
2989 return(xmlStrdup(BAD_CAST "xmlns"));
2990 }
2991 if ((node->type != XML_ELEMENT_NODE) &&
2992 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002993 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002994 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002995 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002996 return(NULL);
2997}
2998
2999/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003000 * xmlTextReaderConstPrefix:
3001 * @reader: the xmlTextReaderPtr used
3002 *
3003 * A shorthand reference to the namespace associated with the node.
3004 *
3005 * Returns the prefix or NULL if not available, the string is deallocated
3006 * with the reader.
3007 */
3008const xmlChar *
3009xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3010 xmlNodePtr node;
3011 if ((reader == NULL) || (reader->node == NULL))
3012 return(NULL);
3013 if (reader->curnode != NULL)
3014 node = reader->curnode;
3015 else
3016 node = reader->node;
3017 if (node->type == XML_NAMESPACE_DECL) {
3018 xmlNsPtr ns = (xmlNsPtr) node;
3019 if (ns->prefix == NULL)
3020 return(NULL);
3021 return(CONSTSTR(BAD_CAST "xmlns"));
3022 }
3023 if ((node->type != XML_ELEMENT_NODE) &&
3024 (node->type != XML_ATTRIBUTE_NODE))
3025 return(NULL);
3026 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3027 return(CONSTSTR(node->ns->prefix));
3028 return(NULL);
3029}
3030
3031/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003032 * xmlTextReaderNamespaceUri:
3033 * @reader: the xmlTextReaderPtr used
3034 *
3035 * The URI defining the namespace associated with the node.
3036 *
3037 * Returns the namespace URI or NULL if not available
3038 */
3039xmlChar *
3040xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003041 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003042 if ((reader == NULL) || (reader->node == NULL))
3043 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003044 if (reader->curnode != NULL)
3045 node = reader->curnode;
3046 else
3047 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003048 if (node->type == XML_NAMESPACE_DECL)
3049 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003050 if ((node->type != XML_ELEMENT_NODE) &&
3051 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003052 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003053 if (node->ns != NULL)
3054 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003055 return(NULL);
3056}
3057
3058/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003059 * xmlTextReaderConstNamespaceUri:
3060 * @reader: the xmlTextReaderPtr used
3061 *
3062 * The URI defining the namespace associated with the node.
3063 *
3064 * Returns the namespace URI or NULL if not available, the string
3065 * will be deallocated with the reader
3066 */
3067const xmlChar *
3068xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3069 xmlNodePtr node;
3070 if ((reader == NULL) || (reader->node == NULL))
3071 return(NULL);
3072 if (reader->curnode != NULL)
3073 node = reader->curnode;
3074 else
3075 node = reader->node;
3076 if (node->type == XML_NAMESPACE_DECL)
3077 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3078 if ((node->type != XML_ELEMENT_NODE) &&
3079 (node->type != XML_ATTRIBUTE_NODE))
3080 return(NULL);
3081 if (node->ns != NULL)
3082 return(CONSTSTR(node->ns->href));
3083 return(NULL);
3084}
3085
3086/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003087 * xmlTextReaderBaseUri:
3088 * @reader: the xmlTextReaderPtr used
3089 *
3090 * The base URI of the node.
3091 *
3092 * Returns the base URI or NULL if not available
3093 */
3094xmlChar *
3095xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3096 if ((reader == NULL) || (reader->node == NULL))
3097 return(NULL);
3098 return(xmlNodeGetBase(NULL, reader->node));
3099}
3100
3101/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003102 * xmlTextReaderConstBaseUri:
3103 * @reader: the xmlTextReaderPtr used
3104 *
3105 * The base URI of the node.
3106 *
3107 * Returns the base URI or NULL if not available, the string
3108 * will be deallocated with the reader
3109 */
3110const xmlChar *
3111xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3112 xmlChar *tmp;
3113 const xmlChar *ret;
3114
3115 if ((reader == NULL) || (reader->node == NULL))
3116 return(NULL);
3117 tmp = xmlNodeGetBase(NULL, reader->node);
3118 if (tmp == NULL)
3119 return(NULL);
3120 ret = CONSTSTR(tmp);
3121 xmlFree(tmp);
3122 return(ret);
3123}
3124
3125/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003126 * xmlTextReaderDepth:
3127 * @reader: the xmlTextReaderPtr used
3128 *
3129 * The depth of the node in the tree.
3130 *
3131 * Returns the depth or -1 in case of error
3132 */
3133int
3134xmlTextReaderDepth(xmlTextReaderPtr reader) {
3135 if (reader == NULL)
3136 return(-1);
3137 if (reader->node == NULL)
3138 return(0);
3139
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003140 if (reader->curnode != NULL) {
3141 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3142 (reader->curnode->type == XML_NAMESPACE_DECL))
3143 return(reader->depth + 1);
3144 return(reader->depth + 2);
3145 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003146 return(reader->depth);
3147}
3148
3149/**
3150 * xmlTextReaderHasAttributes:
3151 * @reader: the xmlTextReaderPtr used
3152 *
3153 * Whether the node has attributes.
3154 *
3155 * Returns 1 if true, 0 if false, and -1 in case or error
3156 */
3157int
3158xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003159 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003160 if (reader == NULL)
3161 return(-1);
3162 if (reader->node == NULL)
3163 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003164 if (reader->curnode != NULL)
3165 node = reader->curnode;
3166 else
3167 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003168
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003169 if ((node->type == XML_ELEMENT_NODE) &&
3170 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003171 return(1);
3172 /* TODO: handle the xmlDecl */
3173 return(0);
3174}
3175
3176/**
3177 * xmlTextReaderHasValue:
3178 * @reader: the xmlTextReaderPtr used
3179 *
3180 * Whether the node can have a text value.
3181 *
3182 * Returns 1 if true, 0 if false, and -1 in case or error
3183 */
3184int
3185xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003186 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003187 if (reader == NULL)
3188 return(-1);
3189 if (reader->node == NULL)
3190 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003191 if (reader->curnode != NULL)
3192 node = reader->curnode;
3193 else
3194 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003195
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003196 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003197 case XML_ATTRIBUTE_NODE:
3198 case XML_TEXT_NODE:
3199 case XML_CDATA_SECTION_NODE:
3200 case XML_PI_NODE:
3201 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003202 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003203 return(1);
3204 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003205 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003206 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003207 return(0);
3208}
3209
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003210/**
3211 * xmlTextReaderValue:
3212 * @reader: the xmlTextReaderPtr used
3213 *
3214 * Provides the text value of the node if present
3215 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003216 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003217 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003218 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003219xmlChar *
3220xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003221 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003222 if (reader == NULL)
3223 return(NULL);
3224 if (reader->node == NULL)
3225 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003226 if (reader->curnode != NULL)
3227 node = reader->curnode;
3228 else
3229 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003230
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003231 switch (node->type) {
3232 case XML_NAMESPACE_DECL:
3233 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003234 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003235 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003236
3237 if (attr->parent != NULL)
3238 return (xmlNodeListGetString
3239 (attr->parent->doc, attr->children, 1));
3240 else
3241 return (xmlNodeListGetString(NULL, attr->children, 1));
3242 break;
3243 }
3244 case XML_TEXT_NODE:
3245 case XML_CDATA_SECTION_NODE:
3246 case XML_PI_NODE:
3247 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003248 if (node->content != NULL)
3249 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003250 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003251 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003252 }
3253 return(NULL);
3254}
3255
3256/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003257 * xmlTextReaderConstValue:
3258 * @reader: the xmlTextReaderPtr used
3259 *
3260 * Provides the text value of the node if present
3261 *
3262 * Returns the string or NULL if not available. The result will be
3263 * deallocated on the next Read() operation.
3264 */
3265const xmlChar *
3266xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3267 xmlNodePtr node;
3268 if (reader == NULL)
3269 return(NULL);
3270 if (reader->node == NULL)
3271 return(NULL);
3272 if (reader->curnode != NULL)
3273 node = reader->curnode;
3274 else
3275 node = reader->node;
3276
3277 switch (node->type) {
3278 case XML_NAMESPACE_DECL:
3279 return(((xmlNsPtr) node)->href);
3280 case XML_ATTRIBUTE_NODE:{
3281 xmlAttrPtr attr = (xmlAttrPtr) node;
3282
3283 if ((attr->children != NULL) &&
3284 (attr->children->type == XML_TEXT_NODE) &&
3285 (attr->children->next == NULL))
3286 return(attr->children->content);
3287 else {
3288 reader->buffer->use = 0;
3289 xmlNodeBufGetContent(reader->buffer, node);
3290 return(reader->buffer->content);
3291 }
3292 break;
3293 }
3294 case XML_TEXT_NODE:
3295 case XML_CDATA_SECTION_NODE:
3296 case XML_PI_NODE:
3297 case XML_COMMENT_NODE:
3298 return(node->content);
3299 default:
3300 break;
3301 }
3302 return(NULL);
3303}
3304
3305/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003306 * xmlTextReaderIsDefault:
3307 * @reader: the xmlTextReaderPtr used
3308 *
3309 * Whether an Attribute node was generated from the default value
3310 * defined in the DTD or schema.
3311 *
3312 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3313 */
3314int
3315xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3316 if (reader == NULL)
3317 return(-1);
3318 return(0);
3319}
3320
3321/**
3322 * xmlTextReaderQuoteChar:
3323 * @reader: the xmlTextReaderPtr used
3324 *
3325 * The quotation mark character used to enclose the value of an attribute.
3326 *
3327 * Returns " or ' and -1 in case of error
3328 */
3329int
3330xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3331 if (reader == NULL)
3332 return(-1);
3333 /* TODO maybe lookup the attribute value for " first */
3334 return((int) '"');
3335}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003336
3337/**
3338 * xmlTextReaderXmlLang:
3339 * @reader: the xmlTextReaderPtr used
3340 *
3341 * The xml:lang scope within which the node resides.
3342 *
3343 * Returns the xml:lang value or NULL if none exists.
3344 */
3345xmlChar *
3346xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3347 if (reader == NULL)
3348 return(NULL);
3349 if (reader->node == NULL)
3350 return(NULL);
3351 return(xmlNodeGetLang(reader->node));
3352}
3353
Daniel Veillard67df8092002-12-16 22:04:11 +00003354/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003355 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003356 * @reader: the xmlTextReaderPtr used
3357 *
3358 * The xml:lang scope within which the node resides.
3359 *
3360 * Returns the xml:lang value or NULL if none exists.
3361 */
3362const xmlChar *
3363xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3364 xmlChar *tmp;
3365 const xmlChar *ret;
3366
3367 if (reader == NULL)
3368 return(NULL);
3369 if (reader->node == NULL)
3370 return(NULL);
3371 tmp = xmlNodeGetLang(reader->node);
3372 if (tmp == NULL)
3373 return(NULL);
3374 ret = CONSTSTR(tmp);
3375 xmlFree(tmp);
3376 return(ret);
3377}
3378
3379/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003380 * xmlTextReaderConstString:
3381 * @reader: the xmlTextReaderPtr used
3382 * @str: the string to intern.
3383 *
3384 * Get an interned string from the reader, allows for example to
3385 * speedup string name comparisons
3386 *
3387 * Returns an interned copy of the string or NULL in case of error. The
3388 * string will be deallocated with the reader.
3389 */
3390const xmlChar *
3391xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3392 if (reader == NULL)
3393 return(NULL);
3394 return(CONSTSTR(str));
3395}
3396
3397/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003398 * xmlTextReaderNormalization:
3399 * @reader: the xmlTextReaderPtr used
3400 *
3401 * The value indicating whether to normalize white space and attribute values.
3402 * Since attribute value and end of line normalizations are a MUST in the XML
3403 * specification only the value true is accepted. The broken bahaviour of
3404 * accepting out of range character entities like &#0; is of course not
3405 * supported either.
3406 *
3407 * Returns 1 or -1 in case of error.
3408 */
3409int
3410xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3411 if (reader == NULL)
3412 return(-1);
3413 return(1);
3414}
3415
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003416/************************************************************************
3417 * *
3418 * Extensions to the base APIs *
3419 * *
3420 ************************************************************************/
3421
3422/**
3423 * xmlTextReaderSetParserProp:
3424 * @reader: the xmlTextReaderPtr used
3425 * @prop: the xmlParserProperties to set
3426 * @value: usually 0 or 1 to (de)activate it
3427 *
3428 * Change the parser processing behaviour by changing some of its internal
3429 * properties. Note that some properties can only be changed before any
3430 * read has been done.
3431 *
3432 * Returns 0 if the call was successful, or -1 in case of error
3433 */
3434int
3435xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3436 xmlParserProperties p = (xmlParserProperties) prop;
3437 xmlParserCtxtPtr ctxt;
3438
3439 if ((reader == NULL) || (reader->ctxt == NULL))
3440 return(-1);
3441 ctxt = reader->ctxt;
3442
3443 switch (p) {
3444 case XML_PARSER_LOADDTD:
3445 if (value != 0) {
3446 if (ctxt->loadsubset == 0) {
3447 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3448 return(-1);
3449 ctxt->loadsubset = XML_DETECT_IDS;
3450 }
3451 } else {
3452 ctxt->loadsubset = 0;
3453 }
3454 return(0);
3455 case XML_PARSER_DEFAULTATTRS:
3456 if (value != 0) {
3457 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3458 } else {
3459 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3460 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3461 }
3462 return(0);
3463 case XML_PARSER_VALIDATE:
3464 if (value != 0) {
3465 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003466 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003467 } else {
3468 ctxt->validate = 0;
3469 }
3470 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003471 case XML_PARSER_SUBST_ENTITIES:
3472 if (value != 0) {
3473 ctxt->replaceEntities = 1;
3474 } else {
3475 ctxt->replaceEntities = 0;
3476 }
3477 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003478 }
3479 return(-1);
3480}
3481
3482/**
3483 * xmlTextReaderGetParserProp:
3484 * @reader: the xmlTextReaderPtr used
3485 * @prop: the xmlParserProperties to get
3486 *
3487 * Read the parser internal property.
3488 *
3489 * Returns the value, usually 0 or 1, or -1 in case of error.
3490 */
3491int
3492xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3493 xmlParserProperties p = (xmlParserProperties) prop;
3494 xmlParserCtxtPtr ctxt;
3495
3496 if ((reader == NULL) || (reader->ctxt == NULL))
3497 return(-1);
3498 ctxt = reader->ctxt;
3499
3500 switch (p) {
3501 case XML_PARSER_LOADDTD:
3502 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3503 return(1);
3504 return(0);
3505 case XML_PARSER_DEFAULTATTRS:
3506 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3507 return(1);
3508 return(0);
3509 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003510 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003511 case XML_PARSER_SUBST_ENTITIES:
3512 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003513 }
3514 return(-1);
3515}
3516
Daniel Veillarde18fc182002-12-28 22:56:33 +00003517/**
3518 * xmlTextReaderCurrentNode:
3519 * @reader: the xmlTextReaderPtr used
3520 *
3521 * Hacking interface allowing to get the xmlNodePtr correponding to the
3522 * current node being accessed by the xmlTextReader. This is dangerous
3523 * because the underlying node may be destroyed on the next Reads.
3524 *
3525 * Returns the xmlNodePtr or NULL in case of error.
3526 */
3527xmlNodePtr
3528xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3529 if (reader == NULL)
3530 return(NULL);
3531
3532 if (reader->curnode != NULL)
3533 return(reader->curnode);
3534 return(reader->node);
3535}
3536
3537/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003538 * xmlTextReaderPreserve:
3539 * @reader: the xmlTextReaderPtr used
3540 *
3541 *
3542 * current node being accessed by the xmlTextReader. This is dangerous
3543 * because the underlying node may be destroyed on the next Reads.
3544 *
3545 * Returns the xmlNodePtr or NULL in case of error.
3546 */
3547xmlNodePtr
3548xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3549 xmlNodePtr cur, parent;
3550
3551 if (reader == NULL)
3552 return(NULL);
3553
3554 if (reader->curnode != NULL)
3555 cur = reader->curnode;
3556 else
3557 cur = reader->node;
3558 if (cur == NULL)
3559 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003560
3561 if (cur->type != XML_DOCUMENT_NODE) {
3562 cur->extra |= NODE_IS_PRESERVED;
3563 cur->extra |= NODE_IS_SPRESERVED;
3564 }
3565 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003566
3567 parent = cur->parent;;
3568 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003569 if (parent->type == XML_ELEMENT_NODE)
3570 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003571 parent = parent->parent;
3572 }
3573 return(cur);
3574}
3575
Daniel Veillard1e906612003-12-05 14:57:46 +00003576#ifdef LIBXML_PATTERN_ENABLED
3577/**
3578 * xmlTextReaderPreservePattern:
3579 * @reader: the xmlTextReaderPtr used
3580 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003581 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003582 *
3583 * This tells the XML Reader to preserve all nodes matched by the
3584 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3585 * keep an handle on the resulting document once parsing has finished
3586 *
3587 * Returns a positive number in case of success and -1 in case of error
3588 */
3589int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003590xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3591 const xmlChar **namespaces)
3592{
Daniel Veillard1e906612003-12-05 14:57:46 +00003593 xmlPatternPtr comp;
3594
3595 if ((reader == NULL) || (pattern == NULL))
3596 return(-1);
3597
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003598 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003599 if (comp == NULL)
3600 return(-1);
3601
3602 if (reader->patternMax <= 0) {
3603 reader->patternMax = 4;
3604 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3605 sizeof(reader->patternTab[0]));
3606 if (reader->patternTab == NULL) {
3607 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3608 return (-1);
3609 }
3610 }
3611 if (reader->patternNr >= reader->patternMax) {
3612 xmlPatternPtr *tmp;
3613 reader->patternMax *= 2;
3614 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3615 reader->patternMax *
3616 sizeof(reader->patternTab[0]));
3617 if (tmp == NULL) {
3618 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3619 reader->patternMax /= 2;
3620 return (-1);
3621 }
3622 reader->patternTab = tmp;
3623 }
3624 reader->patternTab[reader->patternNr] = comp;
3625 return(reader->patternNr++);
3626}
3627#endif
3628
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003629/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003630 * xmlTextReaderCurrentDoc:
3631 * @reader: the xmlTextReaderPtr used
3632 *
3633 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003634 * current document being accessed by the xmlTextReader.
3635 * NOTE: as a result of this call, the reader will not destroy the
3636 * associated XML document and calling xmlFreeDoc() on the result
3637 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003638 *
3639 * Returns the xmlDocPtr or NULL in case of error.
3640 */
3641xmlDocPtr
3642xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003643 if (reader == NULL)
3644 return(NULL);
3645 if (reader->doc != NULL)
3646 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003647 if ((reader == NULL) || (reader->ctxt == NULL) ||
3648 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003649 return(NULL);
3650
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003651 reader->preserve = 1;
3652 if ((reader->ctxt->myDoc->dict != NULL) &&
3653 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3654 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003655 return(reader->ctxt->myDoc);
3656}
3657
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003658#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003659/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003660 * xmlTextReaderRelaxNGSetSchema:
3661 * @reader: the xmlTextReaderPtr used
3662 * @schema: a precompiled RelaxNG schema
3663 *
3664 * Use RelaxNG to validate the document as it is processed.
3665 * Activation is only possible before the first Read().
3666 * if @schema is NULL, then RelaxNG validation is desactivated.
3667 @ The @schema should not be freed until the reader is deallocated
3668 * or its use has been deactivated.
3669 *
3670 * Returns 0 in case the RelaxNG validation could be (des)activated and
3671 * -1 in case of error.
3672 */
3673int
3674xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3675 if (schema == NULL) {
3676 if (reader->rngSchemas != NULL) {
3677 xmlRelaxNGFree(reader->rngSchemas);
3678 reader->rngSchemas = NULL;
3679 }
3680 if (reader->rngValidCtxt != NULL) {
3681 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3682 reader->rngValidCtxt = NULL;
3683 }
3684 return(0);
3685 }
3686 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3687 return(-1);
3688 if (reader->rngSchemas != NULL) {
3689 xmlRelaxNGFree(reader->rngSchemas);
3690 reader->rngSchemas = NULL;
3691 }
3692 if (reader->rngValidCtxt != NULL) {
3693 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3694 reader->rngValidCtxt = NULL;
3695 }
3696 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3697 if (reader->rngValidCtxt == NULL)
3698 return(-1);
3699 if (reader->errorFunc != NULL) {
3700 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3701 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3702 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3703 reader->errorFuncArg);
3704 }
3705 reader->rngValidErrors = 0;
3706 reader->rngFullNode = NULL;
3707 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3708 return(0);
3709}
3710
3711/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003712 * xmlTextReaderRelaxNGValidate:
3713 * @reader: the xmlTextReaderPtr used
3714 * @rng: the path to a RelaxNG schema or NULL
3715 *
3716 * Use RelaxNG to validate the document as it is processed.
3717 * Activation is only possible before the first Read().
3718 * if @rng is NULL, then RelaxNG validation is desactivated.
3719 *
3720 * Returns 0 in case the RelaxNG validation could be (des)activated and
3721 * -1 in case of error.
3722 */
3723int
3724xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3725 xmlRelaxNGParserCtxtPtr ctxt;
3726
3727 if (reader == NULL)
3728 return(-1);
3729
3730 if (rng == NULL) {
3731 if (reader->rngSchemas != NULL) {
3732 xmlRelaxNGFree(reader->rngSchemas);
3733 reader->rngSchemas = NULL;
3734 }
3735 if (reader->rngValidCtxt != NULL) {
3736 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3737 reader->rngValidCtxt = NULL;
3738 }
3739 return(0);
3740 }
3741 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3742 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003743 if (reader->rngSchemas != NULL) {
3744 xmlRelaxNGFree(reader->rngSchemas);
3745 reader->rngSchemas = NULL;
3746 }
3747 if (reader->rngValidCtxt != NULL) {
3748 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3749 reader->rngValidCtxt = NULL;
3750 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003751 ctxt = xmlRelaxNGNewParserCtxt(rng);
3752 if (reader->errorFunc != NULL) {
3753 xmlRelaxNGSetParserErrors(ctxt,
3754 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3755 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3756 reader->errorFuncArg);
3757 }
3758 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3759 xmlRelaxNGFreeParserCtxt(ctxt);
3760 if (reader->rngSchemas == NULL)
3761 return(-1);
3762 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3763 if (reader->rngValidCtxt == NULL)
3764 return(-1);
3765 if (reader->errorFunc != NULL) {
3766 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3767 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3768 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3769 reader->errorFuncArg);
3770 }
3771 reader->rngValidErrors = 0;
3772 reader->rngFullNode = NULL;
3773 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3774 return(0);
3775}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003776#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003777
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003778/************************************************************************
3779 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003780 * Error Handling Extensions *
3781 * *
3782 ************************************************************************/
3783
3784/* helper to build a xmlMalloc'ed string from a format and va_list */
3785static char *
3786xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3787 int size;
3788 int chars;
3789 char *larger;
3790 char *str;
3791
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003792 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003793 if (str == NULL) {
3794 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3795 return NULL;
3796 }
3797
3798 size = 150;
3799
3800 while (1) {
3801 chars = vsnprintf(str, size, msg, ap);
3802 if ((chars > -1) && (chars < size))
3803 break;
3804 if (chars > -1)
3805 size += chars + 1;
3806 else
3807 size += 100;
3808 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3809 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3810 xmlFree(str);
3811 return NULL;
3812 }
3813 str = larger;
3814 }
3815
3816 return str;
3817}
3818
Daniel Veillard417be3a2003-01-20 21:26:34 +00003819/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003820 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003821 * @locator: the xmlTextReaderLocatorPtr used
3822 *
3823 * Obtain the line number for the given locator.
3824 *
3825 * Returns the line number or -1 in case of error.
3826 */
3827int
3828xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3829 /* we know that locator is a xmlParserCtxtPtr */
3830 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3831 int ret = -1;
3832
3833 if (ctx->node != NULL) {
3834 ret = xmlGetLineNo(ctx->node);
3835 }
3836 else {
3837 /* inspired from error.c */
3838 xmlParserInputPtr input;
3839 input = ctx->input;
3840 if ((input->filename == NULL) && (ctx->inputNr > 1))
3841 input = ctx->inputTab[ctx->inputNr - 2];
3842 if (input != NULL) {
3843 ret = input->line;
3844 }
3845 else {
3846 ret = -1;
3847 }
3848 }
3849
3850 return ret;
3851}
3852
3853/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003854 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003855 * @locator: the xmlTextReaderLocatorPtr used
3856 *
3857 * Obtain the base URI for the given locator.
3858 *
3859 * Returns the base URI or NULL in case of error.
3860 */
3861xmlChar *
3862xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3863 /* we know that locator is a xmlParserCtxtPtr */
3864 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3865 xmlChar *ret = NULL;
3866
3867 if (ctx->node != NULL) {
3868 ret = xmlNodeGetBase(NULL,ctx->node);
3869 }
3870 else {
3871 /* inspired from error.c */
3872 xmlParserInputPtr input;
3873 input = ctx->input;
3874 if ((input->filename == NULL) && (ctx->inputNr > 1))
3875 input = ctx->inputTab[ctx->inputNr - 2];
3876 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003877 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003878 }
3879 else {
3880 ret = NULL;
3881 }
3882 }
3883
3884 return ret;
3885}
3886
Daniel Veillard26f70262003-01-16 22:45:08 +00003887static void
William M. Brack899e64a2003-09-26 18:03:42 +00003888xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003889 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3890 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3891
3892 if (str != NULL) {
3893 reader->errorFunc(reader->errorFuncArg,
3894 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003895 severity,
3896 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003897 xmlFree(str);
3898 }
3899}
3900
3901static void
William M. Brack93d004f2004-02-03 00:14:10 +00003902xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) {
3903 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
3904 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
3905
3906 if (error && reader->sErrorFunc) {
3907 reader->sErrorFunc(reader->errorFuncArg,
3908 (xmlErrorPtr) error);
3909 }
3910}
3911
3912static void
Daniel Veillard26f70262003-01-16 22:45:08 +00003913xmlTextReaderError(void *ctxt, const char *msg, ...) {
3914 va_list ap;
3915
3916 va_start(ap,msg);
3917 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003918 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003919 xmlTextReaderBuildMessage(msg,ap));
3920 va_end(ap);
3921
3922}
3923
3924static void
3925xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3926 va_list ap;
3927
3928 va_start(ap,msg);
3929 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003930 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003931 xmlTextReaderBuildMessage(msg,ap));
3932 va_end(ap);
3933}
3934
3935static void
3936xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3937 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003938 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003939
Daniel Veillard417be3a2003-01-20 21:26:34 +00003940 if ((len > 1) && (msg[len - 2] != ':')) {
3941 /*
3942 * some callbacks only report locator information:
3943 * skip them (mimicking behaviour in error.c)
3944 */
3945 va_start(ap,msg);
3946 xmlTextReaderGenericError(ctxt,
3947 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3948 xmlTextReaderBuildMessage(msg,ap));
3949 va_end(ap);
3950 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003951}
3952
3953static void
3954xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3955 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003956 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003957
Daniel Veillard417be3a2003-01-20 21:26:34 +00003958 if ((len != 0) && (msg[len - 1] != ':')) {
3959 /*
3960 * some callbacks only report locator information:
3961 * skip them (mimicking behaviour in error.c)
3962 */
3963 va_start(ap,msg);
3964 xmlTextReaderGenericError(ctxt,
3965 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3966 xmlTextReaderBuildMessage(msg,ap));
3967 va_end(ap);
3968 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003969}
3970
3971/**
3972 * xmlTextReaderSetErrorHandler:
3973 * @reader: the xmlTextReaderPtr used
3974 * @f: the callback function to call on error and warnings
3975 * @arg: a user argument to pass to the callback function
3976 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003977 * Register a callback function that will be called on error and warnings.
3978 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003979 * If @f is NULL, the default error and warning handlers are restored.
3980 */
3981void
3982xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3983 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003984 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003985 if (f != NULL) {
3986 reader->ctxt->sax->error = xmlTextReaderError;
William M. Brack93d004f2004-02-03 00:14:10 +00003987 reader->ctxt->sax->serror = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00003988 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3989 reader->ctxt->sax->warning = xmlTextReaderWarning;
3990 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3991 reader->errorFunc = f;
3992 reader->errorFuncArg = arg;
3993 }
3994 else {
3995 /* restore defaults */
3996 reader->ctxt->sax->error = xmlParserError;
3997 reader->ctxt->vctxt.error = xmlParserValidityError;
3998 reader->ctxt->sax->warning = xmlParserWarning;
3999 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4000 reader->errorFunc = NULL;
William M. Brack93d004f2004-02-03 00:14:10 +00004001 reader->sErrorFunc = NULL;
Daniel Veillard26f70262003-01-16 22:45:08 +00004002 reader->errorFuncArg = NULL;
4003 }
4004}
4005
Daniel Veillard417be3a2003-01-20 21:26:34 +00004006/**
William M. Brack93d004f2004-02-03 00:14:10 +00004007* xmlTextReaderSetStructuredErrorHandler:
4008 * @reader: the xmlTextReaderPtr used
4009 * @f: the callback function to call on error and warnings
4010 * @arg: a user argument to pass to the callback function
4011 *
4012 * Register a callback function that will be called on error and warnings.
4013 *
4014 * If @f is NULL, the default error and warning handlers are restored.
4015 */
4016void
4017xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4018 xmlStructuredErrorFunc f,
4019 void *arg) {
4020 if (f != NULL) {
4021 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4022 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4023 reader->ctxt->sax->warning = xmlTextReaderWarning;
4024 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4025 reader->sErrorFunc = f;
4026 reader->errorFunc = NULL;
4027 reader->errorFuncArg = arg;
4028 }
4029 else {
4030 /* restore defaults */
4031 reader->ctxt->sax->error = xmlParserError;
4032 reader->ctxt->sax->serror = NULL;
4033 reader->ctxt->vctxt.error = xmlParserValidityError;
4034 reader->ctxt->sax->warning = xmlParserWarning;
4035 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4036 reader->errorFunc = NULL;
4037 reader->sErrorFunc = NULL;
4038 reader->errorFuncArg = NULL;
4039 }
4040}
4041
4042/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004043 * xmlTextReaderIsValid:
4044 * @reader: the xmlTextReaderPtr used
4045 *
4046 * Retrieve the validity status from the parser context
4047 *
4048 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4049 */
4050int
4051xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00004052 if (reader == NULL) return(-1);
4053#ifdef LIBXML_SCHEMAS_ENABLED
4054 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
4055 return(reader->rngValidErrors == 0);
4056#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004057 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00004058 return(reader->ctxt->valid);
4059 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004060}
4061
4062/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004063 * xmlTextReaderGetErrorHandler:
4064 * @reader: the xmlTextReaderPtr used
4065 * @f: the callback function or NULL is no callback has been registered
4066 * @arg: a user argument
4067 *
4068 * Retrieve the error callback function and user argument.
4069 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004070void
4071xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4072 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004073 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004074 *f = reader->errorFunc;
4075 *arg = reader->errorFuncArg;
4076}
4077
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004078
4079/************************************************************************
4080 * *
4081 * New set (2.6.0) of simpler and more flexible APIs *
4082 * *
4083 ************************************************************************/
4084
4085/**
4086 * xmlTextReaderSetup:
4087 * @reader: an XML reader
4088 * @URL: the base URL to use for the document
4089 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004090 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004091 * @reuse: keep the context for reuse
4092 *
4093 * Setup an XML reader with new options
4094 *
4095 * Returns 0 in case of success and -1 in case of error.
4096 */
4097static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004098xmlTextReaderSetup(xmlTextReaderPtr reader,
4099 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004100 const char *encoding, int options)
4101{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004102 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004103 return (-1);
4104
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004105 reader->doc = NULL;
4106 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004107 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004108 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004109 if ((input != NULL) && (reader->input != NULL) &&
4110 (reader->allocs & XML_TEXTREADER_INPUT)) {
4111 xmlFreeParserInputBuffer(reader->input);
4112 reader->input = NULL;
4113 reader->allocs -= XML_TEXTREADER_INPUT;
4114 }
4115 if (input != NULL) {
4116 reader->input = input;
4117 reader->allocs |= XML_TEXTREADER_INPUT;
4118 }
4119 if (reader->buffer == NULL)
4120 reader->buffer = xmlBufferCreateSize(100);
4121 if (reader->buffer == NULL) {
4122 xmlGenericError(xmlGenericErrorContext,
4123 "xmlTextReaderSetup : malloc failed\n");
4124 return (-1);
4125 }
4126 if (reader->sax == NULL)
4127 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4128 if (reader->sax == NULL) {
4129 xmlGenericError(xmlGenericErrorContext,
4130 "xmlTextReaderSetup : malloc failed\n");
4131 return (-1);
4132 }
4133 xmlSAXVersion(reader->sax, 2);
4134 reader->startElement = reader->sax->startElement;
4135 reader->sax->startElement = xmlTextReaderStartElement;
4136 reader->endElement = reader->sax->endElement;
4137 reader->sax->endElement = xmlTextReaderEndElement;
4138#ifdef LIBXML_SAX1_ENABLED
4139 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4140#endif /* LIBXML_SAX1_ENABLED */
4141 reader->startElementNs = reader->sax->startElementNs;
4142 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4143 reader->endElementNs = reader->sax->endElementNs;
4144 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4145#ifdef LIBXML_SAX1_ENABLED
4146 } else {
4147 reader->startElementNs = NULL;
4148 reader->endElementNs = NULL;
4149 }
4150#endif /* LIBXML_SAX1_ENABLED */
4151 reader->characters = reader->sax->characters;
4152 reader->sax->characters = xmlTextReaderCharacters;
4153 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4154 reader->cdataBlock = reader->sax->cdataBlock;
4155 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4156
4157 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4158 reader->node = NULL;
4159 reader->curnode = NULL;
4160 if (input != NULL) {
4161 if (reader->input->buffer->use < 4) {
4162 xmlParserInputBufferRead(input, 4);
4163 }
4164 if (reader->ctxt == NULL) {
4165 if (reader->input->buffer->use >= 4) {
4166 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4167 (const char *) reader->input->buffer->content, 4, URL);
4168 reader->base = 0;
4169 reader->cur = 4;
4170 } else {
4171 reader->ctxt =
4172 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4173 reader->base = 0;
4174 reader->cur = 0;
4175 }
4176 } else {
4177 xmlParserInputPtr inputStream;
4178 xmlParserInputBufferPtr buf;
4179 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4180
4181 if (reader->ctxt->myDoc != NULL)
4182 xmlDictReference(reader->ctxt->myDoc->dict);
4183 xmlCtxtReset(reader->ctxt);
4184 buf = xmlAllocParserInputBuffer(enc);
4185 if (buf == NULL) return(-1);
4186 inputStream = xmlNewInputStream(reader->ctxt);
4187 if (inputStream == NULL) {
4188 xmlFreeParserInputBuffer(buf);
4189 return(-1);
4190 }
4191
4192 if (URL == NULL)
4193 inputStream->filename = NULL;
4194 else
4195 inputStream->filename = (char *)
4196 xmlCanonicPath((const xmlChar *) URL);
4197 inputStream->buf = buf;
4198 inputStream->base = inputStream->buf->buffer->content;
4199 inputStream->cur = inputStream->buf->buffer->content;
4200 inputStream->end =
4201 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4202
4203 inputPush(reader->ctxt, inputStream);
4204 reader->cur = 0;
4205 }
4206 if (reader->ctxt == NULL) {
4207 xmlGenericError(xmlGenericErrorContext,
4208 "xmlTextReaderSetup : malloc failed\n");
4209 return (-1);
4210 }
4211 }
4212 if (reader->dict != NULL) {
4213 if (reader->ctxt->dict != NULL) {
4214 if (reader->dict != reader->ctxt->dict) {
4215 xmlDictFree(reader->dict);
4216 reader->dict = reader->ctxt->dict;
4217 }
4218 } else {
4219 reader->ctxt->dict = reader->dict;
4220 }
4221 } else {
4222 if (reader->ctxt->dict == NULL)
4223 reader->ctxt->dict = xmlDictCreate();
4224 reader->dict = reader->ctxt->dict;
4225 }
4226 reader->ctxt->_private = reader;
4227 reader->ctxt->linenumbers = 1;
4228 reader->ctxt->dictNames = 1;
4229 /*
4230 * use the parser dictionnary to allocate all elements and attributes names
4231 */
4232 reader->ctxt->docdict = 1;
4233
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004234#ifdef LIBXML_XINCLUDE_ENABLED
4235 if (reader->xincctxt != NULL) {
4236 xmlXIncludeFreeContext(reader->xincctxt);
4237 reader->xincctxt = NULL;
4238 }
4239 if (options & XML_PARSE_XINCLUDE) {
4240 reader->xinclude = 1;
4241 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4242 options -= XML_PARSE_XINCLUDE;
4243 } else
4244 reader->xinclude = 0;
4245 reader->in_xinclude = 0;
4246#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004247#ifdef LIBXML_PATTERN_ENABLED
4248 if (reader->patternTab == NULL) {
4249 reader->patternNr = 0;
4250 reader->patternMax = 0;
4251 }
4252 while (reader->patternNr > 0) {
4253 reader->patternNr--;
4254 if (reader->patternTab[reader->patternNr] != NULL) {
4255 xmlFreePattern(reader->patternTab[reader->patternNr]);
4256 reader->patternTab[reader->patternNr] = NULL;
4257 }
4258 }
4259#endif
4260
Daniel Veillardc36965d2003-12-02 10:28:48 +00004261 if (options & XML_PARSE_DTDVALID)
4262 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4263
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004264 xmlCtxtUseOptions(reader->ctxt, options);
4265 if (encoding != NULL) {
4266 xmlCharEncodingHandlerPtr hdlr;
4267
4268 hdlr = xmlFindCharEncodingHandler(encoding);
4269 if (hdlr != NULL)
4270 xmlSwitchToEncoding(reader->ctxt, hdlr);
4271 }
4272 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4273 (reader->ctxt->input->filename == NULL))
4274 reader->ctxt->input->filename = (char *)
4275 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004276
4277 reader->doc = NULL;
4278
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004279 return (0);
4280}
4281
4282/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004283 * xmlReaderWalker:
4284 * @doc: a preparsed document
4285 *
4286 * Create an xmltextReader for a preparsed document.
4287 *
4288 * Returns the new reader or NULL in case of error.
4289 */
4290xmlTextReaderPtr
4291xmlReaderWalker(xmlDocPtr doc)
4292{
4293 xmlTextReaderPtr ret;
4294
4295 if (doc == NULL)
4296 return(NULL);
4297
4298 ret = xmlMalloc(sizeof(xmlTextReader));
4299 if (ret == NULL) {
4300 xmlGenericError(xmlGenericErrorContext,
4301 "xmlNewTextReader : malloc failed\n");
4302 return(NULL);
4303 }
4304 memset(ret, 0, sizeof(xmlTextReader));
4305 ret->entNr = 0;
4306 ret->input = NULL;
4307 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4308 ret->node = NULL;
4309 ret->curnode = NULL;
4310 ret->base = 0;
4311 ret->cur = 0;
4312 ret->allocs = XML_TEXTREADER_CTXT;
4313 ret->doc = doc;
4314 ret->state = XML_TEXTREADER_START;
4315 ret->dict = xmlDictCreate();
4316 return(ret);
4317}
4318
4319/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004320 * xmlReaderForDoc:
4321 * @cur: a pointer to a zero terminated string
4322 * @URL: the base URL to use for the document
4323 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004324 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004325 *
4326 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004327 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004328 *
4329 * Returns the new reader or NULL in case of error.
4330 */
4331xmlTextReaderPtr
4332xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4333 int options)
4334{
4335 int len;
4336
4337 if (cur == NULL)
4338 return (NULL);
4339 len = xmlStrlen(cur);
4340
4341 return (xmlReaderForMemory
4342 ((const char *) cur, len, URL, encoding, options));
4343}
4344
4345/**
4346 * xmlReaderForFile:
4347 * @filename: a file or URL
4348 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004349 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004350 *
4351 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004352 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004353 *
4354 * Returns the new reader or NULL in case of error.
4355 */
4356xmlTextReaderPtr
4357xmlReaderForFile(const char *filename, const char *encoding, int options)
4358{
4359 xmlTextReaderPtr reader;
4360
4361 reader = xmlNewTextReaderFilename(filename);
4362 if (reader == NULL)
4363 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004364 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004365 return (reader);
4366}
4367
4368/**
4369 * xmlReaderForMemory:
4370 * @buffer: a pointer to a char array
4371 * @size: the size of the array
4372 * @URL: the base URL to use for the document
4373 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004374 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004375 *
4376 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004377 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004378 *
4379 * Returns the new reader or NULL in case of error.
4380 */
4381xmlTextReaderPtr
4382xmlReaderForMemory(const char *buffer, int size, const char *URL,
4383 const char *encoding, int options)
4384{
4385 xmlTextReaderPtr reader;
4386 xmlParserInputBufferPtr buf;
4387
Daniel Veillard21924522004-02-19 16:37:07 +00004388 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004389 XML_CHAR_ENCODING_NONE);
4390 if (buf == NULL) {
4391 return (NULL);
4392 }
4393 reader = xmlNewTextReader(buf, URL);
4394 if (reader == NULL) {
4395 xmlFreeParserInputBuffer(buf);
4396 return (NULL);
4397 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004398 reader->allocs |= XML_TEXTREADER_INPUT;
4399 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004400 return (reader);
4401}
4402
4403/**
4404 * xmlReaderForFd:
4405 * @fd: an open file descriptor
4406 * @URL: the base URL to use for the document
4407 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004408 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004409 *
4410 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004411 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004412 * NOTE that the file descriptor will not be closed when the
4413 * reader is closed or reset.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004414 *
4415 * Returns the new reader or NULL in case of error.
4416 */
4417xmlTextReaderPtr
4418xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4419{
4420 xmlTextReaderPtr reader;
4421 xmlParserInputBufferPtr input;
4422
4423 if (fd < 0)
4424 return (NULL);
4425
4426 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4427 if (input == NULL)
4428 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004429 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004430 reader = xmlNewTextReader(input, URL);
4431 if (reader == NULL) {
4432 xmlFreeParserInputBuffer(input);
4433 return (NULL);
4434 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004435 reader->allocs |= XML_TEXTREADER_INPUT;
4436 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004437 return (reader);
4438}
4439
4440/**
4441 * xmlReaderForIO:
4442 * @ioread: an I/O read function
4443 * @ioclose: an I/O close function
4444 * @ioctx: an I/O handler
4445 * @URL: the base URL to use for the document
4446 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004447 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004448 *
4449 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004450 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004451 *
4452 * Returns the new reader or NULL in case of error.
4453 */
4454xmlTextReaderPtr
4455xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4456 void *ioctx, const char *URL, const char *encoding,
4457 int options)
4458{
4459 xmlTextReaderPtr reader;
4460 xmlParserInputBufferPtr input;
4461
4462 if (ioread == NULL)
4463 return (NULL);
4464
4465 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4466 XML_CHAR_ENCODING_NONE);
4467 if (input == NULL)
4468 return (NULL);
4469 reader = xmlNewTextReader(input, URL);
4470 if (reader == NULL) {
4471 xmlFreeParserInputBuffer(input);
4472 return (NULL);
4473 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004474 reader->allocs |= XML_TEXTREADER_INPUT;
4475 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004476 return (reader);
4477}
4478
4479/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004480 * xmlReaderNewWalker:
4481 * @reader: an XML reader
4482 * @doc: a preparsed document
4483 *
4484 * Setup an xmltextReader to parse a preparsed XML document.
4485 * This reuses the existing @reader xmlTextReader.
4486 *
4487 * Returns 0 in case of success and -1 in case of error
4488 */
4489int
4490xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4491{
4492 if (doc == NULL)
4493 return (-1);
4494 if (reader == NULL)
4495 return (-1);
4496
4497 if (reader->ctxt != NULL) {
4498 xmlCtxtReset(reader->ctxt);
4499 }
4500
4501 reader->entNr = 0;
4502 reader->input = NULL;
4503 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4504 reader->node = NULL;
4505 reader->curnode = NULL;
4506 reader->base = 0;
4507 reader->cur = 0;
4508 reader->allocs = XML_TEXTREADER_CTXT;
4509 reader->doc = doc;
4510 reader->state = XML_TEXTREADER_START;
4511 if (reader->dict == NULL) {
4512 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4513 reader->dict = reader->ctxt->dict;
4514 else
4515 reader->dict = xmlDictCreate();
4516 }
4517 return(0);
4518}
4519
4520/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004521 * xmlReaderNewDoc:
4522 * @reader: an XML reader
4523 * @cur: a pointer to a zero terminated string
4524 * @URL: the base URL to use for the document
4525 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004526 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004527 *
4528 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004529 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004530 * This reuses the existing @reader xmlTextReader.
4531 *
4532 * Returns 0 in case of success and -1 in case of error
4533 */
4534int
4535xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4536 const char *URL, const char *encoding, int options)
4537{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004538
4539 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004540
4541 if (cur == NULL)
4542 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004543 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004544 return (-1);
4545
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004546 len = xmlStrlen(cur);
4547 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4548 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004549}
4550
4551/**
4552 * xmlReaderNewFile:
4553 * @reader: an XML reader
4554 * @filename: a file or URL
4555 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004556 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004557 *
4558 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004559 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004560 * This reuses the existing @reader xmlTextReader.
4561 *
4562 * Returns 0 in case of success and -1 in case of error
4563 */
4564int
4565xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4566 const char *encoding, int options)
4567{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004568 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004569
4570 if (filename == NULL)
4571 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004572 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004573 return (-1);
4574
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004575 input =
4576 xmlParserInputBufferCreateFilename(filename,
4577 XML_CHAR_ENCODING_NONE);
4578 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004579 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004580 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004581}
4582
4583/**
4584 * xmlReaderNewMemory:
4585 * @reader: an XML reader
4586 * @buffer: a pointer to a char array
4587 * @size: the size of the array
4588 * @URL: the base URL to use for the document
4589 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004590 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004591 *
4592 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004593 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004594 * This reuses the existing @reader xmlTextReader.
4595 *
4596 * Returns 0 in case of success and -1 in case of error
4597 */
4598int
4599xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4600 const char *URL, const char *encoding, int options)
4601{
4602 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004603
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004604 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004605 return (-1);
4606 if (buffer == NULL)
4607 return (-1);
4608
Daniel Veillard21924522004-02-19 16:37:07 +00004609 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004610 XML_CHAR_ENCODING_NONE);
4611 if (input == NULL) {
4612 return (-1);
4613 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004614 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004615}
4616
4617/**
4618 * xmlReaderNewFd:
4619 * @reader: an XML reader
4620 * @fd: an open file descriptor
4621 * @URL: the base URL to use for the document
4622 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004623 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004624 *
4625 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004626 * NOTE that the file descriptor will not be closed when the
4627 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004628 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004629 * This reuses the existing @reader xmlTextReader.
4630 *
4631 * Returns 0 in case of success and -1 in case of error
4632 */
4633int
4634xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4635 const char *URL, const char *encoding, int options)
4636{
4637 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004638
4639 if (fd < 0)
4640 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004641 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004642 return (-1);
4643
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004644 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4645 if (input == NULL)
4646 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00004647 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004648 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004649}
4650
4651/**
4652 * xmlReaderNewIO:
4653 * @reader: an XML reader
4654 * @ioread: an I/O read function
4655 * @ioclose: an I/O close function
4656 * @ioctx: an I/O handler
4657 * @URL: the base URL to use for the document
4658 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004659 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004660 *
4661 * Setup an xmltextReader to parse an XML document from I/O functions
4662 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00004663 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004664 * This reuses the existing @reader xmlTextReader.
4665 *
4666 * Returns 0 in case of success and -1 in case of error
4667 */
4668int
4669xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4670 xmlInputCloseCallback ioclose, void *ioctx,
4671 const char *URL, const char *encoding, int options)
4672{
4673 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004674
4675 if (ioread == NULL)
4676 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004677 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004678 return (-1);
4679
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004680 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4681 XML_CHAR_ENCODING_NONE);
4682 if (input == NULL)
4683 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004684 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004685}
Daniel Veillard26f70262003-01-16 22:45:08 +00004686/************************************************************************
4687 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004688 * Utilities *
4689 * *
4690 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004691#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004692/**
4693 * xmlBase64Decode:
4694 * @in: the input buffer
4695 * @inlen: the size of the input (in), the size read from it (out)
4696 * @to: the output buffer
4697 * @tolen: the size of the output (in), the size written to (out)
4698 *
4699 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004700 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004701 *
4702 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4703 * 2 if there wasn't enough space on the output or -1 in case of error.
4704 */
4705static int
4706xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4707 unsigned char *to, unsigned long *tolen) {
4708 unsigned long incur; /* current index in in[] */
4709 unsigned long inblk; /* last block index in in[] */
4710 unsigned long outcur; /* current index in out[] */
4711 unsigned long inmax; /* size of in[] */
4712 unsigned long outmax; /* size of out[] */
4713 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004714 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004715 int nbintmp; /* number of byte in intmp[] */
4716 int is_ignore; /* cur should be ignored */
4717 int is_end = 0; /* the end of the base64 was found */
4718 int retval = 1;
4719 int i;
4720
4721 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4722 return(-1);
4723
4724 incur = 0;
4725 inblk = 0;
4726 outcur = 0;
4727 inmax = *inlen;
4728 outmax = *tolen;
4729 nbintmp = 0;
4730
4731 while (1) {
4732 if (incur >= inmax)
4733 break;
4734 cur = in[incur++];
4735 is_ignore = 0;
4736 if ((cur >= 'A') && (cur <= 'Z'))
4737 cur = cur - 'A';
4738 else if ((cur >= 'a') && (cur <= 'z'))
4739 cur = cur - 'a' + 26;
4740 else if ((cur >= '0') && (cur <= '9'))
4741 cur = cur - '0' + 52;
4742 else if (cur == '+')
4743 cur = 62;
4744 else if (cur == '/')
4745 cur = 63;
4746 else if (cur == '.')
4747 cur = 0;
4748 else if (cur == '=') /*no op , end of the base64 stream */
4749 is_end = 1;
4750 else {
4751 is_ignore = 1;
4752 if (nbintmp == 0)
4753 inblk = incur;
4754 }
4755
4756 if (!is_ignore) {
4757 int nbouttmp = 3;
4758 int is_break = 0;
4759
4760 if (is_end) {
4761 if (nbintmp == 0)
4762 break;
4763 if ((nbintmp == 1) || (nbintmp == 2))
4764 nbouttmp = 1;
4765 else
4766 nbouttmp = 2;
4767 nbintmp = 3;
4768 is_break = 1;
4769 }
4770 intmp[nbintmp++] = cur;
4771 /*
4772 * if intmp is full, push the 4byte sequence as a 3 byte
4773 * sequence out
4774 */
4775 if (nbintmp == 4) {
4776 nbintmp = 0;
4777 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4778 outtmp[1] =
4779 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4780 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4781 if (outcur + 3 >= outmax) {
4782 retval = 2;
4783 break;
4784 }
4785
4786 for (i = 0; i < nbouttmp; i++)
4787 to[outcur++] = outtmp[i];
4788 inblk = incur;
4789 }
4790
4791 if (is_break) {
4792 retval = 0;
4793 break;
4794 }
4795 }
4796 }
4797
4798 *tolen = outcur;
4799 *inlen = inblk;
4800 return (retval);
4801}
4802
4803/*
4804 * Test routine for the xmlBase64Decode function
4805 */
4806#if 0
4807int main(int argc, char **argv) {
4808 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4809 char output[100];
4810 char output2[100];
4811 char output3[100];
4812 unsigned long inlen = strlen(input);
4813 unsigned long outlen = 100;
4814 int ret;
4815 unsigned long cons, tmp, tmp2, prod;
4816
4817 /*
4818 * Direct
4819 */
4820 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4821
4822 output[outlen] = 0;
4823 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4824
4825 /*
4826 * output chunking
4827 */
4828 cons = 0;
4829 prod = 0;
4830 while (cons < inlen) {
4831 tmp = 5;
4832 tmp2 = inlen - cons;
4833
4834 printf("%ld %ld\n", cons, prod);
4835 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4836 cons += tmp2;
4837 prod += tmp;
4838 printf("%ld %ld\n", cons, prod);
4839 }
4840 output2[outlen] = 0;
4841 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4842
4843 /*
4844 * input chunking
4845 */
4846 cons = 0;
4847 prod = 0;
4848 while (cons < inlen) {
4849 tmp = 100 - prod;
4850 tmp2 = inlen - cons;
4851 if (tmp2 > 5)
4852 tmp2 = 5;
4853
4854 printf("%ld %ld\n", cons, prod);
4855 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4856 cons += tmp2;
4857 prod += tmp;
4858 printf("%ld %ld\n", cons, prod);
4859 }
4860 output3[outlen] = 0;
4861 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4862 return(0);
4863
4864}
4865#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004866#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004867#endif /* LIBXML_READER_ENABLED */