blob: 485859e6c1377880a9e594e5a5c7825ca2948be5 [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard7704fb12003-01-03 16:19:51 +000015 * - provide an API to preserve part of the tree
16 * - Streaming XInclude support
Daniel Veillard067bae52003-01-05 01:27:54 +000017 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000018 * - setting(s) for NoBlanks
19 * - performances and tuning ...
20 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#define IN_LIBXML
22#include "libxml.h"
23
Daniel Veillard81273902003-09-30 00:43:48 +000024#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000026#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000027
28#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#include <libxml/xmlmemory.h>
36#include <libxml/xmlIO.h>
37#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000038#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000039#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000040#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000041#ifdef LIBXML_XINCLUDE_ENABLED
42#include <libxml/xinclude.h>
43#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000047
48/* #define DEBUG_CALLBACKS */
49/* #define DEBUG_READER */
50
51/**
52 * TODO:
53 *
54 * macro to flag unimplemented blocks
55 */
56#define TODO \
57 xmlGenericError(xmlGenericErrorContext, \
58 "Unimplemented block at %s:%d\n", \
59 __FILE__, __LINE__);
60
61#ifdef DEBUG_READER
62#define DUMP_READER xmlTextReaderDebug(reader);
63#else
64#define DUMP_READER
65#endif
66
Daniel Veillarda880b122003-04-21 21:36:41 +000067#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000068/************************************************************************
69 * *
70 * The parser: maps the Text Reader API on top of the existing *
71 * parsing routines building a tree *
72 * *
73 ************************************************************************/
74
75#define XML_TEXTREADER_INPUT 1
76#define XML_TEXTREADER_CTXT 2
77
78typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000079 XML_TEXTREADER_MODE_INITIAL = 0,
80 XML_TEXTREADER_MODE_INTERACTIVE = 1,
81 XML_TEXTREADER_MODE_ERROR = 2,
82 XML_TEXTREADER_MODE_EOF =3,
83 XML_TEXTREADER_MODE_CLOSED = 4,
84 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000085} xmlTextReaderMode;
86
87typedef enum {
88 XML_TEXTREADER_NONE = -1,
89 XML_TEXTREADER_START= 0,
90 XML_TEXTREADER_ELEMENT= 1,
91 XML_TEXTREADER_END= 2,
92 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000093 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000094 XML_TEXTREADER_DONE= 5,
95 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000096} xmlTextReaderState;
97
Daniel Veillardf4e55762003-04-15 23:32:22 +000098typedef enum {
99 XML_TEXTREADER_NOT_VALIDATE = 0,
100 XML_TEXTREADER_VALIDATE_DTD = 1,
101 XML_TEXTREADER_VALIDATE_RNG = 2
102} xmlTextReaderValidate;
103
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000104struct _xmlTextReader {
105 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000106 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000107 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000108 int allocs; /* what structure were deallocated */
109 xmlTextReaderState state;
110 xmlParserCtxtPtr ctxt; /* the parser context */
111 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
112 xmlParserInputBufferPtr input; /* the input */
113 startElementSAXFunc startElement;/* initial SAX callbacks */
114 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000115 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000117 charactersSAXFunc characters;
118 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000119 unsigned int base; /* base of the segment in the input */
120 unsigned int cur; /* current position in the input */
121 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000122 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000123 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000124 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000125 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000126 xmlBufferPtr buffer; /* used to return const xmlChar * */
127 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000128
129 /* entity stack when traversing entities content */
130 xmlNodePtr ent; /* Current Entity Ref Node */
131 int entNr; /* Depth of the entities stack */
132 int entMax; /* Max depth of the entities stack */
133 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000134
135 /* error handling */
136 xmlTextReaderErrorFunc errorFunc; /* callback function */
137 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000138
139#ifdef LIBXML_SCHEMAS_ENABLED
140 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000141 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
142 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
143 int rngValidErrors;/* The number of errors detected */
144 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
145#endif
146#ifdef LIBXML_XINCLUDE_ENABLED
147 /* Handling of XInclude processing */
148 int xinclude; /* is xinclude asked for */
149 const xmlChar * xinclude_name; /* the xinclude name from dict */
150 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
151 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000152#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000153#ifdef LIBXML_PATTERN_ENABLED
154 int patternNr; /* number of preserve patterns */
155 int patternMax; /* max preserve patterns */
156 xmlPatternPtr *patternTab; /* array of preserve patterns */
157#endif
158 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000159 int parserFlags; /* the set of options set */
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;
795 if ((oldstate != XML_TEXTREADER_START) ||
796 (reader->ctxt->myDoc != NULL))
797 return(val);
798 }
799 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000800 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000801 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000802 if ((oldstate != XML_TEXTREADER_START) ||
803 (reader->ctxt->myDoc != NULL))
804 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000805 } else if (val == 0) {
806 /* mark the end of the stream and process the remains */
807 reader->mode = XML_TEXTREADER_MODE_EOF;
808 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000809 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000810
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000811 } else
812 break;
813 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000814 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000815 * parse by block of CHUNK_SIZE bytes, various tests show that
816 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000817 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000818 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000819 val = xmlParseChunk(reader->ctxt,
820 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000821 CHUNK_SIZE, 0);
822 reader->cur += CHUNK_SIZE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000823 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000824 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000825 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000826 s = inbuf->use - reader->cur;
827 val = xmlParseChunk(reader->ctxt,
828 (const char *) &inbuf->content[reader->cur],
829 s, 0);
830 reader->cur += s;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000831 if ((val != 0) && (reader->ctxt->wellFormed == 0))
Daniel Veillarda880b122003-04-21 21:36:41 +0000832 return(-1);
833 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000834 }
835 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000836
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000837 /*
838 * Discard the consumed input when needed and possible
839 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000840 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000841 if ((reader->cur >= 4096) &&
842 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000843 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000844 if (val >= 0) {
845 reader->cur -= val;
846 }
847 }
848 }
849
850 /*
851 * At the end of the stream signal that the work is done to the Push
852 * parser.
853 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000854 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000855 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000856 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000857 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000858 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000859 s, 1);
860 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000861 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard16ed5972003-11-20 18:22:31 +0000862 if ((val != 0) && (reader->ctxt->wellFormed == 0))
863 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000864 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000865 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000866 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000867 return(0);
868}
869
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000870#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000871/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000872 * xmlTextReaderValidatePush:
873 * @reader: the xmlTextReaderPtr used
874 *
875 * Push the current node for validation
876 */
877static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000878xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000879 xmlNodePtr node = reader->node;
880
Daniel 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 }
898#ifdef LIBXML_SCHEMAS_ENABLED
899 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
900 (reader->rngValidCtxt != NULL)) {
901 int ret;
902
903 if (reader->rngFullNode != NULL) return;
904 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
905 reader->ctxt->myDoc,
906 node);
907 if (ret == 0) {
908 /*
909 * this element requires a full tree
910 */
911 node = xmlTextReaderExpand(reader);
912 if (node == NULL) {
913printf("Expand failed !\n");
914 ret = -1;
915 } else {
916 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
917 reader->ctxt->myDoc,
918 node);
919 reader->rngFullNode = node;
920 }
921 }
922 if (ret != 1)
923 reader->rngValidErrors++;
924#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000925 }
926}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000927
928/**
929 * xmlTextReaderValidateCData:
930 * @reader: the xmlTextReaderPtr used
931 * @data: pointer to the CData
932 * @len: lenght of the CData block in bytes.
933 *
934 * Push some CData for validation
935 */
936static void
937xmlTextReaderValidateCData(xmlTextReaderPtr reader,
938 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000939 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
940 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
941 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
942 data, len);
943#ifdef LIBXML_SCHEMAS_ENABLED
944 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
945 (reader->rngValidCtxt != NULL)) {
946 int ret;
947
948 if (reader->rngFullNode != NULL) return;
949 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
950 if (ret != 1)
951 reader->rngValidErrors++;
952#endif
953 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000954}
955
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000956/**
957 * xmlTextReaderValidatePop:
958 * @reader: the xmlTextReaderPtr used
959 *
960 * Pop the current node from validation
961 */
962static void
963xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
964 xmlNodePtr node = reader->node;
965
Daniel Veillardf4e55762003-04-15 23:32:22 +0000966 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
967 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
968 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
969 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
970 reader->ctxt->myDoc, node, node->name);
971 } else {
972 /* TODO use the BuildQName interface */
973 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000974
Daniel Veillardf4e55762003-04-15 23:32:22 +0000975 qname = xmlStrdup(node->ns->prefix);
976 qname = xmlStrcat(qname, BAD_CAST ":");
977 qname = xmlStrcat(qname, node->name);
978 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
979 reader->ctxt->myDoc, node, qname);
980 if (qname != NULL)
981 xmlFree(qname);
982 }
983#ifdef LIBXML_SCHEMAS_ENABLED
984 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
985 (reader->rngValidCtxt != NULL)) {
986 int ret;
987
988 if (reader->rngFullNode != NULL) {
989 if (node == reader->rngFullNode)
990 reader->rngFullNode = NULL;
991 return;
992 }
993 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
994 reader->ctxt->myDoc,
995 node);
996 if (ret != 1)
997 reader->rngValidErrors++;
998#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000999 }
1000}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001001
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001002/**
1003 * xmlTextReaderValidateEntity:
1004 * @reader: the xmlTextReaderPtr used
1005 *
1006 * Handle the validation when an entity reference is encountered and
1007 * entity substitution is not activated. As a result the parser interface
1008 * must walk through the entity and do the validation calls
1009 */
1010static void
1011xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1012 xmlNodePtr oldnode = reader->node;
1013 xmlNodePtr node = reader->node;
1014 xmlParserCtxtPtr ctxt = reader->ctxt;
1015
1016 do {
1017 if (node->type == XML_ENTITY_REF_NODE) {
1018 /*
1019 * Case where the underlying tree is not availble, lookup the entity
1020 * and walk it.
1021 */
1022 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1023 (ctxt->sax->getEntity != NULL)) {
1024 node->children = (xmlNodePtr)
1025 ctxt->sax->getEntity(ctxt, node->name);
1026 }
1027
1028 if ((node->children != NULL) &&
1029 (node->children->type == XML_ENTITY_DECL) &&
1030 (node->children->children != NULL)) {
1031 xmlTextReaderEntPush(reader, node);
1032 node = node->children->children;
1033 continue;
1034 } else {
1035 /*
1036 * The error has probably be raised already.
1037 */
1038 if (node == oldnode)
1039 break;
1040 node = node->next;
1041 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001042#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001043 } else if (node->type == XML_ELEMENT_NODE) {
1044 reader->node = node;
1045 xmlTextReaderValidatePush(reader);
1046 } else if ((node->type == XML_TEXT_NODE) ||
1047 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001048 xmlTextReaderValidateCData(reader, node->content,
1049 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001050#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001051 }
1052
1053 /*
1054 * go to next node
1055 */
1056 if (node->children != NULL) {
1057 node = node->children;
1058 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001059 } else if (node->type == XML_ELEMENT_NODE) {
1060 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001061 }
1062 if (node->next != NULL) {
1063 node = node->next;
1064 continue;
1065 }
1066 do {
1067 node = node->parent;
1068 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001069 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001070 if (reader->entNr == 0) {
1071 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001072 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001073 xmlUnlinkNode(tmp);
1074 xmlTextReaderFreeNode(reader, tmp);
1075 } else
1076 break;
1077 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001078 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001079 reader->node = node;
1080 xmlTextReaderValidatePop(reader);
1081 }
1082 if ((node->type == XML_ENTITY_DECL) &&
1083 (reader->ent != NULL) && (reader->ent->children == node)) {
1084 node = xmlTextReaderEntPop(reader);
1085 }
1086 if (node == oldnode)
1087 break;
1088 if (node->next != NULL) {
1089 node = node->next;
1090 break;
1091 }
1092 } while ((node != NULL) && (node != oldnode));
1093 } while ((node != NULL) && (node != oldnode));
1094 reader->node = oldnode;
1095}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001096#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001097
1098
1099/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001100 * xmlTextReaderGetSuccessor:
1101 * @cur: the current node
1102 *
1103 * Get the successor of a node if available.
1104 *
1105 * Returns the successor node or NULL
1106 */
1107static xmlNodePtr
1108xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1109 if (cur == NULL) return(NULL) ; /* ERROR */
1110 if (cur->next != NULL) return(cur->next) ;
1111 do {
1112 cur = cur->parent;
1113 if (cur == NULL) return(NULL);
1114 if (cur->next != NULL) return(cur->next);
1115 } while (cur != NULL);
1116 return(cur);
1117}
1118
1119/**
1120 * xmlTextReaderDoExpand:
1121 * @reader: the xmlTextReaderPtr used
1122 *
1123 * Makes sure that the current node is fully read as well as all its
1124 * descendant. It means the full DOM subtree must be available at the
1125 * end of the call.
1126 *
1127 * Returns 1 if the node was expanded successfully, 0 if there is no more
1128 * nodes to read, or -1 in case of error
1129 */
1130static int
1131xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1132 int val;
1133
1134 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1135 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001136 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001137 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1138
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001139 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1140 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001141 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001142 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001143 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1144 return(1);
1145 val = xmlTextReaderPushData(reader);
1146 if (val < 0)
1147 return(-1);
1148 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1149 return(1);
1150}
1151
1152/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001153 * xmlTextReaderRead:
1154 * @reader: the xmlTextReaderPtr used
1155 *
1156 * Moves the position of the current instance to the next node in
1157 * the stream, exposing its properties.
1158 *
1159 * Returns 1 if the node was read successfully, 0 if there is no more
1160 * nodes to read, or -1 in case of error
1161 */
1162int
1163xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001164 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001165 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001166 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001167
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001168
1169 if (reader == NULL)
1170 return(-1);
1171 if (reader->doc != NULL)
1172 return(xmlTextReaderReadTree(reader));
1173 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001174 return(-1);
1175 if (reader->ctxt->wellFormed != 1)
1176 return(-1);
1177
1178#ifdef DEBUG_READER
1179 fprintf(stderr, "\nREAD ");
1180 DUMP_READER
1181#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001182 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001183 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1184 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001185 /*
1186 * Initial state
1187 */
1188 do {
1189 val = xmlTextReaderPushData(reader);
1190 if (val < 0)
1191 return(-1);
1192 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001193 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1194 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001195 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001196 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001197 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001198 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001199 if (reader->node == NULL)
1200 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001201 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001202 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001203 if (reader->ctxt->myDoc != NULL) {
1204 reader->node = reader->ctxt->myDoc->children;
1205 }
1206 if (reader->node == NULL)
1207 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001208 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001209 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001210 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001211 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001212 }
1213 oldstate = reader->state;
1214 olddepth = reader->ctxt->nodeNr;
1215 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001216
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001217get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001218 /*
1219 * If we are not backtracking on ancestors or examined nodes,
1220 * that the parser didn't finished or that we arent at the end
1221 * of stream, continue processing.
1222 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001223 while ((reader->node->next == NULL) &&
1224 (reader->ctxt->nodeNr == olddepth) &&
1225 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001226 (reader->node->children == NULL) ||
1227 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001228 ((reader->node->children != NULL) &&
1229 (reader->node->children->type == XML_TEXT_NODE) &&
1230 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001231 (reader->node->type == XML_DTD_NODE) ||
1232 (reader->node->type == XML_DOCUMENT_NODE) ||
1233 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001234 ((reader->ctxt->node == NULL) ||
1235 (reader->ctxt->node == reader->node) ||
1236 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001237 (reader->ctxt->instate != XML_PARSER_EOF)) {
1238 val = xmlTextReaderPushData(reader);
1239 if (val < 0)
1240 return(-1);
1241 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001242 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001243 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001244 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001245 if ((reader->node->children != NULL) &&
1246 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001247 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001248 (reader->node->type != XML_DTD_NODE)) {
1249 reader->node = reader->node->children;
1250 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001251 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001252 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001253 }
1254 }
1255 if (reader->node->next != NULL) {
1256 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001257 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001258 (reader->node->children == NULL) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001259 ((reader->node->extra & NODE_IS_EMPTY) == 0) &&
1260 (reader->in_xinclude <= 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001261 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001262 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001264#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001265 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001266 (reader->node->type == XML_ELEMENT_NODE))
1267 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001268#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001269 if ((reader->preserves > 0) &&
1270 (reader->node->extra & NODE_IS_SPRESERVED))
1271 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001272 reader->node = reader->node->next;
1273 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001274
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001275 /*
1276 * Cleanup of the old node
1277 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001278 if ((reader->preserves == 0) &&
1279 (reader->in_xinclude == 0) &&
1280 (reader->entNr == 0) &&
1281 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001282 (reader->node->prev->type != XML_DTD_NODE) &&
1283 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001284 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001285 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001286 xmlUnlinkNode(tmp);
1287 xmlTextReaderFreeNode(reader, tmp);
1288 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001289 }
1290
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001291 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001292 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001293 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001294 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001295 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001296 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001297 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001298 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001299 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001300#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001301 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001302 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001303#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001304 if ((reader->preserves > 0) &&
1305 (reader->node->extra & NODE_IS_SPRESERVED))
1306 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001307 reader->node = reader->node->parent;
1308 if ((reader->node == NULL) ||
1309 (reader->node->type == XML_DOCUMENT_NODE) ||
1310#ifdef LIBXML_DOCB_ENABLED
1311 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1312#endif
1313 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001314 if (reader->mode != XML_TEXTREADER_DONE) {
1315 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1316 reader->mode = XML_TEXTREADER_DONE;
1317 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001318 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001319 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001320
1321 /*
1322 * Cleanup of the old node
1323 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001324 if ((reader->preserves == 0) &&
1325 (reader->in_xinclude == 0) &&
1326 (reader->entNr == 0) &&
1327 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001328 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001329 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001330 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001331 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001332 }
1333
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001334 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001335 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001336 if ((reader->preserves == 0) &&
1337 (reader->in_xinclude == 0) &&
1338 (reader->entNr == 0) &&
1339 (reader->node->last != NULL) &&
1340 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1341 xmlNodePtr tmp = reader->node->last;
1342 xmlUnlinkNode(tmp);
1343 xmlTextReaderFreeNode(reader, tmp);
1344 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001345 reader->depth--;
1346 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001347
1348node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001349 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001350
1351 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001352 * If we are in the middle of a piece of CDATA make sure it's finished
1353 */
1354 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001355 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001356 ((reader->node->type == XML_TEXT_NODE) ||
1357 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1358 xmlTextReaderExpand(reader);
1359 }
1360
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001361#ifdef LIBXML_XINCLUDE_ENABLED
1362 /*
1363 * Handle XInclude if asked for
1364 */
1365 if ((reader->xinclude) && (reader->node != NULL) &&
1366 (reader->node->type == XML_ELEMENT_NODE) &&
1367 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001368 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1369 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001370 if (reader->xincctxt == NULL) {
1371 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00001372 xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001373 }
1374 /*
1375 * expand that node and process it
1376 */
1377 xmlTextReaderExpand(reader);
1378 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1379 }
1380 if (reader->node->type == XML_XINCLUDE_START) {
1381 reader->in_xinclude++;
1382 goto get_next_node;
1383 }
1384 if (reader->node->type == XML_XINCLUDE_END) {
1385 reader->in_xinclude--;
1386 goto get_next_node;
1387 }
1388#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001389 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001390 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001391 */
1392 if ((reader->node != NULL) &&
1393 (reader->node->type == XML_ENTITY_REF_NODE) &&
1394 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1395 /*
1396 * Case where the underlying tree is not availble, lookup the entity
1397 * and walk it.
1398 */
1399 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1400 (reader->ctxt->sax->getEntity != NULL)) {
1401 reader->node->children = (xmlNodePtr)
1402 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1403 }
1404
1405 if ((reader->node->children != NULL) &&
1406 (reader->node->children->type == XML_ENTITY_DECL) &&
1407 (reader->node->children->children != NULL)) {
1408 xmlTextReaderEntPush(reader, reader->node);
1409 reader->node = reader->node->children->children;
1410 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001411#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001412 } else if ((reader->node != NULL) &&
1413 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001414 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001415 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001416#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001417 }
1418 if ((reader->node != NULL) &&
1419 (reader->node->type == XML_ENTITY_DECL) &&
1420 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1421 reader->node = xmlTextReaderEntPop(reader);
1422 reader->depth++;
1423 goto get_next_node;
1424 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001425#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001426 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001427 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001428
1429 if ((node->type == XML_ELEMENT_NODE) &&
1430 ((reader->state != XML_TEXTREADER_END) &&
1431 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1432 xmlTextReaderValidatePush(reader);
1433 } else if ((node->type == XML_TEXT_NODE) ||
1434 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001435 xmlTextReaderValidateCData(reader, node->content,
1436 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001437 }
1438 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001439#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001440#ifdef LIBXML_PATTERN_ENABLED
1441 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1442 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1443 int i;
1444 for (i = 0;i < reader->patternNr;i++) {
1445 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1446 xmlTextReaderPreserve(reader);
1447 break;
1448 }
1449 }
1450 }
1451#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001452 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001453node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001454 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001455 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001456}
1457
Daniel Veillard67df8092002-12-16 22:04:11 +00001458/**
1459 * xmlTextReaderReadState:
1460 * @reader: the xmlTextReaderPtr used
1461 *
1462 * Gets the read state of the reader.
1463 *
1464 * Returns the state value, or -1 in case of error
1465 */
1466int
1467xmlTextReaderReadState(xmlTextReaderPtr reader) {
1468 if (reader == NULL)
1469 return(-1);
1470 return(reader->mode);
1471}
1472
1473/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001474 * xmlTextReaderExpand:
1475 * @reader: the xmlTextReaderPtr used
1476 *
1477 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001478 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001479 *
1480 * Returns a node pointer valid until the next xmlTextReaderRead() call
1481 * or NULL in case of error.
1482 */
1483xmlNodePtr
1484xmlTextReaderExpand(xmlTextReaderPtr reader) {
1485 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1486 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001487 if (reader->doc != NULL)
1488 return(reader->node);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001489 if (xmlTextReaderDoExpand(reader) < 0)
1490 return(NULL);
1491 return(reader->node);
1492}
1493
1494/**
1495 * xmlTextReaderNext:
1496 * @reader: the xmlTextReaderPtr used
1497 *
1498 * Skip to the node following the current one in document order while
1499 * avoiding the subtree if any.
1500 *
1501 * Returns 1 if the node was read successfully, 0 if there is no more
1502 * nodes to read, or -1 in case of error
1503 */
1504int
1505xmlTextReaderNext(xmlTextReaderPtr reader) {
1506 int ret;
1507 xmlNodePtr cur;
1508
1509 if (reader == NULL)
1510 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001511 if (reader->doc != NULL)
1512 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001513 cur = reader->node;
1514 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1515 return(xmlTextReaderRead(reader));
1516 if (reader->state == XML_TEXTREADER_END)
1517 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001518 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001519 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001520 do {
1521 ret = xmlTextReaderRead(reader);
1522 if (ret != 1)
1523 return(ret);
1524 } while (reader->node != cur);
1525 return(xmlTextReaderRead(reader));
1526}
1527
1528/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001529 * xmlTextReaderReadInnerXml:
1530 * @reader: the xmlTextReaderPtr used
1531 *
1532 * Reads the contents of the current node, including child nodes and markup.
1533 *
1534 * Returns a string containing the XML content, or NULL if the current node
1535 * is neither an element nor attribute, or has no child nodes. The
1536 * string must be deallocated by the caller.
1537 */
1538xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001539xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001540 TODO
1541 return(NULL);
1542}
1543
1544/**
1545 * xmlTextReaderReadOuterXml:
1546 * @reader: the xmlTextReaderPtr used
1547 *
1548 * Reads the contents of the current node, including child nodes and markup.
1549 *
1550 * Returns a string containing the XML content, or NULL if the current node
1551 * is neither an element nor attribute, or has no child nodes. The
1552 * string must be deallocated by the caller.
1553 */
1554xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001555xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001556 TODO
1557 return(NULL);
1558}
1559
1560/**
1561 * xmlTextReaderReadString:
1562 * @reader: the xmlTextReaderPtr used
1563 *
1564 * Reads the contents of an element or a text node as a string.
1565 *
1566 * Returns a string containing the contents of the Element or Text node,
1567 * or NULL if the reader is positioned on any other type of node.
1568 * The string must be deallocated by the caller.
1569 */
1570xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001571xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001572 TODO
1573 return(NULL);
1574}
1575
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001576#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001577/**
1578 * xmlTextReaderReadBase64:
1579 * @reader: the xmlTextReaderPtr used
1580 * @array: a byte array to store the content.
1581 * @offset: the zero-based index into array where the method should
1582 * begin to write.
1583 * @len: the number of bytes to write.
1584 *
1585 * Reads and decodes the Base64 encoded contents of an element and
1586 * stores the result in a byte buffer.
1587 *
1588 * Returns the number of bytes written to array, or zero if the current
1589 * instance is not positioned on an element or -1 in case of error.
1590 */
1591int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001592xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1593 unsigned char *array ATTRIBUTE_UNUSED,
1594 int offset ATTRIBUTE_UNUSED,
1595 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001596 if ((reader == NULL) || (reader->ctxt == NULL))
1597 return(-1);
1598 if (reader->ctxt->wellFormed != 1)
1599 return(-1);
1600
1601 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1602 return(0);
1603 TODO
1604 return(0);
1605}
1606
1607/**
1608 * xmlTextReaderReadBinHex:
1609 * @reader: the xmlTextReaderPtr used
1610 * @array: a byte array to store the content.
1611 * @offset: the zero-based index into array where the method should
1612 * begin to write.
1613 * @len: the number of bytes to write.
1614 *
1615 * Reads and decodes the BinHex encoded contents of an element and
1616 * stores the result in a byte buffer.
1617 *
1618 * Returns the number of bytes written to array, or zero if the current
1619 * instance is not positioned on an element or -1 in case of error.
1620 */
1621int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001622xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1623 unsigned char *array ATTRIBUTE_UNUSED,
1624 int offset ATTRIBUTE_UNUSED,
1625 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001626 if ((reader == NULL) || (reader->ctxt == NULL))
1627 return(-1);
1628 if (reader->ctxt->wellFormed != 1)
1629 return(-1);
1630
1631 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1632 return(0);
1633 TODO
1634 return(0);
1635}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001636#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001637
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001638/************************************************************************
1639 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001640 * Operating on a preparsed tree *
1641 * *
1642 ************************************************************************/
1643static int
1644xmlTextReaderNextTree(xmlTextReaderPtr reader)
1645{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001646 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001647 return(-1);
1648
1649 if (reader->state == XML_TEXTREADER_END)
1650 return(0);
1651
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001652 if (reader->node == NULL) {
1653 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001654 reader->state = XML_TEXTREADER_END;
1655 return(0);
1656 }
1657
1658 reader->node = reader->doc->children;
1659 reader->state = XML_TEXTREADER_START;
1660 return(1);
1661 }
1662
1663 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1664 if (reader->node->children != 0) {
1665 reader->node = reader->node->children;
1666 reader->depth++;
1667 reader->state = XML_TEXTREADER_START;
1668 return(1);
1669 }
1670
1671 if ((reader->node->type == XML_ELEMENT_NODE) ||
1672 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1673 reader->state = XML_TEXTREADER_BACKTRACK;
1674 return(1);
1675 }
1676 }
1677
1678 if (reader->node->next != 0) {
1679 reader->node = reader->node->next;
1680 reader->state = XML_TEXTREADER_START;
1681 return(1);
1682 }
1683
1684 if (reader->node->parent != 0) {
1685 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1686 reader->state = XML_TEXTREADER_END;
1687 return(0);
1688 }
1689
1690 reader->node = reader->node->parent;
1691 reader->depth--;
1692 reader->state = XML_TEXTREADER_BACKTRACK;
1693 return(1);
1694 }
1695
1696 reader->state = XML_TEXTREADER_END;
1697
1698 return(1);
1699}
1700
1701/**
1702 * xmlTextReaderReadTree:
1703 * @reader: the xmlTextReaderPtr used
1704 *
1705 * Moves the position of the current instance to the next node in
1706 * the stream, exposing its properties.
1707 *
1708 * Returns 1 if the node was read successfully, 0 if there is no more
1709 * nodes to read, or -1 in case of error
1710 */
1711static int
1712xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1713 if (reader->state == XML_TEXTREADER_END)
1714 return(0);
1715
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001716next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001717 if (reader->node == NULL) {
1718 if (reader->doc->children == NULL) {
1719 reader->state = XML_TEXTREADER_END;
1720 return(0);
1721 }
1722
1723 reader->node = reader->doc->children;
1724 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001725 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001726 }
1727
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001728 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1729 (reader->node->type != XML_DTD_NODE) &&
1730 (reader->node->type != XML_XINCLUDE_START) &&
1731 (reader->node->type != XML_ENTITY_REF_NODE)) {
1732 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001733 reader->node = reader->node->children;
1734 reader->depth++;
1735 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001736 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001737 }
1738
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001739 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001740 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001741 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001742 }
1743 }
1744
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001745 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001746 reader->node = reader->node->next;
1747 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001748 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001749 }
1750
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001751 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001752 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1753 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1754 reader->state = XML_TEXTREADER_END;
1755 return(0);
1756 }
1757
1758 reader->node = reader->node->parent;
1759 reader->depth--;
1760 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001761 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001762 }
1763
1764 reader->state = XML_TEXTREADER_END;
1765
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001766found_node:
1767 if ((reader->node->type == XML_XINCLUDE_START) ||
1768 (reader->node->type == XML_XINCLUDE_END))
1769 goto next_node;
1770
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001771 return(1);
1772}
1773
1774/**
William M. Brackb1d53162003-11-18 06:54:40 +00001775 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001776 * @reader: the xmlTextReaderPtr used
1777 *
1778 * Skip to the node following the current one in document order while
1779 * avoiding the subtree if any.
1780 * Currently implemented only for Readers built on a document
1781 *
1782 * Returns 1 if the node was read successfully, 0 if there is no more
1783 * nodes to read, or -1 in case of error
1784 */
1785int
1786xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1787 if (reader == NULL)
1788 return(-1);
1789 if (reader->doc == NULL) {
1790 TODO
1791 return(-1);
1792 }
1793
1794 if (reader->state == XML_TEXTREADER_END)
1795 return(0);
1796
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001797 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001798 return(xmlTextReaderNextTree(reader));
1799
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001800 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 reader->node = reader->node->next;
1802 reader->state = XML_TEXTREADER_START;
1803 return(1);
1804 }
1805
1806 return(0);
1807}
1808
1809/************************************************************************
1810 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001811 * Constructor and destructors *
1812 * *
1813 ************************************************************************/
1814/**
1815 * xmlNewTextReader:
1816 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001817 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001818 *
1819 * Create an xmlTextReader structure fed with @input
1820 *
1821 * Returns the new xmlTextReaderPtr or NULL in case of error
1822 */
1823xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001824xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001825 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001826
1827 if (input == NULL)
1828 return(NULL);
1829 ret = xmlMalloc(sizeof(xmlTextReader));
1830 if (ret == NULL) {
1831 xmlGenericError(xmlGenericErrorContext,
1832 "xmlNewTextReader : malloc failed\n");
1833 return(NULL);
1834 }
1835 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001836 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001837 ret->entTab = NULL;
1838 ret->entMax = 0;
1839 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001840 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001841 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001842 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1843 if (ret->sax == NULL) {
1844 xmlFree(ret);
1845 xmlGenericError(xmlGenericErrorContext,
1846 "xmlNewTextReader : malloc failed\n");
1847 return(NULL);
1848 }
Daniel Veillard81273902003-09-30 00:43:48 +00001849 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001850 ret->startElement = ret->sax->startElement;
1851 ret->sax->startElement = xmlTextReaderStartElement;
1852 ret->endElement = ret->sax->endElement;
1853 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001854#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001855 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001856#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001857 ret->startElementNs = ret->sax->startElementNs;
1858 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1859 ret->endElementNs = ret->sax->endElementNs;
1860 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001861#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001862 } else {
1863 ret->startElementNs = NULL;
1864 ret->endElementNs = NULL;
1865 }
Daniel Veillard81273902003-09-30 00:43:48 +00001866#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001867 ret->characters = ret->sax->characters;
1868 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001869 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001870 ret->cdataBlock = ret->sax->cdataBlock;
1871 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001872
Daniel Veillard67df8092002-12-16 22:04:11 +00001873 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001874 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001875 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001876 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001877 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001878 }
1879 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001880 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001881 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001882 ret->base = 0;
1883 ret->cur = 4;
1884 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001885 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001886 ret->base = 0;
1887 ret->cur = 0;
1888 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001889 if (ret->ctxt == NULL) {
1890 xmlGenericError(xmlGenericErrorContext,
1891 "xmlNewTextReader : malloc failed\n");
1892 xmlFree(ret->sax);
1893 xmlFree(ret);
1894 return(NULL);
1895 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001896 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001897 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001898 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001899 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001900 /*
1901 * use the parser dictionnary to allocate all elements and attributes names
1902 */
1903 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001904 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001905#ifdef LIBXML_XINCLUDE_ENABLED
1906 ret->xinclude = 0;
1907#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001908#ifdef LIBXML_PATTERN_ENABLED
1909 ret->patternMax = 0;
1910 ret->patternTab = NULL;
1911#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001912 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001913}
1914
1915/**
1916 * xmlNewTextReaderFilename:
1917 * @URI: the URI of the resource to process
1918 *
1919 * Create an xmlTextReader structure fed with the resource at @URI
1920 *
1921 * Returns the new xmlTextReaderPtr or NULL in case of error
1922 */
1923xmlTextReaderPtr
1924xmlNewTextReaderFilename(const char *URI) {
1925 xmlParserInputBufferPtr input;
1926 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001927 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001928
1929 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1930 if (input == NULL)
1931 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001932 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001933 if (ret == NULL) {
1934 xmlFreeParserInputBuffer(input);
1935 return(NULL);
1936 }
1937 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001938 if (ret->ctxt->directory == NULL)
1939 directory = xmlParserGetDirectory(URI);
1940 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1941 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1942 if (directory != NULL)
1943 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001944 return(ret);
1945}
1946
1947/**
1948 * xmlFreeTextReader:
1949 * @reader: the xmlTextReaderPtr
1950 *
1951 * Deallocate all the resources associated to the reader
1952 */
1953void
1954xmlFreeTextReader(xmlTextReaderPtr reader) {
1955 if (reader == NULL)
1956 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001957#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001958 if (reader->rngSchemas != NULL) {
1959 xmlRelaxNGFree(reader->rngSchemas);
1960 reader->rngSchemas = NULL;
1961 }
1962 if (reader->rngValidCtxt != NULL) {
1963 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1964 reader->rngValidCtxt = NULL;
1965 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001966#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001967#ifdef LIBXML_XINCLUDE_ENABLED
1968 if (reader->xincctxt != NULL)
1969 xmlXIncludeFreeContext(reader->xincctxt);
1970#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001971#ifdef LIBXML_PATTERN_ENABLED
1972 if (reader->patternTab != NULL) {
1973 int i;
1974 for (i = 0;i < reader->patternNr;i++) {
1975 if (reader->patternTab[i] != NULL)
1976 xmlFreePattern(reader->patternTab[i]);
1977 }
1978 xmlFree(reader->patternTab);
1979 }
1980#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001981 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001982 if (reader->dict == reader->ctxt->dict)
1983 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001984 if (reader->ctxt->myDoc != NULL) {
1985 if (reader->preserve == 0)
1986 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1987 reader->ctxt->myDoc = NULL;
1988 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001989 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1990 (reader->ctxt->vctxt.vstateMax > 0)){
1991 xmlFree(reader->ctxt->vctxt.vstateTab);
1992 reader->ctxt->vctxt.vstateTab = 0;
1993 reader->ctxt->vctxt.vstateMax = 0;
1994 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001995 if (reader->allocs & XML_TEXTREADER_CTXT)
1996 xmlFreeParserCtxt(reader->ctxt);
1997 }
1998 if (reader->sax != NULL)
1999 xmlFree(reader->sax);
2000 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2001 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002002 if (reader->faketext != NULL) {
2003 xmlFreeNode(reader->faketext);
2004 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002005 if (reader->buffer != NULL)
2006 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002007 if (reader->entTab != NULL)
2008 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002009 if (reader->dict != NULL)
2010 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002011 xmlFree(reader);
2012}
2013
2014/************************************************************************
2015 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002016 * Methods for XmlTextReader *
2017 * *
2018 ************************************************************************/
2019/**
2020 * xmlTextReaderClose:
2021 * @reader: the xmlTextReaderPtr used
2022 *
2023 * This method releases any resources allocated by the current instance
2024 * changes the state to Closed and close any underlying input.
2025 *
2026 * Returns 0 or -1 in case of error
2027 */
2028int
2029xmlTextReaderClose(xmlTextReaderPtr reader) {
2030 if (reader == NULL)
2031 return(-1);
2032 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002033 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002034 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2035 if (reader->ctxt != NULL) {
2036 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002037 if (reader->preserve == 0)
2038 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002039 reader->ctxt->myDoc = NULL;
2040 }
2041 if (reader->allocs & XML_TEXTREADER_CTXT) {
2042 xmlFreeParserCtxt(reader->ctxt);
2043 reader->allocs -= XML_TEXTREADER_CTXT;
2044 }
2045 }
2046 if (reader->sax != NULL) {
2047 xmlFree(reader->sax);
2048 reader->sax = NULL;
2049 }
2050 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2051 xmlFreeParserInputBuffer(reader->input);
2052 reader->allocs -= XML_TEXTREADER_INPUT;
2053 }
2054 return(0);
2055}
2056
2057/**
2058 * xmlTextReaderGetAttributeNo:
2059 * @reader: the xmlTextReaderPtr used
2060 * @no: the zero-based index of the attribute relative to the containing element
2061 *
2062 * Provides the value of the attribute with the specified index relative
2063 * to the containing element.
2064 *
2065 * Returns a string containing the value of the specified attribute, or NULL
2066 * in case of error. The string must be deallocated by the caller.
2067 */
2068xmlChar *
2069xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2070 xmlChar *ret;
2071 int i;
2072 xmlAttrPtr cur;
2073 xmlNsPtr ns;
2074
2075 if (reader == NULL)
2076 return(NULL);
2077 if (reader->node == NULL)
2078 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002079 if (reader->curnode != NULL)
2080 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002081 /* TODO: handle the xmlDecl */
2082 if (reader->node->type != XML_ELEMENT_NODE)
2083 return(NULL);
2084
2085 ns = reader->node->nsDef;
2086 for (i = 0;(i < no) && (ns != NULL);i++) {
2087 ns = ns->next;
2088 }
2089 if (ns != NULL)
2090 return(xmlStrdup(ns->href));
2091
2092 cur = reader->node->properties;
2093 if (cur == NULL)
2094 return(NULL);
2095 for (;i < no;i++) {
2096 cur = cur->next;
2097 if (cur == NULL)
2098 return(NULL);
2099 }
2100 /* TODO walk the DTD if present */
2101
2102 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2103 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2104 return(ret);
2105}
2106
2107/**
2108 * xmlTextReaderGetAttribute:
2109 * @reader: the xmlTextReaderPtr used
2110 * @name: the qualified name of the attribute.
2111 *
2112 * Provides the value of the attribute with the specified qualified name.
2113 *
2114 * Returns a string containing the value of the specified attribute, or NULL
2115 * in case of error. The string must be deallocated by the caller.
2116 */
2117xmlChar *
2118xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2119 xmlChar *prefix = NULL;
2120 xmlChar *localname;
2121 xmlNsPtr ns;
2122 xmlChar *ret = NULL;
2123
2124 if ((reader == NULL) || (name == NULL))
2125 return(NULL);
2126 if (reader->node == NULL)
2127 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002128 if (reader->curnode != NULL)
2129 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002130
2131 /* TODO: handle the xmlDecl */
2132 if (reader->node->type != XML_ELEMENT_NODE)
2133 return(NULL);
2134
2135 localname = xmlSplitQName2(name, &prefix);
2136 if (localname == NULL)
2137 return(xmlGetProp(reader->node, name));
2138
2139 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2140 if (ns != NULL)
2141 ret = xmlGetNsProp(reader->node, localname, ns->href);
2142
2143 if (localname != NULL)
2144 xmlFree(localname);
2145 if (prefix != NULL)
2146 xmlFree(prefix);
2147 return(ret);
2148}
2149
2150
2151/**
2152 * xmlTextReaderGetAttributeNs:
2153 * @reader: the xmlTextReaderPtr used
2154 * @localName: the local name of the attribute.
2155 * @namespaceURI: the namespace URI of the attribute.
2156 *
2157 * Provides the value of the specified attribute
2158 *
2159 * Returns a string containing the value of the specified attribute, or NULL
2160 * in case of error. The string must be deallocated by the caller.
2161 */
2162xmlChar *
2163xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2164 const xmlChar *namespaceURI) {
2165 if ((reader == NULL) || (localName == NULL))
2166 return(NULL);
2167 if (reader->node == NULL)
2168 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002169 if (reader->curnode != NULL)
2170 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002171
2172 /* TODO: handle the xmlDecl */
2173 if (reader->node->type != XML_ELEMENT_NODE)
2174 return(NULL);
2175
2176 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2177}
2178
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002179/**
2180 * xmlTextReaderGetRemainder:
2181 * @reader: the xmlTextReaderPtr used
2182 *
2183 * Method to get the remainder of the buffered XML. this method stops the
2184 * parser, set its state to End Of File and return the input stream with
2185 * what is left that the parser did not use.
2186 *
2187 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2188 * in case of error.
2189 */
2190xmlParserInputBufferPtr
2191xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2192 xmlParserInputBufferPtr ret = NULL;
2193
2194 if (reader == NULL)
2195 return(NULL);
2196 if (reader->node == NULL)
2197 return(NULL);
2198
2199 reader->node = NULL;
2200 reader->curnode = NULL;
2201 reader->mode = XML_TEXTREADER_MODE_EOF;
2202 if (reader->ctxt != NULL) {
2203 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002204 if (reader->preserve == 0)
2205 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002206 reader->ctxt->myDoc = NULL;
2207 }
2208 if (reader->allocs & XML_TEXTREADER_CTXT) {
2209 xmlFreeParserCtxt(reader->ctxt);
2210 reader->allocs -= XML_TEXTREADER_CTXT;
2211 }
2212 }
2213 if (reader->sax != NULL) {
2214 xmlFree(reader->sax);
2215 reader->sax = NULL;
2216 }
2217 if (reader->allocs & XML_TEXTREADER_INPUT) {
2218 ret = reader->input;
2219 reader->allocs -= XML_TEXTREADER_INPUT;
2220 } else {
2221 /*
2222 * Hum, one may need to duplicate the data structure because
2223 * without reference counting the input may be freed twice:
2224 * - by the layer which allocated it.
2225 * - by the layer to which would have been returned to.
2226 */
2227 TODO
2228 return(NULL);
2229 }
2230 return(ret);
2231}
2232
2233/**
2234 * xmlTextReaderLookupNamespace:
2235 * @reader: the xmlTextReaderPtr used
2236 * @prefix: the prefix whose namespace URI is to be resolved. To return
2237 * the default namespace, specify NULL
2238 *
2239 * Resolves a namespace prefix in the scope of the current element.
2240 *
2241 * Returns a string containing the namespace URI to which the prefix maps
2242 * or NULL in case of error. The string must be deallocated by the caller.
2243 */
2244xmlChar *
2245xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2246 xmlNsPtr ns;
2247
2248 if (reader == NULL)
2249 return(NULL);
2250 if (reader->node == NULL)
2251 return(NULL);
2252
2253 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2254 if (ns == NULL)
2255 return(NULL);
2256 return(xmlStrdup(ns->href));
2257}
2258
2259/**
2260 * xmlTextReaderMoveToAttributeNo:
2261 * @reader: the xmlTextReaderPtr used
2262 * @no: the zero-based index of the attribute relative to the containing
2263 * element.
2264 *
2265 * Moves the position of the current instance to the attribute with
2266 * the specified index relative to the containing element.
2267 *
2268 * Returns 1 in case of success, -1 in case of error, 0 if not found
2269 */
2270int
2271xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2272 int i;
2273 xmlAttrPtr cur;
2274 xmlNsPtr ns;
2275
2276 if (reader == NULL)
2277 return(-1);
2278 if (reader->node == NULL)
2279 return(-1);
2280 /* TODO: handle the xmlDecl */
2281 if (reader->node->type != XML_ELEMENT_NODE)
2282 return(-1);
2283
2284 reader->curnode = NULL;
2285
2286 ns = reader->node->nsDef;
2287 for (i = 0;(i < no) && (ns != NULL);i++) {
2288 ns = ns->next;
2289 }
2290 if (ns != NULL) {
2291 reader->curnode = (xmlNodePtr) ns;
2292 return(1);
2293 }
2294
2295 cur = reader->node->properties;
2296 if (cur == NULL)
2297 return(0);
2298 for (;i < no;i++) {
2299 cur = cur->next;
2300 if (cur == NULL)
2301 return(0);
2302 }
2303 /* TODO walk the DTD if present */
2304
2305 reader->curnode = (xmlNodePtr) cur;
2306 return(1);
2307}
2308
2309/**
2310 * xmlTextReaderMoveToAttribute:
2311 * @reader: the xmlTextReaderPtr used
2312 * @name: the qualified name of the attribute.
2313 *
2314 * Moves the position of the current instance to the attribute with
2315 * the specified qualified name.
2316 *
2317 * Returns 1 in case of success, -1 in case of error, 0 if not found
2318 */
2319int
2320xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2321 xmlChar *prefix = NULL;
2322 xmlChar *localname;
2323 xmlNsPtr ns;
2324 xmlAttrPtr prop;
2325
2326 if ((reader == NULL) || (name == NULL))
2327 return(-1);
2328 if (reader->node == NULL)
2329 return(-1);
2330
2331 /* TODO: handle the xmlDecl */
2332 if (reader->node->type != XML_ELEMENT_NODE)
2333 return(0);
2334
2335 localname = xmlSplitQName2(name, &prefix);
2336 if (localname == NULL) {
2337 /*
2338 * Namespace default decl
2339 */
2340 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2341 ns = reader->node->nsDef;
2342 while (ns != NULL) {
2343 if (ns->prefix == NULL) {
2344 reader->curnode = (xmlNodePtr) ns;
2345 return(1);
2346 }
2347 ns = ns->next;
2348 }
2349 return(0);
2350 }
2351
2352 prop = reader->node->properties;
2353 while (prop != NULL) {
2354 /*
2355 * One need to have
2356 * - same attribute names
2357 * - and the attribute carrying that namespace
2358 */
2359 if ((xmlStrEqual(prop->name, name)) &&
2360 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2361 reader->curnode = (xmlNodePtr) prop;
2362 return(1);
2363 }
2364 prop = prop->next;
2365 }
2366 return(0);
2367 }
2368
2369 /*
2370 * Namespace default decl
2371 */
2372 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2373 ns = reader->node->nsDef;
2374 while (ns != NULL) {
2375 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2376 reader->curnode = (xmlNodePtr) ns;
2377 goto found;
2378 }
2379 ns = ns->next;
2380 }
2381 goto not_found;
2382 }
2383 prop = reader->node->properties;
2384 while (prop != NULL) {
2385 /*
2386 * One need to have
2387 * - same attribute names
2388 * - and the attribute carrying that namespace
2389 */
2390 if ((xmlStrEqual(prop->name, localname)) &&
2391 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2392 reader->curnode = (xmlNodePtr) prop;
2393 goto found;
2394 }
2395 prop = prop->next;
2396 }
2397not_found:
2398 if (localname != NULL)
2399 xmlFree(localname);
2400 if (prefix != NULL)
2401 xmlFree(prefix);
2402 return(0);
2403
2404found:
2405 if (localname != NULL)
2406 xmlFree(localname);
2407 if (prefix != NULL)
2408 xmlFree(prefix);
2409 return(1);
2410}
2411
2412/**
2413 * xmlTextReaderMoveToAttributeNs:
2414 * @reader: the xmlTextReaderPtr used
2415 * @localName: the local name of the attribute.
2416 * @namespaceURI: the namespace URI of the attribute.
2417 *
2418 * Moves the position of the current instance to the attribute with the
2419 * specified local name and namespace URI.
2420 *
2421 * Returns 1 in case of success, -1 in case of error, 0 if not found
2422 */
2423int
2424xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2425 const xmlChar *localName, const xmlChar *namespaceURI) {
2426 xmlAttrPtr prop;
2427 xmlNodePtr node;
2428
2429 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2430 return(-1);
2431 if (reader->node == NULL)
2432 return(-1);
2433 if (reader->node->type != XML_ELEMENT_NODE)
2434 return(0);
2435 node = reader->node;
2436
2437 /*
2438 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2439 * namespace name associated to "xmlns"
2440 */
2441 prop = node->properties;
2442 while (prop != NULL) {
2443 /*
2444 * One need to have
2445 * - same attribute names
2446 * - and the attribute carrying that namespace
2447 */
2448 if (xmlStrEqual(prop->name, localName) &&
2449 ((prop->ns != NULL) &&
2450 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2451 reader->curnode = (xmlNodePtr) prop;
2452 return(1);
2453 }
2454 prop = prop->next;
2455 }
2456 return(0);
2457}
2458
2459/**
2460 * xmlTextReaderMoveToFirstAttribute:
2461 * @reader: the xmlTextReaderPtr used
2462 *
2463 * Moves the position of the current instance to the first attribute
2464 * associated with the current node.
2465 *
2466 * Returns 1 in case of success, -1 in case of error, 0 if not found
2467 */
2468int
2469xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2470 if (reader == NULL)
2471 return(-1);
2472 if (reader->node == NULL)
2473 return(-1);
2474 if (reader->node->type != XML_ELEMENT_NODE)
2475 return(0);
2476
2477 if (reader->node->nsDef != NULL) {
2478 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2479 return(1);
2480 }
2481 if (reader->node->properties != NULL) {
2482 reader->curnode = (xmlNodePtr) reader->node->properties;
2483 return(1);
2484 }
2485 return(0);
2486}
2487
2488/**
2489 * xmlTextReaderMoveToNextAttribute:
2490 * @reader: the xmlTextReaderPtr used
2491 *
2492 * Moves the position of the current instance to the next attribute
2493 * associated with the current node.
2494 *
2495 * Returns 1 in case of success, -1 in case of error, 0 if not found
2496 */
2497int
2498xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2499 if (reader == NULL)
2500 return(-1);
2501 if (reader->node == NULL)
2502 return(-1);
2503 if (reader->node->type != XML_ELEMENT_NODE)
2504 return(0);
2505 if (reader->curnode == NULL)
2506 return(xmlTextReaderMoveToFirstAttribute(reader));
2507
2508 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2509 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2510 if (ns->next != NULL) {
2511 reader->curnode = (xmlNodePtr) ns->next;
2512 return(1);
2513 }
2514 if (reader->node->properties != NULL) {
2515 reader->curnode = (xmlNodePtr) reader->node->properties;
2516 return(1);
2517 }
2518 return(0);
2519 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2520 (reader->curnode->next != NULL)) {
2521 reader->curnode = reader->curnode->next;
2522 return(1);
2523 }
2524 return(0);
2525}
2526
2527/**
2528 * xmlTextReaderMoveToElement:
2529 * @reader: the xmlTextReaderPtr used
2530 *
2531 * Moves the position of the current instance to the node that
2532 * contains the current Attribute node.
2533 *
2534 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2535 */
2536int
2537xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2538 if (reader == NULL)
2539 return(-1);
2540 if (reader->node == NULL)
2541 return(-1);
2542 if (reader->node->type != XML_ELEMENT_NODE)
2543 return(0);
2544 if (reader->curnode != NULL) {
2545 reader->curnode = NULL;
2546 return(1);
2547 }
2548 return(0);
2549}
2550
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002551/**
2552 * xmlTextReaderReadAttributeValue:
2553 * @reader: the xmlTextReaderPtr used
2554 *
2555 * Parses an attribute value into one or more Text and EntityReference nodes.
2556 *
2557 * Returns 1 in case of success, 0 if the reader was not positionned on an
2558 * ttribute node or all the attribute values have been read, or -1
2559 * in case of error.
2560 */
2561int
2562xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2563 if (reader == NULL)
2564 return(-1);
2565 if (reader->node == NULL)
2566 return(-1);
2567 if (reader->curnode == NULL)
2568 return(0);
2569 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2570 if (reader->curnode->children == NULL)
2571 return(0);
2572 reader->curnode = reader->curnode->children;
2573 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2574 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2575
2576 if (reader->faketext == NULL) {
2577 reader->faketext = xmlNewDocText(reader->node->doc,
2578 ns->href);
2579 } else {
2580 if (reader->faketext->content != NULL)
2581 xmlFree(reader->faketext->content);
2582 reader->faketext->content = xmlStrdup(ns->href);
2583 }
2584 reader->curnode = reader->faketext;
2585 } else {
2586 if (reader->curnode->next == NULL)
2587 return(0);
2588 reader->curnode = reader->curnode->next;
2589 }
2590 return(1);
2591}
2592
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002593/************************************************************************
2594 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002595 * Acces API to the current node *
2596 * *
2597 ************************************************************************/
2598/**
2599 * xmlTextReaderAttributeCount:
2600 * @reader: the xmlTextReaderPtr used
2601 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002602 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002603 *
2604 * Returns 0 i no attributes, -1 in case of error or the attribute count
2605 */
2606int
2607xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2608 int ret;
2609 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002610 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002611 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002612
2613 if (reader == NULL)
2614 return(-1);
2615 if (reader->node == NULL)
2616 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002617
2618 if (reader->curnode != NULL)
2619 node = reader->curnode;
2620 else
2621 node = reader->node;
2622
2623 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002624 return(0);
2625 if ((reader->state == XML_TEXTREADER_END) ||
2626 (reader->state == XML_TEXTREADER_BACKTRACK))
2627 return(0);
2628 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002629 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002630 while (attr != NULL) {
2631 ret++;
2632 attr = attr->next;
2633 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002634 ns = node->nsDef;
2635 while (ns != NULL) {
2636 ret++;
2637 ns = ns->next;
2638 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002639 return(ret);
2640}
2641
2642/**
2643 * xmlTextReaderNodeType:
2644 * @reader: the xmlTextReaderPtr used
2645 *
2646 * Get the node type of the current node
2647 * Reference:
2648 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2649 *
2650 * Returns the xmlNodeType of the current node or -1 in case of error
2651 */
2652int
2653xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002654 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002655
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002656 if (reader == NULL)
2657 return(-1);
2658 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002659 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002660 if (reader->curnode != NULL)
2661 node = reader->curnode;
2662 else
2663 node = reader->node;
2664 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002665 case XML_ELEMENT_NODE:
2666 if ((reader->state == XML_TEXTREADER_END) ||
2667 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002668 return(XML_READER_TYPE_END_ELEMENT);
2669 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002670 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002671 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002672 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002673 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002674 if (xmlIsBlankNode(reader->node)) {
2675 if (xmlNodeGetSpacePreserve(reader->node))
2676 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2677 else
2678 return(XML_READER_TYPE_WHITESPACE);
2679 } else {
2680 return(XML_READER_TYPE_TEXT);
2681 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002682 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002683 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002684 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002685 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002686 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002687 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002688 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002689 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002690 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002691 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002692 case XML_DOCUMENT_NODE:
2693 case XML_HTML_DOCUMENT_NODE:
2694#ifdef LIBXML_DOCB_ENABLED
2695 case XML_DOCB_DOCUMENT_NODE:
2696#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002697 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002698 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002699 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002700 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002701 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002702 case XML_DOCUMENT_TYPE_NODE:
2703 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002704 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002705
2706 case XML_ELEMENT_DECL:
2707 case XML_ATTRIBUTE_DECL:
2708 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002709 case XML_XINCLUDE_START:
2710 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002711 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002712 }
2713 return(-1);
2714}
2715
2716/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002717 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002718 * @reader: the xmlTextReaderPtr used
2719 *
2720 * Check if the current node is empty
2721 *
2722 * Returns 1 if empty, 0 if not and -1 in case of error
2723 */
2724int
2725xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2726 if ((reader == NULL) || (reader->node == NULL))
2727 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002728 if (reader->node->type != XML_ELEMENT_NODE)
2729 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002730 if (reader->curnode != NULL)
2731 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002732 if (reader->node->children != NULL)
2733 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002734 if (reader->state == XML_TEXTREADER_END)
2735 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002736 if (reader->doc != NULL)
2737 return(1);
2738 if (reader->in_xinclude > 0)
2739 return(1);
Daniel Veillarde8039df2003-10-27 11:25:13 +00002740 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002741}
2742
2743/**
2744 * xmlTextReaderLocalName:
2745 * @reader: the xmlTextReaderPtr used
2746 *
2747 * The local name of the node.
2748 *
2749 * Returns the local name or NULL if not available
2750 */
2751xmlChar *
2752xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002753 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002754 if ((reader == NULL) || (reader->node == NULL))
2755 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002756 if (reader->curnode != NULL)
2757 node = reader->curnode;
2758 else
2759 node = reader->node;
2760 if (node->type == XML_NAMESPACE_DECL) {
2761 xmlNsPtr ns = (xmlNsPtr) node;
2762 if (ns->prefix == NULL)
2763 return(xmlStrdup(BAD_CAST "xmlns"));
2764 else
2765 return(xmlStrdup(ns->prefix));
2766 }
2767 if ((node->type != XML_ELEMENT_NODE) &&
2768 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002769 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002770 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002771}
2772
2773/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002774 * xmlTextReaderConstLocalName:
2775 * @reader: the xmlTextReaderPtr used
2776 *
2777 * The local name of the node.
2778 *
2779 * Returns the local name or NULL if not available, the
2780 * string will be deallocated with the reader.
2781 */
2782const xmlChar *
2783xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2784 xmlNodePtr node;
2785 if ((reader == NULL) || (reader->node == NULL))
2786 return(NULL);
2787 if (reader->curnode != NULL)
2788 node = reader->curnode;
2789 else
2790 node = reader->node;
2791 if (node->type == XML_NAMESPACE_DECL) {
2792 xmlNsPtr ns = (xmlNsPtr) node;
2793 if (ns->prefix == NULL)
2794 return(CONSTSTR(BAD_CAST "xmlns"));
2795 else
2796 return(ns->prefix);
2797 }
2798 if ((node->type != XML_ELEMENT_NODE) &&
2799 (node->type != XML_ATTRIBUTE_NODE))
2800 return(xmlTextReaderConstName(reader));
2801 return(node->name);
2802}
2803
2804/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002805 * xmlTextReaderName:
2806 * @reader: the xmlTextReaderPtr used
2807 *
2808 * The qualified name of the node, equal to Prefix :LocalName.
2809 *
2810 * Returns the local name or NULL if not available
2811 */
2812xmlChar *
2813xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002814 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002815 xmlChar *ret;
2816
2817 if ((reader == NULL) || (reader->node == NULL))
2818 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002819 if (reader->curnode != NULL)
2820 node = reader->curnode;
2821 else
2822 node = reader->node;
2823 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002824 case XML_ELEMENT_NODE:
2825 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002826 if ((node->ns == NULL) ||
2827 (node->ns->prefix == NULL))
2828 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002829
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002830 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002831 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002832 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002833 return(ret);
2834 case XML_TEXT_NODE:
2835 return(xmlStrdup(BAD_CAST "#text"));
2836 case XML_CDATA_SECTION_NODE:
2837 return(xmlStrdup(BAD_CAST "#cdata-section"));
2838 case XML_ENTITY_NODE:
2839 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002840 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002841 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002842 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002843 case XML_COMMENT_NODE:
2844 return(xmlStrdup(BAD_CAST "#comment"));
2845 case XML_DOCUMENT_NODE:
2846 case XML_HTML_DOCUMENT_NODE:
2847#ifdef LIBXML_DOCB_ENABLED
2848 case XML_DOCB_DOCUMENT_NODE:
2849#endif
2850 return(xmlStrdup(BAD_CAST "#document"));
2851 case XML_DOCUMENT_FRAG_NODE:
2852 return(xmlStrdup(BAD_CAST "#document-fragment"));
2853 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002854 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002855 case XML_DOCUMENT_TYPE_NODE:
2856 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002857 return(xmlStrdup(node->name));
2858 case XML_NAMESPACE_DECL: {
2859 xmlNsPtr ns = (xmlNsPtr) node;
2860
2861 ret = xmlStrdup(BAD_CAST "xmlns");
2862 if (ns->prefix == NULL)
2863 return(ret);
2864 ret = xmlStrcat(ret, BAD_CAST ":");
2865 ret = xmlStrcat(ret, ns->prefix);
2866 return(ret);
2867 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002868
2869 case XML_ELEMENT_DECL:
2870 case XML_ATTRIBUTE_DECL:
2871 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002872 case XML_XINCLUDE_START:
2873 case XML_XINCLUDE_END:
2874 return(NULL);
2875 }
2876 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002877}
2878
2879/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002880 * xmlTextReaderConstName:
2881 * @reader: the xmlTextReaderPtr used
2882 *
2883 * The qualified name of the node, equal to Prefix :LocalName.
2884 *
2885 * Returns the local name or NULL if not available, the string is
2886 * deallocated with the reader.
2887 */
2888const xmlChar *
2889xmlTextReaderConstName(xmlTextReaderPtr reader) {
2890 xmlNodePtr node;
2891
2892 if ((reader == NULL) || (reader->node == NULL))
2893 return(NULL);
2894 if (reader->curnode != NULL)
2895 node = reader->curnode;
2896 else
2897 node = reader->node;
2898 switch (node->type) {
2899 case XML_ELEMENT_NODE:
2900 case XML_ATTRIBUTE_NODE:
2901 if ((node->ns == NULL) ||
2902 (node->ns->prefix == NULL))
2903 return(node->name);
2904 return(CONSTQSTR(node->ns->prefix, node->name));
2905 case XML_TEXT_NODE:
2906 return(CONSTSTR(BAD_CAST "#text"));
2907 case XML_CDATA_SECTION_NODE:
2908 return(CONSTSTR(BAD_CAST "#cdata-section"));
2909 case XML_ENTITY_NODE:
2910 case XML_ENTITY_REF_NODE:
2911 return(CONSTSTR(node->name));
2912 case XML_PI_NODE:
2913 return(CONSTSTR(node->name));
2914 case XML_COMMENT_NODE:
2915 return(CONSTSTR(BAD_CAST "#comment"));
2916 case XML_DOCUMENT_NODE:
2917 case XML_HTML_DOCUMENT_NODE:
2918#ifdef LIBXML_DOCB_ENABLED
2919 case XML_DOCB_DOCUMENT_NODE:
2920#endif
2921 return(CONSTSTR(BAD_CAST "#document"));
2922 case XML_DOCUMENT_FRAG_NODE:
2923 return(CONSTSTR(BAD_CAST "#document-fragment"));
2924 case XML_NOTATION_NODE:
2925 return(CONSTSTR(node->name));
2926 case XML_DOCUMENT_TYPE_NODE:
2927 case XML_DTD_NODE:
2928 return(CONSTSTR(node->name));
2929 case XML_NAMESPACE_DECL: {
2930 xmlNsPtr ns = (xmlNsPtr) node;
2931
2932 if (ns->prefix == NULL)
2933 return(CONSTSTR(BAD_CAST "xmlns"));
2934 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2935 }
2936
2937 case XML_ELEMENT_DECL:
2938 case XML_ATTRIBUTE_DECL:
2939 case XML_ENTITY_DECL:
2940 case XML_XINCLUDE_START:
2941 case XML_XINCLUDE_END:
2942 return(NULL);
2943 }
2944 return(NULL);
2945}
2946
2947/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002948 * xmlTextReaderPrefix:
2949 * @reader: the xmlTextReaderPtr used
2950 *
2951 * A shorthand reference to the namespace associated with the node.
2952 *
2953 * Returns the prefix or NULL if not available
2954 */
2955xmlChar *
2956xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002957 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002958 if ((reader == NULL) || (reader->node == NULL))
2959 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002960 if (reader->curnode != NULL)
2961 node = reader->curnode;
2962 else
2963 node = reader->node;
2964 if (node->type == XML_NAMESPACE_DECL) {
2965 xmlNsPtr ns = (xmlNsPtr) node;
2966 if (ns->prefix == NULL)
2967 return(NULL);
2968 return(xmlStrdup(BAD_CAST "xmlns"));
2969 }
2970 if ((node->type != XML_ELEMENT_NODE) &&
2971 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002972 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002973 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002974 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002975 return(NULL);
2976}
2977
2978/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002979 * xmlTextReaderConstPrefix:
2980 * @reader: the xmlTextReaderPtr used
2981 *
2982 * A shorthand reference to the namespace associated with the node.
2983 *
2984 * Returns the prefix or NULL if not available, the string is deallocated
2985 * with the reader.
2986 */
2987const xmlChar *
2988xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2989 xmlNodePtr node;
2990 if ((reader == NULL) || (reader->node == NULL))
2991 return(NULL);
2992 if (reader->curnode != NULL)
2993 node = reader->curnode;
2994 else
2995 node = reader->node;
2996 if (node->type == XML_NAMESPACE_DECL) {
2997 xmlNsPtr ns = (xmlNsPtr) node;
2998 if (ns->prefix == NULL)
2999 return(NULL);
3000 return(CONSTSTR(BAD_CAST "xmlns"));
3001 }
3002 if ((node->type != XML_ELEMENT_NODE) &&
3003 (node->type != XML_ATTRIBUTE_NODE))
3004 return(NULL);
3005 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3006 return(CONSTSTR(node->ns->prefix));
3007 return(NULL);
3008}
3009
3010/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003011 * xmlTextReaderNamespaceUri:
3012 * @reader: the xmlTextReaderPtr used
3013 *
3014 * The URI defining the namespace associated with the node.
3015 *
3016 * Returns the namespace URI or NULL if not available
3017 */
3018xmlChar *
3019xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003020 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003021 if ((reader == NULL) || (reader->node == NULL))
3022 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003023 if (reader->curnode != NULL)
3024 node = reader->curnode;
3025 else
3026 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003027 if (node->type == XML_NAMESPACE_DECL)
3028 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003029 if ((node->type != XML_ELEMENT_NODE) &&
3030 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003031 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003032 if (node->ns != NULL)
3033 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003034 return(NULL);
3035}
3036
3037/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003038 * xmlTextReaderConstNamespaceUri:
3039 * @reader: the xmlTextReaderPtr used
3040 *
3041 * The URI defining the namespace associated with the node.
3042 *
3043 * Returns the namespace URI or NULL if not available, the string
3044 * will be deallocated with the reader
3045 */
3046const xmlChar *
3047xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3048 xmlNodePtr node;
3049 if ((reader == NULL) || (reader->node == NULL))
3050 return(NULL);
3051 if (reader->curnode != NULL)
3052 node = reader->curnode;
3053 else
3054 node = reader->node;
3055 if (node->type == XML_NAMESPACE_DECL)
3056 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3057 if ((node->type != XML_ELEMENT_NODE) &&
3058 (node->type != XML_ATTRIBUTE_NODE))
3059 return(NULL);
3060 if (node->ns != NULL)
3061 return(CONSTSTR(node->ns->href));
3062 return(NULL);
3063}
3064
3065/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003066 * xmlTextReaderBaseUri:
3067 * @reader: the xmlTextReaderPtr used
3068 *
3069 * The base URI of the node.
3070 *
3071 * Returns the base URI or NULL if not available
3072 */
3073xmlChar *
3074xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3075 if ((reader == NULL) || (reader->node == NULL))
3076 return(NULL);
3077 return(xmlNodeGetBase(NULL, reader->node));
3078}
3079
3080/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003081 * xmlTextReaderConstBaseUri:
3082 * @reader: the xmlTextReaderPtr used
3083 *
3084 * The base URI of the node.
3085 *
3086 * Returns the base URI or NULL if not available, the string
3087 * will be deallocated with the reader
3088 */
3089const xmlChar *
3090xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3091 xmlChar *tmp;
3092 const xmlChar *ret;
3093
3094 if ((reader == NULL) || (reader->node == NULL))
3095 return(NULL);
3096 tmp = xmlNodeGetBase(NULL, reader->node);
3097 if (tmp == NULL)
3098 return(NULL);
3099 ret = CONSTSTR(tmp);
3100 xmlFree(tmp);
3101 return(ret);
3102}
3103
3104/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003105 * xmlTextReaderDepth:
3106 * @reader: the xmlTextReaderPtr used
3107 *
3108 * The depth of the node in the tree.
3109 *
3110 * Returns the depth or -1 in case of error
3111 */
3112int
3113xmlTextReaderDepth(xmlTextReaderPtr reader) {
3114 if (reader == NULL)
3115 return(-1);
3116 if (reader->node == NULL)
3117 return(0);
3118
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003119 if (reader->curnode != NULL) {
3120 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3121 (reader->curnode->type == XML_NAMESPACE_DECL))
3122 return(reader->depth + 1);
3123 return(reader->depth + 2);
3124 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003125 return(reader->depth);
3126}
3127
3128/**
3129 * xmlTextReaderHasAttributes:
3130 * @reader: the xmlTextReaderPtr used
3131 *
3132 * Whether the node has attributes.
3133 *
3134 * Returns 1 if true, 0 if false, and -1 in case or error
3135 */
3136int
3137xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003138 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003139 if (reader == NULL)
3140 return(-1);
3141 if (reader->node == NULL)
3142 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003143 if (reader->curnode != NULL)
3144 node = reader->curnode;
3145 else
3146 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003147
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003148 if ((node->type == XML_ELEMENT_NODE) &&
3149 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003150 return(1);
3151 /* TODO: handle the xmlDecl */
3152 return(0);
3153}
3154
3155/**
3156 * xmlTextReaderHasValue:
3157 * @reader: the xmlTextReaderPtr used
3158 *
3159 * Whether the node can have a text value.
3160 *
3161 * Returns 1 if true, 0 if false, and -1 in case or error
3162 */
3163int
3164xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003165 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003166 if (reader == NULL)
3167 return(-1);
3168 if (reader->node == NULL)
3169 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003170 if (reader->curnode != NULL)
3171 node = reader->curnode;
3172 else
3173 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003174
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003175 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003176 case XML_ATTRIBUTE_NODE:
3177 case XML_TEXT_NODE:
3178 case XML_CDATA_SECTION_NODE:
3179 case XML_PI_NODE:
3180 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003181 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003182 return(1);
3183 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003184 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003185 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003186 return(0);
3187}
3188
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003189/**
3190 * xmlTextReaderValue:
3191 * @reader: the xmlTextReaderPtr used
3192 *
3193 * Provides the text value of the node if present
3194 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003195 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003196 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003197 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003198xmlChar *
3199xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003200 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003201 if (reader == NULL)
3202 return(NULL);
3203 if (reader->node == NULL)
3204 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003205 if (reader->curnode != NULL)
3206 node = reader->curnode;
3207 else
3208 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003209
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003210 switch (node->type) {
3211 case XML_NAMESPACE_DECL:
3212 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003213 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003214 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003215
3216 if (attr->parent != NULL)
3217 return (xmlNodeListGetString
3218 (attr->parent->doc, attr->children, 1));
3219 else
3220 return (xmlNodeListGetString(NULL, attr->children, 1));
3221 break;
3222 }
3223 case XML_TEXT_NODE:
3224 case XML_CDATA_SECTION_NODE:
3225 case XML_PI_NODE:
3226 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003227 if (node->content != NULL)
3228 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003229 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003230 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003231 }
3232 return(NULL);
3233}
3234
3235/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003236 * xmlTextReaderConstValue:
3237 * @reader: the xmlTextReaderPtr used
3238 *
3239 * Provides the text value of the node if present
3240 *
3241 * Returns the string or NULL if not available. The result will be
3242 * deallocated on the next Read() operation.
3243 */
3244const xmlChar *
3245xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3246 xmlNodePtr node;
3247 if (reader == NULL)
3248 return(NULL);
3249 if (reader->node == NULL)
3250 return(NULL);
3251 if (reader->curnode != NULL)
3252 node = reader->curnode;
3253 else
3254 node = reader->node;
3255
3256 switch (node->type) {
3257 case XML_NAMESPACE_DECL:
3258 return(((xmlNsPtr) node)->href);
3259 case XML_ATTRIBUTE_NODE:{
3260 xmlAttrPtr attr = (xmlAttrPtr) node;
3261
3262 if ((attr->children != NULL) &&
3263 (attr->children->type == XML_TEXT_NODE) &&
3264 (attr->children->next == NULL))
3265 return(attr->children->content);
3266 else {
3267 reader->buffer->use = 0;
3268 xmlNodeBufGetContent(reader->buffer, node);
3269 return(reader->buffer->content);
3270 }
3271 break;
3272 }
3273 case XML_TEXT_NODE:
3274 case XML_CDATA_SECTION_NODE:
3275 case XML_PI_NODE:
3276 case XML_COMMENT_NODE:
3277 return(node->content);
3278 default:
3279 break;
3280 }
3281 return(NULL);
3282}
3283
3284/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003285 * xmlTextReaderIsDefault:
3286 * @reader: the xmlTextReaderPtr used
3287 *
3288 * Whether an Attribute node was generated from the default value
3289 * defined in the DTD or schema.
3290 *
3291 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3292 */
3293int
3294xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3295 if (reader == NULL)
3296 return(-1);
3297 return(0);
3298}
3299
3300/**
3301 * xmlTextReaderQuoteChar:
3302 * @reader: the xmlTextReaderPtr used
3303 *
3304 * The quotation mark character used to enclose the value of an attribute.
3305 *
3306 * Returns " or ' and -1 in case of error
3307 */
3308int
3309xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3310 if (reader == NULL)
3311 return(-1);
3312 /* TODO maybe lookup the attribute value for " first */
3313 return((int) '"');
3314}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003315
3316/**
3317 * xmlTextReaderXmlLang:
3318 * @reader: the xmlTextReaderPtr used
3319 *
3320 * The xml:lang scope within which the node resides.
3321 *
3322 * Returns the xml:lang value or NULL if none exists.
3323 */
3324xmlChar *
3325xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3326 if (reader == NULL)
3327 return(NULL);
3328 if (reader->node == NULL)
3329 return(NULL);
3330 return(xmlNodeGetLang(reader->node));
3331}
3332
Daniel Veillard67df8092002-12-16 22:04:11 +00003333/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003334 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003335 * @reader: the xmlTextReaderPtr used
3336 *
3337 * The xml:lang scope within which the node resides.
3338 *
3339 * Returns the xml:lang value or NULL if none exists.
3340 */
3341const xmlChar *
3342xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3343 xmlChar *tmp;
3344 const xmlChar *ret;
3345
3346 if (reader == NULL)
3347 return(NULL);
3348 if (reader->node == NULL)
3349 return(NULL);
3350 tmp = xmlNodeGetLang(reader->node);
3351 if (tmp == NULL)
3352 return(NULL);
3353 ret = CONSTSTR(tmp);
3354 xmlFree(tmp);
3355 return(ret);
3356}
3357
3358/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003359 * xmlTextReaderConstString:
3360 * @reader: the xmlTextReaderPtr used
3361 * @str: the string to intern.
3362 *
3363 * Get an interned string from the reader, allows for example to
3364 * speedup string name comparisons
3365 *
3366 * Returns an interned copy of the string or NULL in case of error. The
3367 * string will be deallocated with the reader.
3368 */
3369const xmlChar *
3370xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3371 if (reader == NULL)
3372 return(NULL);
3373 return(CONSTSTR(str));
3374}
3375
3376/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003377 * xmlTextReaderNormalization:
3378 * @reader: the xmlTextReaderPtr used
3379 *
3380 * The value indicating whether to normalize white space and attribute values.
3381 * Since attribute value and end of line normalizations are a MUST in the XML
3382 * specification only the value true is accepted. The broken bahaviour of
3383 * accepting out of range character entities like &#0; is of course not
3384 * supported either.
3385 *
3386 * Returns 1 or -1 in case of error.
3387 */
3388int
3389xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3390 if (reader == NULL)
3391 return(-1);
3392 return(1);
3393}
3394
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003395/************************************************************************
3396 * *
3397 * Extensions to the base APIs *
3398 * *
3399 ************************************************************************/
3400
3401/**
3402 * xmlTextReaderSetParserProp:
3403 * @reader: the xmlTextReaderPtr used
3404 * @prop: the xmlParserProperties to set
3405 * @value: usually 0 or 1 to (de)activate it
3406 *
3407 * Change the parser processing behaviour by changing some of its internal
3408 * properties. Note that some properties can only be changed before any
3409 * read has been done.
3410 *
3411 * Returns 0 if the call was successful, or -1 in case of error
3412 */
3413int
3414xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3415 xmlParserProperties p = (xmlParserProperties) prop;
3416 xmlParserCtxtPtr ctxt;
3417
3418 if ((reader == NULL) || (reader->ctxt == NULL))
3419 return(-1);
3420 ctxt = reader->ctxt;
3421
3422 switch (p) {
3423 case XML_PARSER_LOADDTD:
3424 if (value != 0) {
3425 if (ctxt->loadsubset == 0) {
3426 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3427 return(-1);
3428 ctxt->loadsubset = XML_DETECT_IDS;
3429 }
3430 } else {
3431 ctxt->loadsubset = 0;
3432 }
3433 return(0);
3434 case XML_PARSER_DEFAULTATTRS:
3435 if (value != 0) {
3436 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3437 } else {
3438 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3439 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3440 }
3441 return(0);
3442 case XML_PARSER_VALIDATE:
3443 if (value != 0) {
3444 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003445 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003446 } else {
3447 ctxt->validate = 0;
3448 }
3449 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003450 case XML_PARSER_SUBST_ENTITIES:
3451 if (value != 0) {
3452 ctxt->replaceEntities = 1;
3453 } else {
3454 ctxt->replaceEntities = 0;
3455 }
3456 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003457 }
3458 return(-1);
3459}
3460
3461/**
3462 * xmlTextReaderGetParserProp:
3463 * @reader: the xmlTextReaderPtr used
3464 * @prop: the xmlParserProperties to get
3465 *
3466 * Read the parser internal property.
3467 *
3468 * Returns the value, usually 0 or 1, or -1 in case of error.
3469 */
3470int
3471xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3472 xmlParserProperties p = (xmlParserProperties) prop;
3473 xmlParserCtxtPtr ctxt;
3474
3475 if ((reader == NULL) || (reader->ctxt == NULL))
3476 return(-1);
3477 ctxt = reader->ctxt;
3478
3479 switch (p) {
3480 case XML_PARSER_LOADDTD:
3481 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3482 return(1);
3483 return(0);
3484 case XML_PARSER_DEFAULTATTRS:
3485 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3486 return(1);
3487 return(0);
3488 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003489 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003490 case XML_PARSER_SUBST_ENTITIES:
3491 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003492 }
3493 return(-1);
3494}
3495
Daniel Veillarde18fc182002-12-28 22:56:33 +00003496/**
3497 * xmlTextReaderCurrentNode:
3498 * @reader: the xmlTextReaderPtr used
3499 *
3500 * Hacking interface allowing to get the xmlNodePtr correponding to the
3501 * current node being accessed by the xmlTextReader. This is dangerous
3502 * because the underlying node may be destroyed on the next Reads.
3503 *
3504 * Returns the xmlNodePtr or NULL in case of error.
3505 */
3506xmlNodePtr
3507xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3508 if (reader == NULL)
3509 return(NULL);
3510
3511 if (reader->curnode != NULL)
3512 return(reader->curnode);
3513 return(reader->node);
3514}
3515
3516/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003517 * xmlTextReaderPreserve:
3518 * @reader: the xmlTextReaderPtr used
3519 *
3520 *
3521 * current node being accessed by the xmlTextReader. This is dangerous
3522 * because the underlying node may be destroyed on the next Reads.
3523 *
3524 * Returns the xmlNodePtr or NULL in case of error.
3525 */
3526xmlNodePtr
3527xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3528 xmlNodePtr cur, parent;
3529
3530 if (reader == NULL)
3531 return(NULL);
3532
3533 if (reader->curnode != NULL)
3534 cur = reader->curnode;
3535 else
3536 cur = reader->node;
3537 if (cur == NULL)
3538 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003539
3540 if (cur->type != XML_DOCUMENT_NODE) {
3541 cur->extra |= NODE_IS_PRESERVED;
3542 cur->extra |= NODE_IS_SPRESERVED;
3543 }
3544 reader->preserves++;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003545
3546 parent = cur->parent;;
3547 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003548 if (parent->type == XML_ELEMENT_NODE)
3549 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003550 parent = parent->parent;
3551 }
3552 return(cur);
3553}
3554
Daniel Veillard1e906612003-12-05 14:57:46 +00003555#ifdef LIBXML_PATTERN_ENABLED
3556/**
3557 * xmlTextReaderPreservePattern:
3558 * @reader: the xmlTextReaderPtr used
3559 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003560 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillard1e906612003-12-05 14:57:46 +00003561 *
3562 * This tells the XML Reader to preserve all nodes matched by the
3563 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3564 * keep an handle on the resulting document once parsing has finished
3565 *
3566 * Returns a positive number in case of success and -1 in case of error
3567 */
3568int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003569xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3570 const xmlChar **namespaces)
3571{
Daniel Veillard1e906612003-12-05 14:57:46 +00003572 xmlPatternPtr comp;
3573
3574 if ((reader == NULL) || (pattern == NULL))
3575 return(-1);
3576
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003577 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003578 if (comp == NULL)
3579 return(-1);
3580
3581 if (reader->patternMax <= 0) {
3582 reader->patternMax = 4;
3583 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3584 sizeof(reader->patternTab[0]));
3585 if (reader->patternTab == NULL) {
3586 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3587 return (-1);
3588 }
3589 }
3590 if (reader->patternNr >= reader->patternMax) {
3591 xmlPatternPtr *tmp;
3592 reader->patternMax *= 2;
3593 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3594 reader->patternMax *
3595 sizeof(reader->patternTab[0]));
3596 if (tmp == NULL) {
3597 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3598 reader->patternMax /= 2;
3599 return (-1);
3600 }
3601 reader->patternTab = tmp;
3602 }
3603 reader->patternTab[reader->patternNr] = comp;
3604 return(reader->patternNr++);
3605}
3606#endif
3607
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003608/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003609 * xmlTextReaderCurrentDoc:
3610 * @reader: the xmlTextReaderPtr used
3611 *
3612 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003613 * current document being accessed by the xmlTextReader.
3614 * NOTE: as a result of this call, the reader will not destroy the
3615 * associated XML document and calling xmlFreeDoc() on the result
3616 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003617 *
3618 * Returns the xmlDocPtr or NULL in case of error.
3619 */
3620xmlDocPtr
3621xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003622 if (reader == NULL)
3623 return(NULL);
3624 if (reader->doc != NULL)
3625 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003626 if ((reader == NULL) || (reader->ctxt == NULL) ||
3627 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003628 return(NULL);
3629
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003630 reader->preserve = 1;
3631 if ((reader->ctxt->myDoc->dict != NULL) &&
3632 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3633 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003634 return(reader->ctxt->myDoc);
3635}
3636
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003637#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003638/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003639 * xmlTextReaderRelaxNGSetSchema:
3640 * @reader: the xmlTextReaderPtr used
3641 * @schema: a precompiled RelaxNG schema
3642 *
3643 * Use RelaxNG to validate the document as it is processed.
3644 * Activation is only possible before the first Read().
3645 * if @schema is NULL, then RelaxNG validation is desactivated.
3646 @ The @schema should not be freed until the reader is deallocated
3647 * or its use has been deactivated.
3648 *
3649 * Returns 0 in case the RelaxNG validation could be (des)activated and
3650 * -1 in case of error.
3651 */
3652int
3653xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3654 if (schema == NULL) {
3655 if (reader->rngSchemas != NULL) {
3656 xmlRelaxNGFree(reader->rngSchemas);
3657 reader->rngSchemas = NULL;
3658 }
3659 if (reader->rngValidCtxt != NULL) {
3660 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3661 reader->rngValidCtxt = NULL;
3662 }
3663 return(0);
3664 }
3665 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3666 return(-1);
3667 if (reader->rngSchemas != NULL) {
3668 xmlRelaxNGFree(reader->rngSchemas);
3669 reader->rngSchemas = NULL;
3670 }
3671 if (reader->rngValidCtxt != NULL) {
3672 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3673 reader->rngValidCtxt = NULL;
3674 }
3675 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3676 if (reader->rngValidCtxt == NULL)
3677 return(-1);
3678 if (reader->errorFunc != NULL) {
3679 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3680 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3681 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3682 reader->errorFuncArg);
3683 }
3684 reader->rngValidErrors = 0;
3685 reader->rngFullNode = NULL;
3686 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3687 return(0);
3688}
3689
3690/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003691 * xmlTextReaderRelaxNGValidate:
3692 * @reader: the xmlTextReaderPtr used
3693 * @rng: the path to a RelaxNG schema or NULL
3694 *
3695 * Use RelaxNG to validate the document as it is processed.
3696 * Activation is only possible before the first Read().
3697 * if @rng is NULL, then RelaxNG validation is desactivated.
3698 *
3699 * Returns 0 in case the RelaxNG validation could be (des)activated and
3700 * -1 in case of error.
3701 */
3702int
3703xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3704 xmlRelaxNGParserCtxtPtr ctxt;
3705
3706 if (reader == NULL)
3707 return(-1);
3708
3709 if (rng == NULL) {
3710 if (reader->rngSchemas != NULL) {
3711 xmlRelaxNGFree(reader->rngSchemas);
3712 reader->rngSchemas = NULL;
3713 }
3714 if (reader->rngValidCtxt != NULL) {
3715 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3716 reader->rngValidCtxt = NULL;
3717 }
3718 return(0);
3719 }
3720 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3721 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003722 if (reader->rngSchemas != NULL) {
3723 xmlRelaxNGFree(reader->rngSchemas);
3724 reader->rngSchemas = NULL;
3725 }
3726 if (reader->rngValidCtxt != NULL) {
3727 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3728 reader->rngValidCtxt = NULL;
3729 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003730 ctxt = xmlRelaxNGNewParserCtxt(rng);
3731 if (reader->errorFunc != NULL) {
3732 xmlRelaxNGSetParserErrors(ctxt,
3733 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3734 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3735 reader->errorFuncArg);
3736 }
3737 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3738 xmlRelaxNGFreeParserCtxt(ctxt);
3739 if (reader->rngSchemas == NULL)
3740 return(-1);
3741 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3742 if (reader->rngValidCtxt == NULL)
3743 return(-1);
3744 if (reader->errorFunc != NULL) {
3745 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3746 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3747 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3748 reader->errorFuncArg);
3749 }
3750 reader->rngValidErrors = 0;
3751 reader->rngFullNode = NULL;
3752 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3753 return(0);
3754}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003755#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003756
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003757/************************************************************************
3758 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003759 * Error Handling Extensions *
3760 * *
3761 ************************************************************************/
3762
3763/* helper to build a xmlMalloc'ed string from a format and va_list */
3764static char *
3765xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3766 int size;
3767 int chars;
3768 char *larger;
3769 char *str;
3770
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003771 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003772 if (str == NULL) {
3773 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3774 return NULL;
3775 }
3776
3777 size = 150;
3778
3779 while (1) {
3780 chars = vsnprintf(str, size, msg, ap);
3781 if ((chars > -1) && (chars < size))
3782 break;
3783 if (chars > -1)
3784 size += chars + 1;
3785 else
3786 size += 100;
3787 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3788 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3789 xmlFree(str);
3790 return NULL;
3791 }
3792 str = larger;
3793 }
3794
3795 return str;
3796}
3797
Daniel Veillard417be3a2003-01-20 21:26:34 +00003798/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003799 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003800 * @locator: the xmlTextReaderLocatorPtr used
3801 *
3802 * Obtain the line number for the given locator.
3803 *
3804 * Returns the line number or -1 in case of error.
3805 */
3806int
3807xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3808 /* we know that locator is a xmlParserCtxtPtr */
3809 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3810 int ret = -1;
3811
3812 if (ctx->node != NULL) {
3813 ret = xmlGetLineNo(ctx->node);
3814 }
3815 else {
3816 /* inspired from error.c */
3817 xmlParserInputPtr input;
3818 input = ctx->input;
3819 if ((input->filename == NULL) && (ctx->inputNr > 1))
3820 input = ctx->inputTab[ctx->inputNr - 2];
3821 if (input != NULL) {
3822 ret = input->line;
3823 }
3824 else {
3825 ret = -1;
3826 }
3827 }
3828
3829 return ret;
3830}
3831
3832/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003833 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003834 * @locator: the xmlTextReaderLocatorPtr used
3835 *
3836 * Obtain the base URI for the given locator.
3837 *
3838 * Returns the base URI or NULL in case of error.
3839 */
3840xmlChar *
3841xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3842 /* we know that locator is a xmlParserCtxtPtr */
3843 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3844 xmlChar *ret = NULL;
3845
3846 if (ctx->node != NULL) {
3847 ret = xmlNodeGetBase(NULL,ctx->node);
3848 }
3849 else {
3850 /* inspired from error.c */
3851 xmlParserInputPtr input;
3852 input = ctx->input;
3853 if ((input->filename == NULL) && (ctx->inputNr > 1))
3854 input = ctx->inputTab[ctx->inputNr - 2];
3855 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003856 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003857 }
3858 else {
3859 ret = NULL;
3860 }
3861 }
3862
3863 return ret;
3864}
3865
Daniel Veillard26f70262003-01-16 22:45:08 +00003866static void
William M. Brack899e64a2003-09-26 18:03:42 +00003867xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003868 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3869 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3870
3871 if (str != NULL) {
3872 reader->errorFunc(reader->errorFuncArg,
3873 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003874 severity,
3875 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003876 xmlFree(str);
3877 }
3878}
3879
3880static void
3881xmlTextReaderError(void *ctxt, const char *msg, ...) {
3882 va_list ap;
3883
3884 va_start(ap,msg);
3885 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003886 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003887 xmlTextReaderBuildMessage(msg,ap));
3888 va_end(ap);
3889
3890}
3891
3892static void
3893xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3894 va_list ap;
3895
3896 va_start(ap,msg);
3897 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003898 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003899 xmlTextReaderBuildMessage(msg,ap));
3900 va_end(ap);
3901}
3902
3903static void
3904xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3905 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003906 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003907
Daniel Veillard417be3a2003-01-20 21:26:34 +00003908 if ((len > 1) && (msg[len - 2] != ':')) {
3909 /*
3910 * some callbacks only report locator information:
3911 * skip them (mimicking behaviour in error.c)
3912 */
3913 va_start(ap,msg);
3914 xmlTextReaderGenericError(ctxt,
3915 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3916 xmlTextReaderBuildMessage(msg,ap));
3917 va_end(ap);
3918 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003919}
3920
3921static void
3922xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3923 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003924 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003925
Daniel Veillard417be3a2003-01-20 21:26:34 +00003926 if ((len != 0) && (msg[len - 1] != ':')) {
3927 /*
3928 * some callbacks only report locator information:
3929 * skip them (mimicking behaviour in error.c)
3930 */
3931 va_start(ap,msg);
3932 xmlTextReaderGenericError(ctxt,
3933 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3934 xmlTextReaderBuildMessage(msg,ap));
3935 va_end(ap);
3936 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003937}
3938
3939/**
3940 * xmlTextReaderSetErrorHandler:
3941 * @reader: the xmlTextReaderPtr used
3942 * @f: the callback function to call on error and warnings
3943 * @arg: a user argument to pass to the callback function
3944 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003945 * Register a callback function that will be called on error and warnings.
3946 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003947 * If @f is NULL, the default error and warning handlers are restored.
3948 */
3949void
3950xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3951 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003952 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003953 if (f != NULL) {
3954 reader->ctxt->sax->error = xmlTextReaderError;
3955 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3956 reader->ctxt->sax->warning = xmlTextReaderWarning;
3957 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3958 reader->errorFunc = f;
3959 reader->errorFuncArg = arg;
3960 }
3961 else {
3962 /* restore defaults */
3963 reader->ctxt->sax->error = xmlParserError;
3964 reader->ctxt->vctxt.error = xmlParserValidityError;
3965 reader->ctxt->sax->warning = xmlParserWarning;
3966 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3967 reader->errorFunc = NULL;
3968 reader->errorFuncArg = NULL;
3969 }
3970}
3971
Daniel Veillard417be3a2003-01-20 21:26:34 +00003972/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003973 * xmlTextReaderIsValid:
3974 * @reader: the xmlTextReaderPtr used
3975 *
3976 * Retrieve the validity status from the parser context
3977 *
3978 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3979 */
3980int
3981xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003982 if (reader == NULL) return(-1);
3983#ifdef LIBXML_SCHEMAS_ENABLED
3984 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3985 return(reader->rngValidErrors == 0);
3986#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00003987 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardf4e55762003-04-15 23:32:22 +00003988 return(reader->ctxt->valid);
3989 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003990}
3991
3992/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003993 * xmlTextReaderGetErrorHandler:
3994 * @reader: the xmlTextReaderPtr used
3995 * @f: the callback function or NULL is no callback has been registered
3996 * @arg: a user argument
3997 *
3998 * Retrieve the error callback function and user argument.
3999 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004000void
4001xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4002 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004003 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00004004 *f = reader->errorFunc;
4005 *arg = reader->errorFuncArg;
4006}
4007
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004008
4009/************************************************************************
4010 * *
4011 * New set (2.6.0) of simpler and more flexible APIs *
4012 * *
4013 ************************************************************************/
4014
4015/**
4016 * xmlTextReaderSetup:
4017 * @reader: an XML reader
4018 * @URL: the base URL to use for the document
4019 * @encoding: the document encoding, or NULL
4020 * @options: a combination of xmlParserOption(s)
4021 * @reuse: keep the context for reuse
4022 *
4023 * Setup an XML reader with new options
4024 *
4025 * Returns 0 in case of success and -1 in case of error.
4026 */
4027static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004028xmlTextReaderSetup(xmlTextReaderPtr reader,
4029 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004030 const char *encoding, int options)
4031{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004032 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004033 return (-1);
4034
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004035 reader->doc = NULL;
4036 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004037 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00004038 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004039 if ((input != NULL) && (reader->input != NULL) &&
4040 (reader->allocs & XML_TEXTREADER_INPUT)) {
4041 xmlFreeParserInputBuffer(reader->input);
4042 reader->input = NULL;
4043 reader->allocs -= XML_TEXTREADER_INPUT;
4044 }
4045 if (input != NULL) {
4046 reader->input = input;
4047 reader->allocs |= XML_TEXTREADER_INPUT;
4048 }
4049 if (reader->buffer == NULL)
4050 reader->buffer = xmlBufferCreateSize(100);
4051 if (reader->buffer == NULL) {
4052 xmlGenericError(xmlGenericErrorContext,
4053 "xmlTextReaderSetup : malloc failed\n");
4054 return (-1);
4055 }
4056 if (reader->sax == NULL)
4057 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
4058 if (reader->sax == NULL) {
4059 xmlGenericError(xmlGenericErrorContext,
4060 "xmlTextReaderSetup : malloc failed\n");
4061 return (-1);
4062 }
4063 xmlSAXVersion(reader->sax, 2);
4064 reader->startElement = reader->sax->startElement;
4065 reader->sax->startElement = xmlTextReaderStartElement;
4066 reader->endElement = reader->sax->endElement;
4067 reader->sax->endElement = xmlTextReaderEndElement;
4068#ifdef LIBXML_SAX1_ENABLED
4069 if (reader->sax->initialized == XML_SAX2_MAGIC) {
4070#endif /* LIBXML_SAX1_ENABLED */
4071 reader->startElementNs = reader->sax->startElementNs;
4072 reader->sax->startElementNs = xmlTextReaderStartElementNs;
4073 reader->endElementNs = reader->sax->endElementNs;
4074 reader->sax->endElementNs = xmlTextReaderEndElementNs;
4075#ifdef LIBXML_SAX1_ENABLED
4076 } else {
4077 reader->startElementNs = NULL;
4078 reader->endElementNs = NULL;
4079 }
4080#endif /* LIBXML_SAX1_ENABLED */
4081 reader->characters = reader->sax->characters;
4082 reader->sax->characters = xmlTextReaderCharacters;
4083 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
4084 reader->cdataBlock = reader->sax->cdataBlock;
4085 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
4086
4087 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4088 reader->node = NULL;
4089 reader->curnode = NULL;
4090 if (input != NULL) {
4091 if (reader->input->buffer->use < 4) {
4092 xmlParserInputBufferRead(input, 4);
4093 }
4094 if (reader->ctxt == NULL) {
4095 if (reader->input->buffer->use >= 4) {
4096 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
4097 (const char *) reader->input->buffer->content, 4, URL);
4098 reader->base = 0;
4099 reader->cur = 4;
4100 } else {
4101 reader->ctxt =
4102 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
4103 reader->base = 0;
4104 reader->cur = 0;
4105 }
4106 } else {
4107 xmlParserInputPtr inputStream;
4108 xmlParserInputBufferPtr buf;
4109 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
4110
4111 if (reader->ctxt->myDoc != NULL)
4112 xmlDictReference(reader->ctxt->myDoc->dict);
4113 xmlCtxtReset(reader->ctxt);
4114 buf = xmlAllocParserInputBuffer(enc);
4115 if (buf == NULL) return(-1);
4116 inputStream = xmlNewInputStream(reader->ctxt);
4117 if (inputStream == NULL) {
4118 xmlFreeParserInputBuffer(buf);
4119 return(-1);
4120 }
4121
4122 if (URL == NULL)
4123 inputStream->filename = NULL;
4124 else
4125 inputStream->filename = (char *)
4126 xmlCanonicPath((const xmlChar *) URL);
4127 inputStream->buf = buf;
4128 inputStream->base = inputStream->buf->buffer->content;
4129 inputStream->cur = inputStream->buf->buffer->content;
4130 inputStream->end =
4131 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
4132
4133 inputPush(reader->ctxt, inputStream);
4134 reader->cur = 0;
4135 }
4136 if (reader->ctxt == NULL) {
4137 xmlGenericError(xmlGenericErrorContext,
4138 "xmlTextReaderSetup : malloc failed\n");
4139 return (-1);
4140 }
4141 }
4142 if (reader->dict != NULL) {
4143 if (reader->ctxt->dict != NULL) {
4144 if (reader->dict != reader->ctxt->dict) {
4145 xmlDictFree(reader->dict);
4146 reader->dict = reader->ctxt->dict;
4147 }
4148 } else {
4149 reader->ctxt->dict = reader->dict;
4150 }
4151 } else {
4152 if (reader->ctxt->dict == NULL)
4153 reader->ctxt->dict = xmlDictCreate();
4154 reader->dict = reader->ctxt->dict;
4155 }
4156 reader->ctxt->_private = reader;
4157 reader->ctxt->linenumbers = 1;
4158 reader->ctxt->dictNames = 1;
4159 /*
4160 * use the parser dictionnary to allocate all elements and attributes names
4161 */
4162 reader->ctxt->docdict = 1;
4163
Daniel Veillard7899c5c2003-11-03 12:31:38 +00004164#ifdef LIBXML_XINCLUDE_ENABLED
4165 if (reader->xincctxt != NULL) {
4166 xmlXIncludeFreeContext(reader->xincctxt);
4167 reader->xincctxt = NULL;
4168 }
4169 if (options & XML_PARSE_XINCLUDE) {
4170 reader->xinclude = 1;
4171 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
4172 options -= XML_PARSE_XINCLUDE;
4173 } else
4174 reader->xinclude = 0;
4175 reader->in_xinclude = 0;
4176#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00004177#ifdef LIBXML_PATTERN_ENABLED
4178 if (reader->patternTab == NULL) {
4179 reader->patternNr = 0;
4180 reader->patternMax = 0;
4181 }
4182 while (reader->patternNr > 0) {
4183 reader->patternNr--;
4184 if (reader->patternTab[reader->patternNr] != NULL) {
4185 xmlFreePattern(reader->patternTab[reader->patternNr]);
4186 reader->patternTab[reader->patternNr] = NULL;
4187 }
4188 }
4189#endif
4190
Daniel Veillardc36965d2003-12-02 10:28:48 +00004191 if (options & XML_PARSE_DTDVALID)
4192 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
4193
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004194 xmlCtxtUseOptions(reader->ctxt, options);
4195 if (encoding != NULL) {
4196 xmlCharEncodingHandlerPtr hdlr;
4197
4198 hdlr = xmlFindCharEncodingHandler(encoding);
4199 if (hdlr != NULL)
4200 xmlSwitchToEncoding(reader->ctxt, hdlr);
4201 }
4202 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
4203 (reader->ctxt->input->filename == NULL))
4204 reader->ctxt->input->filename = (char *)
4205 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004206
4207 reader->doc = NULL;
4208
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004209 return (0);
4210}
4211
4212/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004213 * xmlReaderWalker:
4214 * @doc: a preparsed document
4215 *
4216 * Create an xmltextReader for a preparsed document.
4217 *
4218 * Returns the new reader or NULL in case of error.
4219 */
4220xmlTextReaderPtr
4221xmlReaderWalker(xmlDocPtr doc)
4222{
4223 xmlTextReaderPtr ret;
4224
4225 if (doc == NULL)
4226 return(NULL);
4227
4228 ret = xmlMalloc(sizeof(xmlTextReader));
4229 if (ret == NULL) {
4230 xmlGenericError(xmlGenericErrorContext,
4231 "xmlNewTextReader : malloc failed\n");
4232 return(NULL);
4233 }
4234 memset(ret, 0, sizeof(xmlTextReader));
4235 ret->entNr = 0;
4236 ret->input = NULL;
4237 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4238 ret->node = NULL;
4239 ret->curnode = NULL;
4240 ret->base = 0;
4241 ret->cur = 0;
4242 ret->allocs = XML_TEXTREADER_CTXT;
4243 ret->doc = doc;
4244 ret->state = XML_TEXTREADER_START;
4245 ret->dict = xmlDictCreate();
4246 return(ret);
4247}
4248
4249/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004250 * xmlReaderForDoc:
4251 * @cur: a pointer to a zero terminated string
4252 * @URL: the base URL to use for the document
4253 * @encoding: the document encoding, or NULL
4254 * @options: a combination of xmlParserOption(s)
4255 *
4256 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004257 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004258 *
4259 * Returns the new reader or NULL in case of error.
4260 */
4261xmlTextReaderPtr
4262xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4263 int options)
4264{
4265 int len;
4266
4267 if (cur == NULL)
4268 return (NULL);
4269 len = xmlStrlen(cur);
4270
4271 return (xmlReaderForMemory
4272 ((const char *) cur, len, URL, encoding, options));
4273}
4274
4275/**
4276 * xmlReaderForFile:
4277 * @filename: a file or URL
4278 * @encoding: the document encoding, or NULL
4279 * @options: a combination of xmlParserOption(s)
4280 *
4281 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004282 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004283 *
4284 * Returns the new reader or NULL in case of error.
4285 */
4286xmlTextReaderPtr
4287xmlReaderForFile(const char *filename, const char *encoding, int options)
4288{
4289 xmlTextReaderPtr reader;
4290
4291 reader = xmlNewTextReaderFilename(filename);
4292 if (reader == NULL)
4293 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004294 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004295 return (reader);
4296}
4297
4298/**
4299 * xmlReaderForMemory:
4300 * @buffer: a pointer to a char array
4301 * @size: the size of the array
4302 * @URL: the base URL to use for the document
4303 * @encoding: the document encoding, or NULL
4304 * @options: a combination of xmlParserOption(s)
4305 *
4306 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004307 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004308 *
4309 * Returns the new reader or NULL in case of error.
4310 */
4311xmlTextReaderPtr
4312xmlReaderForMemory(const char *buffer, int size, const char *URL,
4313 const char *encoding, int options)
4314{
4315 xmlTextReaderPtr reader;
4316 xmlParserInputBufferPtr buf;
4317
4318 buf =
4319 xmlParserInputBufferCreateMem(buffer, size,
4320 XML_CHAR_ENCODING_NONE);
4321 if (buf == NULL) {
4322 return (NULL);
4323 }
4324 reader = xmlNewTextReader(buf, URL);
4325 if (reader == NULL) {
4326 xmlFreeParserInputBuffer(buf);
4327 return (NULL);
4328 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004329 reader->allocs |= XML_TEXTREADER_INPUT;
4330 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004331 return (reader);
4332}
4333
4334/**
4335 * xmlReaderForFd:
4336 * @fd: an open file descriptor
4337 * @URL: the base URL to use for the document
4338 * @encoding: the document encoding, or NULL
4339 * @options: a combination of xmlParserOption(s)
4340 *
4341 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004342 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004343 *
4344 * Returns the new reader or NULL in case of error.
4345 */
4346xmlTextReaderPtr
4347xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4348{
4349 xmlTextReaderPtr reader;
4350 xmlParserInputBufferPtr input;
4351
4352 if (fd < 0)
4353 return (NULL);
4354
4355 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4356 if (input == NULL)
4357 return (NULL);
4358 reader = xmlNewTextReader(input, URL);
4359 if (reader == NULL) {
4360 xmlFreeParserInputBuffer(input);
4361 return (NULL);
4362 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004363 reader->allocs |= XML_TEXTREADER_INPUT;
4364 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004365 return (reader);
4366}
4367
4368/**
4369 * xmlReaderForIO:
4370 * @ioread: an I/O read function
4371 * @ioclose: an I/O close function
4372 * @ioctx: an I/O handler
4373 * @URL: the base URL to use for the document
4374 * @encoding: the document encoding, or NULL
4375 * @options: a combination of xmlParserOption(s)
4376 *
4377 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004378 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004379 *
4380 * Returns the new reader or NULL in case of error.
4381 */
4382xmlTextReaderPtr
4383xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4384 void *ioctx, const char *URL, const char *encoding,
4385 int options)
4386{
4387 xmlTextReaderPtr reader;
4388 xmlParserInputBufferPtr input;
4389
4390 if (ioread == NULL)
4391 return (NULL);
4392
4393 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4394 XML_CHAR_ENCODING_NONE);
4395 if (input == NULL)
4396 return (NULL);
4397 reader = xmlNewTextReader(input, URL);
4398 if (reader == NULL) {
4399 xmlFreeParserInputBuffer(input);
4400 return (NULL);
4401 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004402 reader->allocs |= XML_TEXTREADER_INPUT;
4403 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004404 return (reader);
4405}
4406
4407/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004408 * xmlReaderNewWalker:
4409 * @reader: an XML reader
4410 * @doc: a preparsed document
4411 *
4412 * Setup an xmltextReader to parse a preparsed XML document.
4413 * This reuses the existing @reader xmlTextReader.
4414 *
4415 * Returns 0 in case of success and -1 in case of error
4416 */
4417int
4418xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4419{
4420 if (doc == NULL)
4421 return (-1);
4422 if (reader == NULL)
4423 return (-1);
4424
4425 if (reader->ctxt != NULL) {
4426 xmlCtxtReset(reader->ctxt);
4427 }
4428
4429 reader->entNr = 0;
4430 reader->input = NULL;
4431 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4432 reader->node = NULL;
4433 reader->curnode = NULL;
4434 reader->base = 0;
4435 reader->cur = 0;
4436 reader->allocs = XML_TEXTREADER_CTXT;
4437 reader->doc = doc;
4438 reader->state = XML_TEXTREADER_START;
4439 if (reader->dict == NULL) {
4440 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4441 reader->dict = reader->ctxt->dict;
4442 else
4443 reader->dict = xmlDictCreate();
4444 }
4445 return(0);
4446}
4447
4448/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004449 * xmlReaderNewDoc:
4450 * @reader: an XML reader
4451 * @cur: a pointer to a zero terminated string
4452 * @URL: the base URL to use for the document
4453 * @encoding: the document encoding, or NULL
4454 * @options: a combination of xmlParserOption(s)
4455 *
4456 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004457 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004458 * This reuses the existing @reader xmlTextReader.
4459 *
4460 * Returns 0 in case of success and -1 in case of error
4461 */
4462int
4463xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4464 const char *URL, const char *encoding, int options)
4465{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004466
4467 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004468
4469 if (cur == NULL)
4470 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004471 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004472 return (-1);
4473
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004474 len = xmlStrlen(cur);
4475 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4476 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004477}
4478
4479/**
4480 * xmlReaderNewFile:
4481 * @reader: an XML reader
4482 * @filename: a file or URL
4483 * @encoding: the document encoding, or NULL
4484 * @options: a combination of xmlParserOption(s)
4485 *
4486 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004487 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004488 * This reuses the existing @reader xmlTextReader.
4489 *
4490 * Returns 0 in case of success and -1 in case of error
4491 */
4492int
4493xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4494 const char *encoding, int options)
4495{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004496 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004497
4498 if (filename == NULL)
4499 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004500 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004501 return (-1);
4502
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004503 input =
4504 xmlParserInputBufferCreateFilename(filename,
4505 XML_CHAR_ENCODING_NONE);
4506 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004507 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004508 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004509}
4510
4511/**
4512 * xmlReaderNewMemory:
4513 * @reader: an XML reader
4514 * @buffer: a pointer to a char array
4515 * @size: the size of the array
4516 * @URL: the base URL to use for the document
4517 * @encoding: the document encoding, or NULL
4518 * @options: a combination of xmlParserOption(s)
4519 *
4520 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004521 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004522 * This reuses the existing @reader xmlTextReader.
4523 *
4524 * Returns 0 in case of success and -1 in case of error
4525 */
4526int
4527xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4528 const char *URL, const char *encoding, int options)
4529{
4530 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004531
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004532 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004533 return (-1);
4534 if (buffer == NULL)
4535 return (-1);
4536
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004537 input = xmlParserInputBufferCreateMem(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004538 XML_CHAR_ENCODING_NONE);
4539 if (input == NULL) {
4540 return (-1);
4541 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004542 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004543}
4544
4545/**
4546 * xmlReaderNewFd:
4547 * @reader: an XML reader
4548 * @fd: an open file descriptor
4549 * @URL: the base URL to use for the document
4550 * @encoding: the document encoding, or NULL
4551 * @options: a combination of xmlParserOption(s)
4552 *
4553 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004554 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004555 * This reuses the existing @reader xmlTextReader.
4556 *
4557 * Returns 0 in case of success and -1 in case of error
4558 */
4559int
4560xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4561 const char *URL, const char *encoding, int options)
4562{
4563 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004564
4565 if (fd < 0)
4566 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004567 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004568 return (-1);
4569
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004570 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4571 if (input == NULL)
4572 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004573 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004574}
4575
4576/**
4577 * xmlReaderNewIO:
4578 * @reader: an XML reader
4579 * @ioread: an I/O read function
4580 * @ioclose: an I/O close function
4581 * @ioctx: an I/O handler
4582 * @URL: the base URL to use for the document
4583 * @encoding: the document encoding, or NULL
4584 * @options: a combination of xmlParserOption(s)
4585 *
4586 * Setup an xmltextReader to parse an XML document from I/O functions
4587 * and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004588 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004589 * This reuses the existing @reader xmlTextReader.
4590 *
4591 * Returns 0 in case of success and -1 in case of error
4592 */
4593int
4594xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4595 xmlInputCloseCallback ioclose, void *ioctx,
4596 const char *URL, const char *encoding, int options)
4597{
4598 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004599
4600 if (ioread == NULL)
4601 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004602 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004603 return (-1);
4604
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004605 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4606 XML_CHAR_ENCODING_NONE);
4607 if (input == NULL)
4608 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004609 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004610}
Daniel Veillard26f70262003-01-16 22:45:08 +00004611/************************************************************************
4612 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004613 * Utilities *
4614 * *
4615 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004616#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004617/**
4618 * xmlBase64Decode:
4619 * @in: the input buffer
4620 * @inlen: the size of the input (in), the size read from it (out)
4621 * @to: the output buffer
4622 * @tolen: the size of the output (in), the size written to (out)
4623 *
4624 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004625 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004626 *
4627 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4628 * 2 if there wasn't enough space on the output or -1 in case of error.
4629 */
4630static int
4631xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4632 unsigned char *to, unsigned long *tolen) {
4633 unsigned long incur; /* current index in in[] */
4634 unsigned long inblk; /* last block index in in[] */
4635 unsigned long outcur; /* current index in out[] */
4636 unsigned long inmax; /* size of in[] */
4637 unsigned long outmax; /* size of out[] */
4638 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004639 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004640 int nbintmp; /* number of byte in intmp[] */
4641 int is_ignore; /* cur should be ignored */
4642 int is_end = 0; /* the end of the base64 was found */
4643 int retval = 1;
4644 int i;
4645
4646 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4647 return(-1);
4648
4649 incur = 0;
4650 inblk = 0;
4651 outcur = 0;
4652 inmax = *inlen;
4653 outmax = *tolen;
4654 nbintmp = 0;
4655
4656 while (1) {
4657 if (incur >= inmax)
4658 break;
4659 cur = in[incur++];
4660 is_ignore = 0;
4661 if ((cur >= 'A') && (cur <= 'Z'))
4662 cur = cur - 'A';
4663 else if ((cur >= 'a') && (cur <= 'z'))
4664 cur = cur - 'a' + 26;
4665 else if ((cur >= '0') && (cur <= '9'))
4666 cur = cur - '0' + 52;
4667 else if (cur == '+')
4668 cur = 62;
4669 else if (cur == '/')
4670 cur = 63;
4671 else if (cur == '.')
4672 cur = 0;
4673 else if (cur == '=') /*no op , end of the base64 stream */
4674 is_end = 1;
4675 else {
4676 is_ignore = 1;
4677 if (nbintmp == 0)
4678 inblk = incur;
4679 }
4680
4681 if (!is_ignore) {
4682 int nbouttmp = 3;
4683 int is_break = 0;
4684
4685 if (is_end) {
4686 if (nbintmp == 0)
4687 break;
4688 if ((nbintmp == 1) || (nbintmp == 2))
4689 nbouttmp = 1;
4690 else
4691 nbouttmp = 2;
4692 nbintmp = 3;
4693 is_break = 1;
4694 }
4695 intmp[nbintmp++] = cur;
4696 /*
4697 * if intmp is full, push the 4byte sequence as a 3 byte
4698 * sequence out
4699 */
4700 if (nbintmp == 4) {
4701 nbintmp = 0;
4702 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4703 outtmp[1] =
4704 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4705 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4706 if (outcur + 3 >= outmax) {
4707 retval = 2;
4708 break;
4709 }
4710
4711 for (i = 0; i < nbouttmp; i++)
4712 to[outcur++] = outtmp[i];
4713 inblk = incur;
4714 }
4715
4716 if (is_break) {
4717 retval = 0;
4718 break;
4719 }
4720 }
4721 }
4722
4723 *tolen = outcur;
4724 *inlen = inblk;
4725 return (retval);
4726}
4727
4728/*
4729 * Test routine for the xmlBase64Decode function
4730 */
4731#if 0
4732int main(int argc, char **argv) {
4733 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4734 char output[100];
4735 char output2[100];
4736 char output3[100];
4737 unsigned long inlen = strlen(input);
4738 unsigned long outlen = 100;
4739 int ret;
4740 unsigned long cons, tmp, tmp2, prod;
4741
4742 /*
4743 * Direct
4744 */
4745 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4746
4747 output[outlen] = 0;
4748 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4749
4750 /*
4751 * output chunking
4752 */
4753 cons = 0;
4754 prod = 0;
4755 while (cons < inlen) {
4756 tmp = 5;
4757 tmp2 = inlen - cons;
4758
4759 printf("%ld %ld\n", cons, prod);
4760 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4761 cons += tmp2;
4762 prod += tmp;
4763 printf("%ld %ld\n", cons, prod);
4764 }
4765 output2[outlen] = 0;
4766 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4767
4768 /*
4769 * input chunking
4770 */
4771 cons = 0;
4772 prod = 0;
4773 while (cons < inlen) {
4774 tmp = 100 - prod;
4775 tmp2 = inlen - cons;
4776 if (tmp2 > 5)
4777 tmp2 = 5;
4778
4779 printf("%ld %ld\n", cons, prod);
4780 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4781 cons += tmp2;
4782 prod += tmp;
4783 printf("%ld %ld\n", cons, prod);
4784 }
4785 output3[outlen] = 0;
4786 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4787 return(0);
4788
4789}
4790#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004791#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004792#endif /* LIBXML_READER_ENABLED */