blob: b4c9d707454b2d01218fba2da1e8d6470130ca17 [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 Veillardf4e55762003-04-15 23:32:22 +000038#include <libxml/relaxng.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000039
40/* #define DEBUG_CALLBACKS */
41/* #define DEBUG_READER */
42
43/**
44 * TODO:
45 *
46 * macro to flag unimplemented blocks
47 */
48#define TODO \
49 xmlGenericError(xmlGenericErrorContext, \
50 "Unimplemented block at %s:%d\n", \
51 __FILE__, __LINE__);
52
53#ifdef DEBUG_READER
54#define DUMP_READER xmlTextReaderDebug(reader);
55#else
56#define DUMP_READER
57#endif
58
Daniel Veillarda880b122003-04-21 21:36:41 +000059#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000060/************************************************************************
61 * *
62 * The parser: maps the Text Reader API on top of the existing *
63 * parsing routines building a tree *
64 * *
65 ************************************************************************/
66
67#define XML_TEXTREADER_INPUT 1
68#define XML_TEXTREADER_CTXT 2
69
70typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000071 XML_TEXTREADER_MODE_INITIAL = 0,
72 XML_TEXTREADER_MODE_INTERACTIVE = 1,
73 XML_TEXTREADER_MODE_ERROR = 2,
74 XML_TEXTREADER_MODE_EOF =3,
75 XML_TEXTREADER_MODE_CLOSED = 4,
76 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000077} xmlTextReaderMode;
78
79typedef enum {
80 XML_TEXTREADER_NONE = -1,
81 XML_TEXTREADER_START= 0,
82 XML_TEXTREADER_ELEMENT= 1,
83 XML_TEXTREADER_END= 2,
84 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000085 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000086 XML_TEXTREADER_DONE= 5,
87 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000088} xmlTextReaderState;
89
Daniel Veillardf4e55762003-04-15 23:32:22 +000090typedef enum {
91 XML_TEXTREADER_NOT_VALIDATE = 0,
92 XML_TEXTREADER_VALIDATE_DTD = 1,
93 XML_TEXTREADER_VALIDATE_RNG = 2
94} xmlTextReaderValidate;
95
Daniel Veillarde1ca5032002-12-09 14:13:43 +000096struct _xmlTextReader {
97 int mode; /* the parsing mode */
Daniel Veillardf4e55762003-04-15 23:32:22 +000098 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000099 int allocs; /* what structure were deallocated */
100 xmlTextReaderState state;
101 xmlParserCtxtPtr ctxt; /* the parser context */
102 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
103 xmlParserInputBufferPtr input; /* the input */
104 startElementSAXFunc startElement;/* initial SAX callbacks */
105 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000106 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000107 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000108 charactersSAXFunc characters;
109 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000110 unsigned int base; /* base of the segment in the input */
111 unsigned int cur; /* current position in the input */
112 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000113 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000114 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000115 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000116 int preserve;/* preserve the resulting document */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000117
118 /* entity stack when traversing entities content */
119 xmlNodePtr ent; /* Current Entity Ref Node */
120 int entNr; /* Depth of the entities stack */
121 int entMax; /* Max depth of the entities stack */
122 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000123
124 /* error handling */
125 xmlTextReaderErrorFunc errorFunc; /* callback function */
126 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000127
128#ifdef LIBXML_SCHEMAS_ENABLED
129 /* Handling of RelaxNG validation */
130 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
131 xmlRelaxNGValidCtxtPtr rngValidCtxt; /* The Relax NG validation context */
132 int rngValidErrors; /* The number of errors detected */
133 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
134#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000135};
136
Daniel Veillard067bae52003-01-05 01:27:54 +0000137static const char *xmlTextReaderIsEmpty = "This element is empty";
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000138static const char *xmlTextReaderIsEmptyPreserved = "Preserve this element";
139static const char *xmlTextReaderIsPreserved = "Preserve this element";
Daniel Veillard067bae52003-01-05 01:27:54 +0000140
Daniel Veillarde72c5082003-09-19 12:44:05 +0000141/**
142 * CONSTSTR:
143 *
144 * Macro used to return an interned string
145 */
146#define CONSTSTR(str) xmlDictLookup(reader->ctxt->dict, (str), -1)
147#define CONSTQSTR(p, str) xmlDictQLookup(reader->ctxt->dict, (p), (str))
148
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000149/************************************************************************
150 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000151 * Our own version of the freeing routines as we recycle nodes *
152 * *
153 ************************************************************************/
154/**
155 * DICT_FREE:
156 * @str: a string
157 *
158 * Free a string if it is not owned by the "dict" dictionnary in the
159 * current scope
160 */
161#define DICT_FREE(str) \
162 if ((str) && ((!dict) || \
163 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
164 xmlFree((char *)(str));
165
166static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
167static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
168
169/**
170 * xmlTextReaderFreeProp:
171 * @reader: the xmlTextReaderPtr used
172 * @cur: the node
173 *
174 * Free a node.
175 */
176static void
177xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
178 xmlDictPtr dict;
179
180 dict = reader->ctxt->dict;
181 if (cur == NULL) return;
182
183 /* Check for ID removal -> leading to invalid references ! */
184 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
185 ((cur->parent->doc->intSubset != NULL) ||
186 (cur->parent->doc->extSubset != NULL))) {
187 if (xmlIsID(cur->parent->doc, cur->parent, cur))
188 xmlRemoveID(cur->parent->doc, cur);
189 }
190 if (cur->children != NULL)
191 xmlTextReaderFreeNodeList(reader, cur->children);
192
193 DICT_FREE(cur->name);
194 if ((reader != NULL) && (reader->ctxt != NULL) &&
195 (reader->ctxt->freeAttrsNr < 100)) {
196 cur->next = reader->ctxt->freeAttrs;
197 reader->ctxt->freeAttrs = cur;
198 reader->ctxt->freeAttrsNr++;
199 } else {
200 xmlFree(cur);
201 }
202}
203
204/**
205 * xmlTextReaderFreePropList:
206 * @reader: the xmlTextReaderPtr used
207 * @cur: the first property in the list
208 *
209 * Free a property and all its siblings, all the children are freed too.
210 */
211static void
212xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
213 xmlAttrPtr next;
214 if (cur == NULL) return;
215 while (cur != NULL) {
216 next = cur->next;
217 xmlTextReaderFreeProp(reader, cur);
218 cur = next;
219 }
220}
221
222/**
223 * xmlTextReaderFreeNodeList:
224 * @reader: the xmlTextReaderPtr used
225 * @cur: the first node in the list
226 *
227 * Free a node and all its siblings, this is a recursive behaviour, all
228 * the children are freed too.
229 */
230static void
231xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
232 xmlNodePtr next;
233 xmlDictPtr dict;
234
235 dict = reader->ctxt->dict;
236 if (cur == NULL) return;
237 if (cur->type == XML_NAMESPACE_DECL) {
238 xmlFreeNsList((xmlNsPtr) cur);
239 return;
240 }
241 if ((cur->type == XML_DOCUMENT_NODE) ||
242 (cur->type == XML_HTML_DOCUMENT_NODE)) {
243 xmlFreeDoc((xmlDocPtr) cur);
244 return;
245 }
246 while (cur != NULL) {
247 next = cur->next;
248 /* unroll to speed up freeing the document */
249 if (cur->type != XML_DTD_NODE) {
250
251 if ((cur->children != NULL) &&
252 (cur->type != XML_ENTITY_REF_NODE))
253 xmlTextReaderFreeNodeList(reader, cur->children);
254 if (((cur->type == XML_ELEMENT_NODE) ||
255 (cur->type == XML_XINCLUDE_START) ||
256 (cur->type == XML_XINCLUDE_END)) &&
257 (cur->properties != NULL))
258 xmlTextReaderFreePropList(reader, cur->properties);
259 if ((cur->type != XML_ELEMENT_NODE) &&
260 (cur->type != XML_XINCLUDE_START) &&
261 (cur->type != XML_XINCLUDE_END) &&
262 (cur->type != XML_ENTITY_REF_NODE)) {
263 DICT_FREE(cur->content);
264 }
265 if (((cur->type == XML_ELEMENT_NODE) ||
266 (cur->type == XML_XINCLUDE_START) ||
267 (cur->type == XML_XINCLUDE_END)) &&
268 (cur->nsDef != NULL))
269 xmlFreeNsList(cur->nsDef);
270
271 /*
272 * we don't free element names here they are interned now
273 */
274 if ((cur->type != XML_TEXT_NODE) &&
275 (cur->type != XML_COMMENT_NODE))
276 DICT_FREE(cur->name);
277 if (((cur->type == XML_ELEMENT_NODE) ||
278 (cur->type == XML_TEXT_NODE)) &&
279 (reader != NULL) && (reader->ctxt != NULL) &&
280 (reader->ctxt->freeElemsNr < 100)) {
281 cur->next = reader->ctxt->freeElems;
282 reader->ctxt->freeElems = cur;
283 reader->ctxt->freeElemsNr++;
284 } else {
285 xmlFree(cur);
286 }
287 }
288 cur = next;
289 }
290}
291
292/**
293 * xmlTextReaderFreeNode:
294 * @reader: the xmlTextReaderPtr used
295 * @cur: the node
296 *
297 * Free a node, this is a recursive behaviour, all the children are freed too.
298 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
299 */
300static void
301xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
302 xmlDictPtr dict;
303
304 dict = reader->ctxt->dict;
305 if (cur->type == XML_DTD_NODE) {
306 xmlFreeDtd((xmlDtdPtr) cur);
307 return;
308 }
309 if (cur->type == XML_NAMESPACE_DECL) {
310 xmlFreeNs((xmlNsPtr) cur);
311 return;
312 }
313 if (cur->type == XML_ATTRIBUTE_NODE) {
314 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
315 return;
316 }
317
318 if ((cur->children != NULL) &&
319 (cur->type != XML_ENTITY_REF_NODE))
320 xmlTextReaderFreeNodeList(reader, cur->children);
321 if (((cur->type == XML_ELEMENT_NODE) ||
322 (cur->type == XML_XINCLUDE_START) ||
323 (cur->type == XML_XINCLUDE_END)) &&
324 (cur->properties != NULL))
325 xmlTextReaderFreePropList(reader, cur->properties);
326 if ((cur->type != XML_ELEMENT_NODE) &&
327 (cur->type != XML_XINCLUDE_START) &&
328 (cur->type != XML_XINCLUDE_END) &&
329 (cur->type != XML_ENTITY_REF_NODE)) {
330 DICT_FREE(cur->content);
331 }
332 if (((cur->type == XML_ELEMENT_NODE) ||
333 (cur->type == XML_XINCLUDE_START) ||
334 (cur->type == XML_XINCLUDE_END)) &&
335 (cur->nsDef != NULL))
336 xmlFreeNsList(cur->nsDef);
337
338 /*
339 * we don't free names here they are interned now
340 */
341 if ((cur->type != XML_TEXT_NODE) &&
342 (cur->type != XML_COMMENT_NODE))
343 DICT_FREE(cur->name);
344 if (((cur->type == XML_ELEMENT_NODE) ||
345 (cur->type == XML_TEXT_NODE)) &&
346 (reader != NULL) && (reader->ctxt != NULL) &&
347 (reader->ctxt->freeElemsNr < 100)) {
348 cur->next = reader->ctxt->freeElems;
349 reader->ctxt->freeElems = cur;
350 reader->ctxt->freeElemsNr++;
351 } else {
352 xmlFree(cur);
353 }
354}
355
356/**
357 * xmlTextReaderFreeDoc:
358 * @reader: the xmlTextReaderPtr used
359 * @cur: pointer to the document
360 *
361 * Free up all the structures used by a document, tree included.
362 */
363static void
364xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
365 xmlDtdPtr extSubset, intSubset;
366
367 if (cur == NULL) return;
368
369 /*
370 * Do this before freeing the children list to avoid ID lookups
371 */
372 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
373 cur->ids = NULL;
374 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
375 cur->refs = NULL;
376 extSubset = cur->extSubset;
377 intSubset = cur->intSubset;
378 if (intSubset == extSubset)
379 extSubset = NULL;
380 if (extSubset != NULL) {
381 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
382 cur->extSubset = NULL;
383 xmlFreeDtd(extSubset);
384 }
385 if (intSubset != NULL) {
386 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
387 cur->intSubset = NULL;
388 xmlFreeDtd(intSubset);
389 }
390
391 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
392
393 if (cur->version != NULL) xmlFree((char *) cur->version);
394 if (cur->name != NULL) xmlFree((char *) cur->name);
395 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
396 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
397 if (cur->URL != NULL) xmlFree((char *) cur->URL);
398 xmlFree(cur);
399}
400
401/************************************************************************
402 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000403 * The reader core parser *
404 * *
405 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000406#ifdef DEBUG_READER
407static void
408xmlTextReaderDebug(xmlTextReaderPtr reader) {
409 if ((reader == NULL) || (reader->ctxt == NULL)) {
410 fprintf(stderr, "xmlTextReader NULL\n");
411 return;
412 }
413 fprintf(stderr, "xmlTextReader: state %d depth %d ",
414 reader->state, reader->depth);
415 if (reader->node == NULL) {
416 fprintf(stderr, "node = NULL\n");
417 } else {
418 fprintf(stderr, "node %s\n", reader->node->name);
419 }
420 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
421 reader->base, reader->cur, reader->ctxt->nodeNr);
422 if (reader->input->buffer == NULL) {
423 fprintf(stderr, "buffer is NULL\n");
424 } else {
425#ifdef LIBXML_DEBUG_ENABLED
426 xmlDebugDumpString(stderr,
427 &reader->input->buffer->content[reader->cur]);
428#endif
429 fprintf(stderr, "\n");
430 }
431}
432#endif
433
434/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000435 * xmlTextReaderEntPush:
436 * @reader: the xmlTextReaderPtr used
437 * @value: the entity reference node
438 *
439 * Pushes a new entity reference node on top of the entities stack
440 *
441 * Returns 0 in case of error, the index in the stack otherwise
442 */
443static int
444xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
445{
446 if (reader->entMax <= 0) {
447 reader->entMax = 10;
448 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
449 sizeof(reader->entTab[0]));
450 if (reader->entTab == NULL) {
451 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
452 return (0);
453 }
454 }
455 if (reader->entNr >= reader->entMax) {
456 reader->entMax *= 2;
457 reader->entTab =
458 (xmlNodePtr *) xmlRealloc(reader->entTab,
459 reader->entMax *
460 sizeof(reader->entTab[0]));
461 if (reader->entTab == NULL) {
462 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
463 return (0);
464 }
465 }
466 reader->entTab[reader->entNr] = value;
467 reader->ent = value;
468 return (reader->entNr++);
469}
470
471/**
472 * xmlTextReaderEntPop:
473 * @reader: the xmlTextReaderPtr used
474 *
475 * Pops the top element entity from the entities stack
476 *
477 * Returns the entity just removed
478 */
479static xmlNodePtr
480xmlTextReaderEntPop(xmlTextReaderPtr reader)
481{
482 xmlNodePtr ret;
483
484 if (reader->entNr <= 0)
485 return (0);
486 reader->entNr--;
487 if (reader->entNr > 0)
488 reader->ent = reader->entTab[reader->entNr - 1];
489 else
490 reader->ent = NULL;
491 ret = reader->entTab[reader->entNr];
492 reader->entTab[reader->entNr] = 0;
493 return (ret);
494}
495
496/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000497 * xmlTextReaderStartElement:
498 * @ctx: the user data (XML parser context)
499 * @fullname: The element name, including namespace prefix
500 * @atts: An array of name/value attributes pairs, NULL terminated
501 *
502 * called when an opening tag has been processed.
503 */
504static void
505xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
506 const xmlChar **atts) {
507 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
508 xmlTextReaderPtr reader = ctxt->_private;
509
510#ifdef DEBUG_CALLBACKS
511 printf("xmlTextReaderStartElement(%s)\n", fullname);
512#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000513 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000514 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000515 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
516 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
517 (ctxt->input->cur[1] == '>'))
518 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000519 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000520 if (reader != NULL)
521 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000522}
523
524/**
525 * xmlTextReaderEndElement:
526 * @ctx: the user data (XML parser context)
527 * @fullname: The element name, including namespace prefix
528 *
529 * called when an ending tag has been processed.
530 */
531static void
532xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
533 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
534 xmlTextReaderPtr reader = ctxt->_private;
535
536#ifdef DEBUG_CALLBACKS
537 printf("xmlTextReaderEndElement(%s)\n", fullname);
538#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000539 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000540 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000541 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000542}
543
544/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000545 * xmlTextReaderStartElementNs:
546 * @ctx: the user data (XML parser context)
547 * @localname: the local name of the element
548 * @prefix: the element namespace prefix if available
549 * @URI: the element namespace name if available
550 * @nb_namespaces: number of namespace definitions on that node
551 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
552 * @nb_attributes: the number of attributes on that node
553 * nb_defaulted: the number of defaulted attributes.
554 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
555 * attribute values.
556 *
557 * called when an opening tag has been processed.
558 */
559static void
560xmlTextReaderStartElementNs(void *ctx,
561 const xmlChar *localname,
562 const xmlChar *prefix,
563 const xmlChar *URI,
564 int nb_namespaces,
565 const xmlChar **namespaces,
566 int nb_attributes,
567 int nb_defaulted,
568 const xmlChar **attributes)
569{
570 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
571 xmlTextReaderPtr reader = ctxt->_private;
572
573#ifdef DEBUG_CALLBACKS
574 printf("xmlTextReaderStartElementNs(%s)\n", fullname);
575#endif
576 if ((reader != NULL) && (reader->startElementNs != NULL)) {
577 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
578 namespaces, nb_attributes, nb_defaulted,
579 attributes);
580 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
581 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
582 (ctxt->input->cur[1] == '>'))
583 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
584 }
585 if (reader != NULL)
586 reader->state = XML_TEXTREADER_ELEMENT;
587}
588
589/**
590 * xmlTextReaderEndElementNs:
591 * @ctx: the user data (XML parser context)
592 * @localname: the local name of the element
593 * @prefix: the element namespace prefix if available
594 * @URI: the element namespace name if available
595 *
596 * called when an ending tag has been processed.
597 */
598static void
599xmlTextReaderEndElementNs(void *ctx,
600 const xmlChar * localname,
601 const xmlChar * prefix,
602 const xmlChar * URI)
603{
604 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
605 xmlTextReaderPtr reader = ctxt->_private;
606
607#ifdef DEBUG_CALLBACKS
608 printf("xmlTextReaderEndElementNs(%s)\n", fullname);
609#endif
610 if ((reader != NULL) && (reader->endElementNs != NULL)) {
611 reader->endElementNs(ctx, localname, prefix, URI);
612 }
613}
614
615
616/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000617 * xmlTextReaderCharacters:
618 * @ctx: the user data (XML parser context)
619 * @ch: a xmlChar string
620 * @len: the number of xmlChar
621 *
622 * receiving some chars from the parser.
623 */
624static void
625xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
626{
627 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
628 xmlTextReaderPtr reader = ctxt->_private;
629
630#ifdef DEBUG_CALLBACKS
631 printf("xmlTextReaderCharacters()\n");
632#endif
633 if ((reader != NULL) && (reader->characters != NULL)) {
634 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000635 }
636}
637
638/**
639 * xmlTextReaderCDataBlock:
640 * @ctx: the user data (XML parser context)
641 * @value: The pcdata content
642 * @len: the block length
643 *
644 * called when a pcdata block has been parsed
645 */
646static void
647xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
648{
649 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
650 xmlTextReaderPtr reader = ctxt->_private;
651
652#ifdef DEBUG_CALLBACKS
653 printf("xmlTextReaderCDataBlock()\n");
654#endif
655 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
656 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000657 }
658}
659
660/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000661 * xmlTextReaderPushData:
662 * @reader: the xmlTextReaderPtr used
663 *
664 * Push data down the progressive parser until a significant callback
665 * got raised.
666 *
667 * Returns -1 in case of failure, 0 otherwise
668 */
669static int
670xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000671 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000672 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000673 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000674
675 if ((reader->input == NULL) || (reader->input->buffer == NULL))
676 return(-1);
677
Daniel Veillardea7751d2002-12-20 00:16:24 +0000678 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000679 reader->state = XML_TEXTREADER_NONE;
680 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000681
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000682 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000683 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000684 /*
685 * Refill the buffer unless we are at the end of the stream
686 */
687 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
688 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000689 if ((val == 0) &&
690 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
691 if (inbuf->use == reader->cur) {
692 reader->mode = XML_TEXTREADER_MODE_EOF;
693 reader->state = oldstate;
694 if ((oldstate != XML_TEXTREADER_START) ||
695 (reader->ctxt->myDoc != NULL))
696 return(val);
697 }
698 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000699 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000700 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000701 if ((oldstate != XML_TEXTREADER_START) ||
702 (reader->ctxt->myDoc != NULL))
703 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000704 } else if (val == 0) {
705 /* mark the end of the stream and process the remains */
706 reader->mode = XML_TEXTREADER_MODE_EOF;
707 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000708 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000709
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000710 } else
711 break;
712 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000713 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000714 * parse by block of CHUNK_SIZE bytes, various tests show that
715 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000716 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000717 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000718 val = xmlParseChunk(reader->ctxt,
719 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000720 CHUNK_SIZE, 0);
721 reader->cur += CHUNK_SIZE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000722 if (val != 0)
723 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000724 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000725 s = inbuf->use - reader->cur;
726 val = xmlParseChunk(reader->ctxt,
727 (const char *) &inbuf->content[reader->cur],
728 s, 0);
729 reader->cur += s;
730 if (val != 0)
731 return(-1);
732 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000733 }
734 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000735
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000736 /*
737 * Discard the consumed input when needed and possible
738 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000739 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000740 if ((reader->cur >= 4096) &&
741 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000742 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000743 if (val >= 0) {
744 reader->cur -= val;
745 }
746 }
747 }
748
749 /*
750 * At the end of the stream signal that the work is done to the Push
751 * parser.
752 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000753 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000754 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000755 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000756 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000757 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000758 s, 1);
759 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000760 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000761 if (val != 0) return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000762 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000763 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000764 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000765 return(0);
766}
767
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000768#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000769/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000770 * xmlTextReaderValidatePush:
771 * @reader: the xmlTextReaderPtr used
772 *
773 * Push the current node for validation
774 */
775static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000776xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000777 xmlNodePtr node = reader->node;
778
Daniel Veillardf4e55762003-04-15 23:32:22 +0000779 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
780 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
781 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
782 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
783 reader->ctxt->myDoc, node, node->name);
784 } else {
785 /* TODO use the BuildQName interface */
786 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000787
Daniel Veillardf4e55762003-04-15 23:32:22 +0000788 qname = xmlStrdup(node->ns->prefix);
789 qname = xmlStrcat(qname, BAD_CAST ":");
790 qname = xmlStrcat(qname, node->name);
791 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
792 reader->ctxt->myDoc, node, qname);
793 if (qname != NULL)
794 xmlFree(qname);
795 }
796#ifdef LIBXML_SCHEMAS_ENABLED
797 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
798 (reader->rngValidCtxt != NULL)) {
799 int ret;
800
801 if (reader->rngFullNode != NULL) return;
802 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
803 reader->ctxt->myDoc,
804 node);
805 if (ret == 0) {
806 /*
807 * this element requires a full tree
808 */
809 node = xmlTextReaderExpand(reader);
810 if (node == NULL) {
811printf("Expand failed !\n");
812 ret = -1;
813 } else {
814 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
815 reader->ctxt->myDoc,
816 node);
817 reader->rngFullNode = node;
818 }
819 }
820 if (ret != 1)
821 reader->rngValidErrors++;
822#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000823 }
824}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000825
826/**
827 * xmlTextReaderValidateCData:
828 * @reader: the xmlTextReaderPtr used
829 * @data: pointer to the CData
830 * @len: lenght of the CData block in bytes.
831 *
832 * Push some CData for validation
833 */
834static void
835xmlTextReaderValidateCData(xmlTextReaderPtr reader,
836 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000837 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
838 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
839 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
840 data, len);
841#ifdef LIBXML_SCHEMAS_ENABLED
842 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
843 (reader->rngValidCtxt != NULL)) {
844 int ret;
845
846 if (reader->rngFullNode != NULL) return;
847 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
848 if (ret != 1)
849 reader->rngValidErrors++;
850#endif
851 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000852}
853
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000854/**
855 * xmlTextReaderValidatePop:
856 * @reader: the xmlTextReaderPtr used
857 *
858 * Pop the current node from validation
859 */
860static void
861xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
862 xmlNodePtr node = reader->node;
863
Daniel Veillardf4e55762003-04-15 23:32:22 +0000864 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
865 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
866 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
867 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
868 reader->ctxt->myDoc, node, node->name);
869 } else {
870 /* TODO use the BuildQName interface */
871 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000872
Daniel Veillardf4e55762003-04-15 23:32:22 +0000873 qname = xmlStrdup(node->ns->prefix);
874 qname = xmlStrcat(qname, BAD_CAST ":");
875 qname = xmlStrcat(qname, node->name);
876 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
877 reader->ctxt->myDoc, node, qname);
878 if (qname != NULL)
879 xmlFree(qname);
880 }
881#ifdef LIBXML_SCHEMAS_ENABLED
882 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
883 (reader->rngValidCtxt != NULL)) {
884 int ret;
885
886 if (reader->rngFullNode != NULL) {
887 if (node == reader->rngFullNode)
888 reader->rngFullNode = NULL;
889 return;
890 }
891 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
892 reader->ctxt->myDoc,
893 node);
894 if (ret != 1)
895 reader->rngValidErrors++;
896#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000897 }
898}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000899
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000900/**
901 * xmlTextReaderValidateEntity:
902 * @reader: the xmlTextReaderPtr used
903 *
904 * Handle the validation when an entity reference is encountered and
905 * entity substitution is not activated. As a result the parser interface
906 * must walk through the entity and do the validation calls
907 */
908static void
909xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
910 xmlNodePtr oldnode = reader->node;
911 xmlNodePtr node = reader->node;
912 xmlParserCtxtPtr ctxt = reader->ctxt;
913
914 do {
915 if (node->type == XML_ENTITY_REF_NODE) {
916 /*
917 * Case where the underlying tree is not availble, lookup the entity
918 * and walk it.
919 */
920 if ((node->children == NULL) && (ctxt->sax != NULL) &&
921 (ctxt->sax->getEntity != NULL)) {
922 node->children = (xmlNodePtr)
923 ctxt->sax->getEntity(ctxt, node->name);
924 }
925
926 if ((node->children != NULL) &&
927 (node->children->type == XML_ENTITY_DECL) &&
928 (node->children->children != NULL)) {
929 xmlTextReaderEntPush(reader, node);
930 node = node->children->children;
931 continue;
932 } else {
933 /*
934 * The error has probably be raised already.
935 */
936 if (node == oldnode)
937 break;
938 node = node->next;
939 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000940#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000941 } else if (node->type == XML_ELEMENT_NODE) {
942 reader->node = node;
943 xmlTextReaderValidatePush(reader);
944 } else if ((node->type == XML_TEXT_NODE) ||
945 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000946 xmlTextReaderValidateCData(reader, node->content,
947 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000948#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000949 }
950
951 /*
952 * go to next node
953 */
954 if (node->children != NULL) {
955 node = node->children;
956 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +0000957 } else if (node->type == XML_ELEMENT_NODE) {
958 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000959 }
960 if (node->next != NULL) {
961 node = node->next;
962 continue;
963 }
964 do {
965 node = node->parent;
966 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000967 xmlNodePtr tmp;
968 while ((tmp = node->last) != NULL) {
969 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
970 (tmp->_private != xmlTextReaderIsPreserved)) {
971 xmlUnlinkNode(tmp);
972 xmlTextReaderFreeNode(reader, tmp);
973 } else
974 break;
975 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000976 reader->node = node;
977 xmlTextReaderValidatePop(reader);
978 }
979 if ((node->type == XML_ENTITY_DECL) &&
980 (reader->ent != NULL) && (reader->ent->children == node)) {
981 node = xmlTextReaderEntPop(reader);
982 }
983 if (node == oldnode)
984 break;
985 if (node->next != NULL) {
986 node = node->next;
987 break;
988 }
989 } while ((node != NULL) && (node != oldnode));
990 } while ((node != NULL) && (node != oldnode));
991 reader->node = oldnode;
992}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000993#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000994
995
996/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +0000997 * xmlTextReaderGetSuccessor:
998 * @cur: the current node
999 *
1000 * Get the successor of a node if available.
1001 *
1002 * Returns the successor node or NULL
1003 */
1004static xmlNodePtr
1005xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1006 if (cur == NULL) return(NULL) ; /* ERROR */
1007 if (cur->next != NULL) return(cur->next) ;
1008 do {
1009 cur = cur->parent;
1010 if (cur == NULL) return(NULL);
1011 if (cur->next != NULL) return(cur->next);
1012 } while (cur != NULL);
1013 return(cur);
1014}
1015
1016/**
1017 * xmlTextReaderDoExpand:
1018 * @reader: the xmlTextReaderPtr used
1019 *
1020 * Makes sure that the current node is fully read as well as all its
1021 * descendant. It means the full DOM subtree must be available at the
1022 * end of the call.
1023 *
1024 * Returns 1 if the node was expanded successfully, 0 if there is no more
1025 * nodes to read, or -1 in case of error
1026 */
1027static int
1028xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1029 int val;
1030
1031 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1032 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001033 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001034 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1035
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001036 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1037 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001038 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001039 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001040 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1041 return(1);
1042 val = xmlTextReaderPushData(reader);
1043 if (val < 0)
1044 return(-1);
1045 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1046 return(1);
1047}
1048
1049/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001050 * xmlTextReaderRead:
1051 * @reader: the xmlTextReaderPtr used
1052 *
1053 * Moves the position of the current instance to the next node in
1054 * the stream, exposing its properties.
1055 *
1056 * Returns 1 if the node was read successfully, 0 if there is no more
1057 * nodes to read, or -1 in case of error
1058 */
1059int
1060xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001061 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001062 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001063 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001064
1065 if ((reader == NULL) || (reader->ctxt == NULL))
1066 return(-1);
1067 if (reader->ctxt->wellFormed != 1)
1068 return(-1);
1069
1070#ifdef DEBUG_READER
1071 fprintf(stderr, "\nREAD ");
1072 DUMP_READER
1073#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001074 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001075 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1076 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001077 /*
1078 * Initial state
1079 */
1080 do {
1081 val = xmlTextReaderPushData(reader);
1082 if (val < 0)
1083 return(-1);
1084 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001085 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1086 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001087 if (reader->ctxt->myDoc != NULL)
1088 reader->ctxt->myDoc->_private = reader;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001089 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001090 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001091 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001092 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001093 if (reader->node == NULL)
1094 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001095 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001096 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001097 if (reader->ctxt->myDoc != NULL) {
1098 reader->node = reader->ctxt->myDoc->children;
1099 }
1100 if (reader->node == NULL)
1101 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001102 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001103 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001104 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001105 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001106 }
1107 oldstate = reader->state;
1108 olddepth = reader->ctxt->nodeNr;
1109 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001110
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001111get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001112 /*
1113 * If we are not backtracking on ancestors or examined nodes,
1114 * that the parser didn't finished or that we arent at the end
1115 * of stream, continue processing.
1116 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001117 while ((reader->node->next == NULL) &&
1118 (reader->ctxt->nodeNr == olddepth) &&
1119 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001120 (reader->node->children == NULL) ||
1121 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001122 ((reader->node->children != NULL) &&
1123 (reader->node->children->type == XML_TEXT_NODE) &&
1124 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001125 (reader->node->type == XML_DTD_NODE) ||
1126 (reader->node->type == XML_DOCUMENT_NODE) ||
1127 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001128 ((reader->ctxt->node == NULL) ||
1129 (reader->ctxt->node == reader->node) ||
1130 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001131 (reader->ctxt->instate != XML_PARSER_EOF)) {
1132 val = xmlTextReaderPushData(reader);
1133 if (val < 0)
1134 return(-1);
1135 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001136 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001137 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001138 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001139 if ((reader->node->children != NULL) &&
1140 (reader->node->type != XML_ENTITY_REF_NODE) &&
1141 (reader->node->type != XML_DTD_NODE)) {
1142 reader->node = reader->node->children;
1143 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001144 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001145 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001146 }
1147 }
1148 if (reader->node->next != NULL) {
1149 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001150 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001151 (reader->node->children == NULL) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001152 (reader->node->_private != (void *)xmlTextReaderIsEmpty) &&
1153 (reader->node->_private != (void *)xmlTextReaderIsEmptyPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001154 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001155 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001156 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001157#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001158 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001159 (reader->node->type == XML_ELEMENT_NODE))
1160 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001161#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001162 reader->node = reader->node->next;
1163 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001164
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001165 /*
1166 * Cleanup of the old node
1167 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001168 if ((reader->node->prev != NULL) &&
1169 (reader->node->prev->type != XML_DTD_NODE)) {
1170 xmlNodePtr tmp = reader->node->prev;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001171 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
1172 (tmp->_private != xmlTextReaderIsPreserved)) {
1173 xmlUnlinkNode(tmp);
1174 xmlTextReaderFreeNode(reader, tmp);
1175 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001176 }
1177
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001178 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001179 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001180 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001181 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001182 (reader->node->children == NULL) &&
1183 (reader->node->_private != (void *)xmlTextReaderIsEmpty)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001184 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001185 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001186 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001187#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001188 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001189 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001190#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001191 reader->node = reader->node->parent;
1192 if ((reader->node == NULL) ||
1193 (reader->node->type == XML_DOCUMENT_NODE) ||
1194#ifdef LIBXML_DOCB_ENABLED
1195 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1196#endif
1197 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001198 if (reader->mode != XML_TEXTREADER_DONE) {
1199 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1200 reader->mode = XML_TEXTREADER_DONE;
1201 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001202 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001203 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001204
1205 /*
1206 * Cleanup of the old node
1207 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001208 if ((oldnode->type != XML_DTD_NODE) &&
1209 (oldnode->_private != xmlTextReaderIsEmptyPreserved) &&
1210 (oldnode->_private != xmlTextReaderIsPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001211 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001212 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001213 }
1214
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001215 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001216 }
1217 reader->depth--;
1218 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001219
1220node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001221 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001222
1223 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001224 * If we are in the middle of a piece of CDATA make sure it's finished
1225 */
1226 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001227 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001228 ((reader->node->type == XML_TEXT_NODE) ||
1229 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1230 xmlTextReaderExpand(reader);
1231 }
1232
1233 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001234 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001235 */
1236 if ((reader->node != NULL) &&
1237 (reader->node->type == XML_ENTITY_REF_NODE) &&
1238 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1239 /*
1240 * Case where the underlying tree is not availble, lookup the entity
1241 * and walk it.
1242 */
1243 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1244 (reader->ctxt->sax->getEntity != NULL)) {
1245 reader->node->children = (xmlNodePtr)
1246 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1247 }
1248
1249 if ((reader->node->children != NULL) &&
1250 (reader->node->children->type == XML_ENTITY_DECL) &&
1251 (reader->node->children->children != NULL)) {
1252 xmlTextReaderEntPush(reader, reader->node);
1253 reader->node = reader->node->children->children;
1254 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001255#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001256 } else if ((reader->node != NULL) &&
1257 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001258 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001259 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001260#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001261 }
1262 if ((reader->node != NULL) &&
1263 (reader->node->type == XML_ENTITY_DECL) &&
1264 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1265 reader->node = xmlTextReaderEntPop(reader);
1266 reader->depth++;
1267 goto get_next_node;
1268 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001269#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001270 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001271 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001272
1273 if ((node->type == XML_ELEMENT_NODE) &&
1274 ((reader->state != XML_TEXTREADER_END) &&
1275 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1276 xmlTextReaderValidatePush(reader);
1277 } else if ((node->type == XML_TEXT_NODE) ||
1278 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001279 xmlTextReaderValidateCData(reader, node->content,
1280 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001281 }
1282 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001283#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001284 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001285node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001286 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001287 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001288}
1289
Daniel Veillard67df8092002-12-16 22:04:11 +00001290/**
1291 * xmlTextReaderReadState:
1292 * @reader: the xmlTextReaderPtr used
1293 *
1294 * Gets the read state of the reader.
1295 *
1296 * Returns the state value, or -1 in case of error
1297 */
1298int
1299xmlTextReaderReadState(xmlTextReaderPtr reader) {
1300 if (reader == NULL)
1301 return(-1);
1302 return(reader->mode);
1303}
1304
1305/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001306 * xmlTextReaderExpand:
1307 * @reader: the xmlTextReaderPtr used
1308 *
1309 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001310 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001311 *
1312 * Returns a node pointer valid until the next xmlTextReaderRead() call
1313 * or NULL in case of error.
1314 */
1315xmlNodePtr
1316xmlTextReaderExpand(xmlTextReaderPtr reader) {
1317 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1318 return(NULL);
1319 if (xmlTextReaderDoExpand(reader) < 0)
1320 return(NULL);
1321 return(reader->node);
1322}
1323
1324/**
1325 * xmlTextReaderNext:
1326 * @reader: the xmlTextReaderPtr used
1327 *
1328 * Skip to the node following the current one in document order while
1329 * avoiding the subtree if any.
1330 *
1331 * Returns 1 if the node was read successfully, 0 if there is no more
1332 * nodes to read, or -1 in case of error
1333 */
1334int
1335xmlTextReaderNext(xmlTextReaderPtr reader) {
1336 int ret;
1337 xmlNodePtr cur;
1338
1339 if (reader == NULL)
1340 return(-1);
1341 cur = reader->node;
1342 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1343 return(xmlTextReaderRead(reader));
1344 if (reader->state == XML_TEXTREADER_END)
1345 return(xmlTextReaderRead(reader));
1346 if (cur->_private == (void *)xmlTextReaderIsEmpty)
1347 return(xmlTextReaderRead(reader));
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001348 if (cur->_private == (void *)xmlTextReaderIsEmptyPreserved)
1349 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001350 do {
1351 ret = xmlTextReaderRead(reader);
1352 if (ret != 1)
1353 return(ret);
1354 } while (reader->node != cur);
1355 return(xmlTextReaderRead(reader));
1356}
1357
1358/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001359 * xmlTextReaderReadInnerXml:
1360 * @reader: the xmlTextReaderPtr used
1361 *
1362 * Reads the contents of the current node, including child nodes and markup.
1363 *
1364 * Returns a string containing the XML content, or NULL if the current node
1365 * is neither an element nor attribute, or has no child nodes. The
1366 * string must be deallocated by the caller.
1367 */
1368xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001369xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001370 TODO
1371 return(NULL);
1372}
1373
1374/**
1375 * xmlTextReaderReadOuterXml:
1376 * @reader: the xmlTextReaderPtr used
1377 *
1378 * Reads the contents of the current node, including child nodes and markup.
1379 *
1380 * Returns a string containing the XML content, or NULL if the current node
1381 * is neither an element nor attribute, or has no child nodes. The
1382 * string must be deallocated by the caller.
1383 */
1384xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001385xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001386 TODO
1387 return(NULL);
1388}
1389
1390/**
1391 * xmlTextReaderReadString:
1392 * @reader: the xmlTextReaderPtr used
1393 *
1394 * Reads the contents of an element or a text node as a string.
1395 *
1396 * Returns a string containing the contents of the Element or Text node,
1397 * or NULL if the reader is positioned on any other type of node.
1398 * The string must be deallocated by the caller.
1399 */
1400xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001401xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001402 TODO
1403 return(NULL);
1404}
1405
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001406#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001407/**
1408 * xmlTextReaderReadBase64:
1409 * @reader: the xmlTextReaderPtr used
1410 * @array: a byte array to store the content.
1411 * @offset: the zero-based index into array where the method should
1412 * begin to write.
1413 * @len: the number of bytes to write.
1414 *
1415 * Reads and decodes the Base64 encoded contents of an element and
1416 * stores the result in a byte buffer.
1417 *
1418 * Returns the number of bytes written to array, or zero if the current
1419 * instance is not positioned on an element or -1 in case of error.
1420 */
1421int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001422xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1423 unsigned char *array ATTRIBUTE_UNUSED,
1424 int offset ATTRIBUTE_UNUSED,
1425 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001426 if ((reader == NULL) || (reader->ctxt == NULL))
1427 return(-1);
1428 if (reader->ctxt->wellFormed != 1)
1429 return(-1);
1430
1431 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1432 return(0);
1433 TODO
1434 return(0);
1435}
1436
1437/**
1438 * xmlTextReaderReadBinHex:
1439 * @reader: the xmlTextReaderPtr used
1440 * @array: a byte array to store the content.
1441 * @offset: the zero-based index into array where the method should
1442 * begin to write.
1443 * @len: the number of bytes to write.
1444 *
1445 * Reads and decodes the BinHex encoded contents of an element and
1446 * stores the result in a byte buffer.
1447 *
1448 * Returns the number of bytes written to array, or zero if the current
1449 * instance is not positioned on an element or -1 in case of error.
1450 */
1451int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001452xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1453 unsigned char *array ATTRIBUTE_UNUSED,
1454 int offset ATTRIBUTE_UNUSED,
1455 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001456 if ((reader == NULL) || (reader->ctxt == NULL))
1457 return(-1);
1458 if (reader->ctxt->wellFormed != 1)
1459 return(-1);
1460
1461 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1462 return(0);
1463 TODO
1464 return(0);
1465}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001466#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001467
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001468/************************************************************************
1469 * *
1470 * Constructor and destructors *
1471 * *
1472 ************************************************************************/
1473/**
1474 * xmlNewTextReader:
1475 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001476 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001477 *
1478 * Create an xmlTextReader structure fed with @input
1479 *
1480 * Returns the new xmlTextReaderPtr or NULL in case of error
1481 */
1482xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001483xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001484 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485
1486 if (input == NULL)
1487 return(NULL);
1488 ret = xmlMalloc(sizeof(xmlTextReader));
1489 if (ret == NULL) {
1490 xmlGenericError(xmlGenericErrorContext,
1491 "xmlNewTextReader : malloc failed\n");
1492 return(NULL);
1493 }
1494 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001495 ret->entTab = NULL;
1496 ret->entMax = 0;
1497 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001498 ret->input = input;
1499 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1500 if (ret->sax == NULL) {
1501 xmlFree(ret);
1502 xmlGenericError(xmlGenericErrorContext,
1503 "xmlNewTextReader : malloc failed\n");
1504 return(NULL);
1505 }
Daniel Veillard81273902003-09-30 00:43:48 +00001506 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001507 ret->startElement = ret->sax->startElement;
1508 ret->sax->startElement = xmlTextReaderStartElement;
1509 ret->endElement = ret->sax->endElement;
1510 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001511#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001512 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001513#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001514 ret->startElementNs = ret->sax->startElementNs;
1515 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1516 ret->endElementNs = ret->sax->endElementNs;
1517 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001518#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001519 } else {
1520 ret->startElementNs = NULL;
1521 ret->endElementNs = NULL;
1522 }
Daniel Veillard81273902003-09-30 00:43:48 +00001523#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001524 ret->characters = ret->sax->characters;
1525 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001526 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001527 ret->cdataBlock = ret->sax->cdataBlock;
1528 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001529
Daniel Veillard67df8092002-12-16 22:04:11 +00001530 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001531 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001532 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001533 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001534 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001535 }
1536 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001537 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001538 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001539 ret->base = 0;
1540 ret->cur = 4;
1541 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001542 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001543 ret->base = 0;
1544 ret->cur = 0;
1545 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001546 if (ret->ctxt == NULL) {
1547 xmlGenericError(xmlGenericErrorContext,
1548 "xmlNewTextReader : malloc failed\n");
1549 xmlFree(ret->sax);
1550 xmlFree(ret);
1551 return(NULL);
1552 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001553 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001554 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001555 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001556 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001557 /*
1558 * use the parser dictionnary to allocate all elements and attributes names
1559 */
1560 ret->ctxt->docdict = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001561 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001562}
1563
1564/**
1565 * xmlNewTextReaderFilename:
1566 * @URI: the URI of the resource to process
1567 *
1568 * Create an xmlTextReader structure fed with the resource at @URI
1569 *
1570 * Returns the new xmlTextReaderPtr or NULL in case of error
1571 */
1572xmlTextReaderPtr
1573xmlNewTextReaderFilename(const char *URI) {
1574 xmlParserInputBufferPtr input;
1575 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001576 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001577
1578 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1579 if (input == NULL)
1580 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001581 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001582 if (ret == NULL) {
1583 xmlFreeParserInputBuffer(input);
1584 return(NULL);
1585 }
1586 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001587 if (ret->ctxt->directory == NULL)
1588 directory = xmlParserGetDirectory(URI);
1589 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1590 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1591 if (directory != NULL)
1592 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001593 return(ret);
1594}
1595
1596/**
1597 * xmlFreeTextReader:
1598 * @reader: the xmlTextReaderPtr
1599 *
1600 * Deallocate all the resources associated to the reader
1601 */
1602void
1603xmlFreeTextReader(xmlTextReaderPtr reader) {
1604 if (reader == NULL)
1605 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001606#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001607 if (reader->rngSchemas != NULL) {
1608 xmlRelaxNGFree(reader->rngSchemas);
1609 reader->rngSchemas = NULL;
1610 }
1611 if (reader->rngValidCtxt != NULL) {
1612 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1613 reader->rngValidCtxt = NULL;
1614 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001615#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001616 if (reader->ctxt != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001617 if (reader->ctxt->myDoc != NULL) {
1618 if (reader->preserve == 0)
1619 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1620 reader->ctxt->myDoc = NULL;
1621 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001622 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1623 (reader->ctxt->vctxt.vstateMax > 0)){
1624 xmlFree(reader->ctxt->vctxt.vstateTab);
1625 reader->ctxt->vctxt.vstateTab = 0;
1626 reader->ctxt->vctxt.vstateMax = 0;
1627 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001628 if (reader->allocs & XML_TEXTREADER_CTXT)
1629 xmlFreeParserCtxt(reader->ctxt);
1630 }
1631 if (reader->sax != NULL)
1632 xmlFree(reader->sax);
1633 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1634 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001635 if (reader->faketext != NULL) {
1636 xmlFreeNode(reader->faketext);
1637 }
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001638 if (reader->entTab != NULL)
1639 xmlFree(reader->entTab);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001640 xmlFree(reader);
1641}
1642
1643/************************************************************************
1644 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001645 * Methods for XmlTextReader *
1646 * *
1647 ************************************************************************/
1648/**
1649 * xmlTextReaderClose:
1650 * @reader: the xmlTextReaderPtr used
1651 *
1652 * This method releases any resources allocated by the current instance
1653 * changes the state to Closed and close any underlying input.
1654 *
1655 * Returns 0 or -1 in case of error
1656 */
1657int
1658xmlTextReaderClose(xmlTextReaderPtr reader) {
1659 if (reader == NULL)
1660 return(-1);
1661 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001662 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001663 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1664 if (reader->ctxt != NULL) {
1665 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001666 if (reader->preserve == 0)
1667 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001668 reader->ctxt->myDoc = NULL;
1669 }
1670 if (reader->allocs & XML_TEXTREADER_CTXT) {
1671 xmlFreeParserCtxt(reader->ctxt);
1672 reader->allocs -= XML_TEXTREADER_CTXT;
1673 }
1674 }
1675 if (reader->sax != NULL) {
1676 xmlFree(reader->sax);
1677 reader->sax = NULL;
1678 }
1679 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1680 xmlFreeParserInputBuffer(reader->input);
1681 reader->allocs -= XML_TEXTREADER_INPUT;
1682 }
1683 return(0);
1684}
1685
1686/**
1687 * xmlTextReaderGetAttributeNo:
1688 * @reader: the xmlTextReaderPtr used
1689 * @no: the zero-based index of the attribute relative to the containing element
1690 *
1691 * Provides the value of the attribute with the specified index relative
1692 * to the containing element.
1693 *
1694 * Returns a string containing the value of the specified attribute, or NULL
1695 * in case of error. The string must be deallocated by the caller.
1696 */
1697xmlChar *
1698xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1699 xmlChar *ret;
1700 int i;
1701 xmlAttrPtr cur;
1702 xmlNsPtr ns;
1703
1704 if (reader == NULL)
1705 return(NULL);
1706 if (reader->node == NULL)
1707 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001708 if (reader->curnode != NULL)
1709 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001710 /* TODO: handle the xmlDecl */
1711 if (reader->node->type != XML_ELEMENT_NODE)
1712 return(NULL);
1713
1714 ns = reader->node->nsDef;
1715 for (i = 0;(i < no) && (ns != NULL);i++) {
1716 ns = ns->next;
1717 }
1718 if (ns != NULL)
1719 return(xmlStrdup(ns->href));
1720
1721 cur = reader->node->properties;
1722 if (cur == NULL)
1723 return(NULL);
1724 for (;i < no;i++) {
1725 cur = cur->next;
1726 if (cur == NULL)
1727 return(NULL);
1728 }
1729 /* TODO walk the DTD if present */
1730
1731 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1732 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1733 return(ret);
1734}
1735
1736/**
1737 * xmlTextReaderGetAttribute:
1738 * @reader: the xmlTextReaderPtr used
1739 * @name: the qualified name of the attribute.
1740 *
1741 * Provides the value of the attribute with the specified qualified name.
1742 *
1743 * Returns a string containing the value of the specified attribute, or NULL
1744 * in case of error. The string must be deallocated by the caller.
1745 */
1746xmlChar *
1747xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1748 xmlChar *prefix = NULL;
1749 xmlChar *localname;
1750 xmlNsPtr ns;
1751 xmlChar *ret = NULL;
1752
1753 if ((reader == NULL) || (name == NULL))
1754 return(NULL);
1755 if (reader->node == NULL)
1756 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001757 if (reader->curnode != NULL)
1758 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001759
1760 /* TODO: handle the xmlDecl */
1761 if (reader->node->type != XML_ELEMENT_NODE)
1762 return(NULL);
1763
1764 localname = xmlSplitQName2(name, &prefix);
1765 if (localname == NULL)
1766 return(xmlGetProp(reader->node, name));
1767
1768 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1769 if (ns != NULL)
1770 ret = xmlGetNsProp(reader->node, localname, ns->href);
1771
1772 if (localname != NULL)
1773 xmlFree(localname);
1774 if (prefix != NULL)
1775 xmlFree(prefix);
1776 return(ret);
1777}
1778
1779
1780/**
1781 * xmlTextReaderGetAttributeNs:
1782 * @reader: the xmlTextReaderPtr used
1783 * @localName: the local name of the attribute.
1784 * @namespaceURI: the namespace URI of the attribute.
1785 *
1786 * Provides the value of the specified attribute
1787 *
1788 * Returns a string containing the value of the specified attribute, or NULL
1789 * in case of error. The string must be deallocated by the caller.
1790 */
1791xmlChar *
1792xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
1793 const xmlChar *namespaceURI) {
1794 if ((reader == NULL) || (localName == NULL))
1795 return(NULL);
1796 if (reader->node == NULL)
1797 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001798 if (reader->curnode != NULL)
1799 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001800
1801 /* TODO: handle the xmlDecl */
1802 if (reader->node->type != XML_ELEMENT_NODE)
1803 return(NULL);
1804
1805 return(xmlGetNsProp(reader->node, localName, namespaceURI));
1806}
1807
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001808/**
1809 * xmlTextReaderGetRemainder:
1810 * @reader: the xmlTextReaderPtr used
1811 *
1812 * Method to get the remainder of the buffered XML. this method stops the
1813 * parser, set its state to End Of File and return the input stream with
1814 * what is left that the parser did not use.
1815 *
1816 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
1817 * in case of error.
1818 */
1819xmlParserInputBufferPtr
1820xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
1821 xmlParserInputBufferPtr ret = NULL;
1822
1823 if (reader == NULL)
1824 return(NULL);
1825 if (reader->node == NULL)
1826 return(NULL);
1827
1828 reader->node = NULL;
1829 reader->curnode = NULL;
1830 reader->mode = XML_TEXTREADER_MODE_EOF;
1831 if (reader->ctxt != NULL) {
1832 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001833 if (reader->preserve == 0)
1834 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001835 reader->ctxt->myDoc = NULL;
1836 }
1837 if (reader->allocs & XML_TEXTREADER_CTXT) {
1838 xmlFreeParserCtxt(reader->ctxt);
1839 reader->allocs -= XML_TEXTREADER_CTXT;
1840 }
1841 }
1842 if (reader->sax != NULL) {
1843 xmlFree(reader->sax);
1844 reader->sax = NULL;
1845 }
1846 if (reader->allocs & XML_TEXTREADER_INPUT) {
1847 ret = reader->input;
1848 reader->allocs -= XML_TEXTREADER_INPUT;
1849 } else {
1850 /*
1851 * Hum, one may need to duplicate the data structure because
1852 * without reference counting the input may be freed twice:
1853 * - by the layer which allocated it.
1854 * - by the layer to which would have been returned to.
1855 */
1856 TODO
1857 return(NULL);
1858 }
1859 return(ret);
1860}
1861
1862/**
1863 * xmlTextReaderLookupNamespace:
1864 * @reader: the xmlTextReaderPtr used
1865 * @prefix: the prefix whose namespace URI is to be resolved. To return
1866 * the default namespace, specify NULL
1867 *
1868 * Resolves a namespace prefix in the scope of the current element.
1869 *
1870 * Returns a string containing the namespace URI to which the prefix maps
1871 * or NULL in case of error. The string must be deallocated by the caller.
1872 */
1873xmlChar *
1874xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
1875 xmlNsPtr ns;
1876
1877 if (reader == NULL)
1878 return(NULL);
1879 if (reader->node == NULL)
1880 return(NULL);
1881
1882 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1883 if (ns == NULL)
1884 return(NULL);
1885 return(xmlStrdup(ns->href));
1886}
1887
1888/**
1889 * xmlTextReaderMoveToAttributeNo:
1890 * @reader: the xmlTextReaderPtr used
1891 * @no: the zero-based index of the attribute relative to the containing
1892 * element.
1893 *
1894 * Moves the position of the current instance to the attribute with
1895 * the specified index relative to the containing element.
1896 *
1897 * Returns 1 in case of success, -1 in case of error, 0 if not found
1898 */
1899int
1900xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
1901 int i;
1902 xmlAttrPtr cur;
1903 xmlNsPtr ns;
1904
1905 if (reader == NULL)
1906 return(-1);
1907 if (reader->node == NULL)
1908 return(-1);
1909 /* TODO: handle the xmlDecl */
1910 if (reader->node->type != XML_ELEMENT_NODE)
1911 return(-1);
1912
1913 reader->curnode = NULL;
1914
1915 ns = reader->node->nsDef;
1916 for (i = 0;(i < no) && (ns != NULL);i++) {
1917 ns = ns->next;
1918 }
1919 if (ns != NULL) {
1920 reader->curnode = (xmlNodePtr) ns;
1921 return(1);
1922 }
1923
1924 cur = reader->node->properties;
1925 if (cur == NULL)
1926 return(0);
1927 for (;i < no;i++) {
1928 cur = cur->next;
1929 if (cur == NULL)
1930 return(0);
1931 }
1932 /* TODO walk the DTD if present */
1933
1934 reader->curnode = (xmlNodePtr) cur;
1935 return(1);
1936}
1937
1938/**
1939 * xmlTextReaderMoveToAttribute:
1940 * @reader: the xmlTextReaderPtr used
1941 * @name: the qualified name of the attribute.
1942 *
1943 * Moves the position of the current instance to the attribute with
1944 * the specified qualified name.
1945 *
1946 * Returns 1 in case of success, -1 in case of error, 0 if not found
1947 */
1948int
1949xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1950 xmlChar *prefix = NULL;
1951 xmlChar *localname;
1952 xmlNsPtr ns;
1953 xmlAttrPtr prop;
1954
1955 if ((reader == NULL) || (name == NULL))
1956 return(-1);
1957 if (reader->node == NULL)
1958 return(-1);
1959
1960 /* TODO: handle the xmlDecl */
1961 if (reader->node->type != XML_ELEMENT_NODE)
1962 return(0);
1963
1964 localname = xmlSplitQName2(name, &prefix);
1965 if (localname == NULL) {
1966 /*
1967 * Namespace default decl
1968 */
1969 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
1970 ns = reader->node->nsDef;
1971 while (ns != NULL) {
1972 if (ns->prefix == NULL) {
1973 reader->curnode = (xmlNodePtr) ns;
1974 return(1);
1975 }
1976 ns = ns->next;
1977 }
1978 return(0);
1979 }
1980
1981 prop = reader->node->properties;
1982 while (prop != NULL) {
1983 /*
1984 * One need to have
1985 * - same attribute names
1986 * - and the attribute carrying that namespace
1987 */
1988 if ((xmlStrEqual(prop->name, name)) &&
1989 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
1990 reader->curnode = (xmlNodePtr) prop;
1991 return(1);
1992 }
1993 prop = prop->next;
1994 }
1995 return(0);
1996 }
1997
1998 /*
1999 * Namespace default decl
2000 */
2001 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2002 ns = reader->node->nsDef;
2003 while (ns != NULL) {
2004 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2005 reader->curnode = (xmlNodePtr) ns;
2006 goto found;
2007 }
2008 ns = ns->next;
2009 }
2010 goto not_found;
2011 }
2012 prop = reader->node->properties;
2013 while (prop != NULL) {
2014 /*
2015 * One need to have
2016 * - same attribute names
2017 * - and the attribute carrying that namespace
2018 */
2019 if ((xmlStrEqual(prop->name, localname)) &&
2020 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2021 reader->curnode = (xmlNodePtr) prop;
2022 goto found;
2023 }
2024 prop = prop->next;
2025 }
2026not_found:
2027 if (localname != NULL)
2028 xmlFree(localname);
2029 if (prefix != NULL)
2030 xmlFree(prefix);
2031 return(0);
2032
2033found:
2034 if (localname != NULL)
2035 xmlFree(localname);
2036 if (prefix != NULL)
2037 xmlFree(prefix);
2038 return(1);
2039}
2040
2041/**
2042 * xmlTextReaderMoveToAttributeNs:
2043 * @reader: the xmlTextReaderPtr used
2044 * @localName: the local name of the attribute.
2045 * @namespaceURI: the namespace URI of the attribute.
2046 *
2047 * Moves the position of the current instance to the attribute with the
2048 * specified local name and namespace URI.
2049 *
2050 * Returns 1 in case of success, -1 in case of error, 0 if not found
2051 */
2052int
2053xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2054 const xmlChar *localName, const xmlChar *namespaceURI) {
2055 xmlAttrPtr prop;
2056 xmlNodePtr node;
2057
2058 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2059 return(-1);
2060 if (reader->node == NULL)
2061 return(-1);
2062 if (reader->node->type != XML_ELEMENT_NODE)
2063 return(0);
2064 node = reader->node;
2065
2066 /*
2067 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2068 * namespace name associated to "xmlns"
2069 */
2070 prop = node->properties;
2071 while (prop != NULL) {
2072 /*
2073 * One need to have
2074 * - same attribute names
2075 * - and the attribute carrying that namespace
2076 */
2077 if (xmlStrEqual(prop->name, localName) &&
2078 ((prop->ns != NULL) &&
2079 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2080 reader->curnode = (xmlNodePtr) prop;
2081 return(1);
2082 }
2083 prop = prop->next;
2084 }
2085 return(0);
2086}
2087
2088/**
2089 * xmlTextReaderMoveToFirstAttribute:
2090 * @reader: the xmlTextReaderPtr used
2091 *
2092 * Moves the position of the current instance to the first attribute
2093 * associated with the current node.
2094 *
2095 * Returns 1 in case of success, -1 in case of error, 0 if not found
2096 */
2097int
2098xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2099 if (reader == NULL)
2100 return(-1);
2101 if (reader->node == NULL)
2102 return(-1);
2103 if (reader->node->type != XML_ELEMENT_NODE)
2104 return(0);
2105
2106 if (reader->node->nsDef != NULL) {
2107 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2108 return(1);
2109 }
2110 if (reader->node->properties != NULL) {
2111 reader->curnode = (xmlNodePtr) reader->node->properties;
2112 return(1);
2113 }
2114 return(0);
2115}
2116
2117/**
2118 * xmlTextReaderMoveToNextAttribute:
2119 * @reader: the xmlTextReaderPtr used
2120 *
2121 * Moves the position of the current instance to the next attribute
2122 * associated with the current node.
2123 *
2124 * Returns 1 in case of success, -1 in case of error, 0 if not found
2125 */
2126int
2127xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2128 if (reader == NULL)
2129 return(-1);
2130 if (reader->node == NULL)
2131 return(-1);
2132 if (reader->node->type != XML_ELEMENT_NODE)
2133 return(0);
2134 if (reader->curnode == NULL)
2135 return(xmlTextReaderMoveToFirstAttribute(reader));
2136
2137 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2138 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2139 if (ns->next != NULL) {
2140 reader->curnode = (xmlNodePtr) ns->next;
2141 return(1);
2142 }
2143 if (reader->node->properties != NULL) {
2144 reader->curnode = (xmlNodePtr) reader->node->properties;
2145 return(1);
2146 }
2147 return(0);
2148 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2149 (reader->curnode->next != NULL)) {
2150 reader->curnode = reader->curnode->next;
2151 return(1);
2152 }
2153 return(0);
2154}
2155
2156/**
2157 * xmlTextReaderMoveToElement:
2158 * @reader: the xmlTextReaderPtr used
2159 *
2160 * Moves the position of the current instance to the node that
2161 * contains the current Attribute node.
2162 *
2163 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2164 */
2165int
2166xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2167 if (reader == NULL)
2168 return(-1);
2169 if (reader->node == NULL)
2170 return(-1);
2171 if (reader->node->type != XML_ELEMENT_NODE)
2172 return(0);
2173 if (reader->curnode != NULL) {
2174 reader->curnode = NULL;
2175 return(1);
2176 }
2177 return(0);
2178}
2179
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002180/**
2181 * xmlTextReaderReadAttributeValue:
2182 * @reader: the xmlTextReaderPtr used
2183 *
2184 * Parses an attribute value into one or more Text and EntityReference nodes.
2185 *
2186 * Returns 1 in case of success, 0 if the reader was not positionned on an
2187 * ttribute node or all the attribute values have been read, or -1
2188 * in case of error.
2189 */
2190int
2191xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2192 if (reader == NULL)
2193 return(-1);
2194 if (reader->node == NULL)
2195 return(-1);
2196 if (reader->curnode == NULL)
2197 return(0);
2198 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2199 if (reader->curnode->children == NULL)
2200 return(0);
2201 reader->curnode = reader->curnode->children;
2202 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2203 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2204
2205 if (reader->faketext == NULL) {
2206 reader->faketext = xmlNewDocText(reader->node->doc,
2207 ns->href);
2208 } else {
2209 if (reader->faketext->content != NULL)
2210 xmlFree(reader->faketext->content);
2211 reader->faketext->content = xmlStrdup(ns->href);
2212 }
2213 reader->curnode = reader->faketext;
2214 } else {
2215 if (reader->curnode->next == NULL)
2216 return(0);
2217 reader->curnode = reader->curnode->next;
2218 }
2219 return(1);
2220}
2221
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002222/************************************************************************
2223 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002224 * Acces API to the current node *
2225 * *
2226 ************************************************************************/
2227/**
2228 * xmlTextReaderAttributeCount:
2229 * @reader: the xmlTextReaderPtr used
2230 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002231 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002232 *
2233 * Returns 0 i no attributes, -1 in case of error or the attribute count
2234 */
2235int
2236xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2237 int ret;
2238 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002239 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002240 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002241
2242 if (reader == NULL)
2243 return(-1);
2244 if (reader->node == NULL)
2245 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002246
2247 if (reader->curnode != NULL)
2248 node = reader->curnode;
2249 else
2250 node = reader->node;
2251
2252 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002253 return(0);
2254 if ((reader->state == XML_TEXTREADER_END) ||
2255 (reader->state == XML_TEXTREADER_BACKTRACK))
2256 return(0);
2257 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002258 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002259 while (attr != NULL) {
2260 ret++;
2261 attr = attr->next;
2262 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002263 ns = node->nsDef;
2264 while (ns != NULL) {
2265 ret++;
2266 ns = ns->next;
2267 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002268 return(ret);
2269}
2270
2271/**
2272 * xmlTextReaderNodeType:
2273 * @reader: the xmlTextReaderPtr used
2274 *
2275 * Get the node type of the current node
2276 * Reference:
2277 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2278 *
2279 * Returns the xmlNodeType of the current node or -1 in case of error
2280 */
2281int
2282xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002283 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002284
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002285 if (reader == NULL)
2286 return(-1);
2287 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002288 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002289 if (reader->curnode != NULL)
2290 node = reader->curnode;
2291 else
2292 node = reader->node;
2293 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002294 case XML_ELEMENT_NODE:
2295 if ((reader->state == XML_TEXTREADER_END) ||
2296 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002297 return(XML_READER_TYPE_END_ELEMENT);
2298 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002299 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002300 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002301 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002302 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002303 if (xmlIsBlankNode(reader->node)) {
2304 if (xmlNodeGetSpacePreserve(reader->node))
2305 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2306 else
2307 return(XML_READER_TYPE_WHITESPACE);
2308 } else {
2309 return(XML_READER_TYPE_TEXT);
2310 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002311 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002312 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002313 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002314 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002315 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002316 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002317 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002318 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002319 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002320 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002321 case XML_DOCUMENT_NODE:
2322 case XML_HTML_DOCUMENT_NODE:
2323#ifdef LIBXML_DOCB_ENABLED
2324 case XML_DOCB_DOCUMENT_NODE:
2325#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002326 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002327 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002328 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002329 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002330 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002331 case XML_DOCUMENT_TYPE_NODE:
2332 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002333 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002334
2335 case XML_ELEMENT_DECL:
2336 case XML_ATTRIBUTE_DECL:
2337 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002338 case XML_XINCLUDE_START:
2339 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002340 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002341 }
2342 return(-1);
2343}
2344
2345/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002346 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002347 * @reader: the xmlTextReaderPtr used
2348 *
2349 * Check if the current node is empty
2350 *
2351 * Returns 1 if empty, 0 if not and -1 in case of error
2352 */
2353int
2354xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2355 if ((reader == NULL) || (reader->node == NULL))
2356 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002357 if (reader->node->type != XML_ELEMENT_NODE)
2358 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002359 if (reader->curnode != NULL)
2360 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002361 if (reader->node->children != NULL)
2362 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002363 if (reader->state == XML_TEXTREADER_END)
2364 return(0);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002365 return((reader->node->_private == (void *)xmlTextReaderIsEmpty) ||
2366 (reader->node->_private == (void *)xmlTextReaderIsEmptyPreserved));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002367}
2368
2369/**
2370 * xmlTextReaderLocalName:
2371 * @reader: the xmlTextReaderPtr used
2372 *
2373 * The local name of the node.
2374 *
2375 * Returns the local name or NULL if not available
2376 */
2377xmlChar *
2378xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002379 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002380 if ((reader == NULL) || (reader->node == NULL))
2381 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002382 if (reader->curnode != NULL)
2383 node = reader->curnode;
2384 else
2385 node = reader->node;
2386 if (node->type == XML_NAMESPACE_DECL) {
2387 xmlNsPtr ns = (xmlNsPtr) node;
2388 if (ns->prefix == NULL)
2389 return(xmlStrdup(BAD_CAST "xmlns"));
2390 else
2391 return(xmlStrdup(ns->prefix));
2392 }
2393 if ((node->type != XML_ELEMENT_NODE) &&
2394 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002395 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002396 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002397}
2398
2399/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002400 * xmlTextReaderConstLocalName:
2401 * @reader: the xmlTextReaderPtr used
2402 *
2403 * The local name of the node.
2404 *
2405 * Returns the local name or NULL if not available, the
2406 * string will be deallocated with the reader.
2407 */
2408const xmlChar *
2409xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2410 xmlNodePtr node;
2411 if ((reader == NULL) || (reader->node == NULL))
2412 return(NULL);
2413 if (reader->curnode != NULL)
2414 node = reader->curnode;
2415 else
2416 node = reader->node;
2417 if (node->type == XML_NAMESPACE_DECL) {
2418 xmlNsPtr ns = (xmlNsPtr) node;
2419 if (ns->prefix == NULL)
2420 return(CONSTSTR(BAD_CAST "xmlns"));
2421 else
2422 return(ns->prefix);
2423 }
2424 if ((node->type != XML_ELEMENT_NODE) &&
2425 (node->type != XML_ATTRIBUTE_NODE))
2426 return(xmlTextReaderConstName(reader));
2427 return(node->name);
2428}
2429
2430/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002431 * xmlTextReaderName:
2432 * @reader: the xmlTextReaderPtr used
2433 *
2434 * The qualified name of the node, equal to Prefix :LocalName.
2435 *
2436 * Returns the local name or NULL if not available
2437 */
2438xmlChar *
2439xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002440 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002441 xmlChar *ret;
2442
2443 if ((reader == NULL) || (reader->node == NULL))
2444 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002445 if (reader->curnode != NULL)
2446 node = reader->curnode;
2447 else
2448 node = reader->node;
2449 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002450 case XML_ELEMENT_NODE:
2451 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002452 if ((node->ns == NULL) ||
2453 (node->ns->prefix == NULL))
2454 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002455
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002456 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002457 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002458 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002459 return(ret);
2460 case XML_TEXT_NODE:
2461 return(xmlStrdup(BAD_CAST "#text"));
2462 case XML_CDATA_SECTION_NODE:
2463 return(xmlStrdup(BAD_CAST "#cdata-section"));
2464 case XML_ENTITY_NODE:
2465 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002466 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002467 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002468 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002469 case XML_COMMENT_NODE:
2470 return(xmlStrdup(BAD_CAST "#comment"));
2471 case XML_DOCUMENT_NODE:
2472 case XML_HTML_DOCUMENT_NODE:
2473#ifdef LIBXML_DOCB_ENABLED
2474 case XML_DOCB_DOCUMENT_NODE:
2475#endif
2476 return(xmlStrdup(BAD_CAST "#document"));
2477 case XML_DOCUMENT_FRAG_NODE:
2478 return(xmlStrdup(BAD_CAST "#document-fragment"));
2479 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002480 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002481 case XML_DOCUMENT_TYPE_NODE:
2482 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002483 return(xmlStrdup(node->name));
2484 case XML_NAMESPACE_DECL: {
2485 xmlNsPtr ns = (xmlNsPtr) node;
2486
2487 ret = xmlStrdup(BAD_CAST "xmlns");
2488 if (ns->prefix == NULL)
2489 return(ret);
2490 ret = xmlStrcat(ret, BAD_CAST ":");
2491 ret = xmlStrcat(ret, ns->prefix);
2492 return(ret);
2493 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002494
2495 case XML_ELEMENT_DECL:
2496 case XML_ATTRIBUTE_DECL:
2497 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002498 case XML_XINCLUDE_START:
2499 case XML_XINCLUDE_END:
2500 return(NULL);
2501 }
2502 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002503}
2504
2505/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002506 * xmlTextReaderConstName:
2507 * @reader: the xmlTextReaderPtr used
2508 *
2509 * The qualified name of the node, equal to Prefix :LocalName.
2510 *
2511 * Returns the local name or NULL if not available, the string is
2512 * deallocated with the reader.
2513 */
2514const xmlChar *
2515xmlTextReaderConstName(xmlTextReaderPtr reader) {
2516 xmlNodePtr node;
2517
2518 if ((reader == NULL) || (reader->node == NULL))
2519 return(NULL);
2520 if (reader->curnode != NULL)
2521 node = reader->curnode;
2522 else
2523 node = reader->node;
2524 switch (node->type) {
2525 case XML_ELEMENT_NODE:
2526 case XML_ATTRIBUTE_NODE:
2527 if ((node->ns == NULL) ||
2528 (node->ns->prefix == NULL))
2529 return(node->name);
2530 return(CONSTQSTR(node->ns->prefix, node->name));
2531 case XML_TEXT_NODE:
2532 return(CONSTSTR(BAD_CAST "#text"));
2533 case XML_CDATA_SECTION_NODE:
2534 return(CONSTSTR(BAD_CAST "#cdata-section"));
2535 case XML_ENTITY_NODE:
2536 case XML_ENTITY_REF_NODE:
2537 return(CONSTSTR(node->name));
2538 case XML_PI_NODE:
2539 return(CONSTSTR(node->name));
2540 case XML_COMMENT_NODE:
2541 return(CONSTSTR(BAD_CAST "#comment"));
2542 case XML_DOCUMENT_NODE:
2543 case XML_HTML_DOCUMENT_NODE:
2544#ifdef LIBXML_DOCB_ENABLED
2545 case XML_DOCB_DOCUMENT_NODE:
2546#endif
2547 return(CONSTSTR(BAD_CAST "#document"));
2548 case XML_DOCUMENT_FRAG_NODE:
2549 return(CONSTSTR(BAD_CAST "#document-fragment"));
2550 case XML_NOTATION_NODE:
2551 return(CONSTSTR(node->name));
2552 case XML_DOCUMENT_TYPE_NODE:
2553 case XML_DTD_NODE:
2554 return(CONSTSTR(node->name));
2555 case XML_NAMESPACE_DECL: {
2556 xmlNsPtr ns = (xmlNsPtr) node;
2557
2558 if (ns->prefix == NULL)
2559 return(CONSTSTR(BAD_CAST "xmlns"));
2560 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2561 }
2562
2563 case XML_ELEMENT_DECL:
2564 case XML_ATTRIBUTE_DECL:
2565 case XML_ENTITY_DECL:
2566 case XML_XINCLUDE_START:
2567 case XML_XINCLUDE_END:
2568 return(NULL);
2569 }
2570 return(NULL);
2571}
2572
2573/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002574 * xmlTextReaderPrefix:
2575 * @reader: the xmlTextReaderPtr used
2576 *
2577 * A shorthand reference to the namespace associated with the node.
2578 *
2579 * Returns the prefix or NULL if not available
2580 */
2581xmlChar *
2582xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002583 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002584 if ((reader == NULL) || (reader->node == NULL))
2585 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002586 if (reader->curnode != NULL)
2587 node = reader->curnode;
2588 else
2589 node = reader->node;
2590 if (node->type == XML_NAMESPACE_DECL) {
2591 xmlNsPtr ns = (xmlNsPtr) node;
2592 if (ns->prefix == NULL)
2593 return(NULL);
2594 return(xmlStrdup(BAD_CAST "xmlns"));
2595 }
2596 if ((node->type != XML_ELEMENT_NODE) &&
2597 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002598 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002599 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002600 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002601 return(NULL);
2602}
2603
2604/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002605 * xmlTextReaderConstPrefix:
2606 * @reader: the xmlTextReaderPtr used
2607 *
2608 * A shorthand reference to the namespace associated with the node.
2609 *
2610 * Returns the prefix or NULL if not available, the string is deallocated
2611 * with the reader.
2612 */
2613const xmlChar *
2614xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2615 xmlNodePtr node;
2616 if ((reader == NULL) || (reader->node == NULL))
2617 return(NULL);
2618 if (reader->curnode != NULL)
2619 node = reader->curnode;
2620 else
2621 node = reader->node;
2622 if (node->type == XML_NAMESPACE_DECL) {
2623 xmlNsPtr ns = (xmlNsPtr) node;
2624 if (ns->prefix == NULL)
2625 return(NULL);
2626 return(CONSTSTR(BAD_CAST "xmlns"));
2627 }
2628 if ((node->type != XML_ELEMENT_NODE) &&
2629 (node->type != XML_ATTRIBUTE_NODE))
2630 return(NULL);
2631 if ((node->ns != NULL) && (node->ns->prefix != NULL))
2632 return(CONSTSTR(node->ns->prefix));
2633 return(NULL);
2634}
2635
2636/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002637 * xmlTextReaderNamespaceUri:
2638 * @reader: the xmlTextReaderPtr used
2639 *
2640 * The URI defining the namespace associated with the node.
2641 *
2642 * Returns the namespace URI or NULL if not available
2643 */
2644xmlChar *
2645xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002646 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002647 if ((reader == NULL) || (reader->node == NULL))
2648 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002649 if (reader->curnode != NULL)
2650 node = reader->curnode;
2651 else
2652 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00002653 if (node->type == XML_NAMESPACE_DECL)
2654 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002655 if ((node->type != XML_ELEMENT_NODE) &&
2656 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002657 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002658 if (node->ns != NULL)
2659 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002660 return(NULL);
2661}
2662
2663/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002664 * xmlTextReaderConstNamespaceUri:
2665 * @reader: the xmlTextReaderPtr used
2666 *
2667 * The URI defining the namespace associated with the node.
2668 *
2669 * Returns the namespace URI or NULL if not available, the string
2670 * will be deallocated with the reader
2671 */
2672const xmlChar *
2673xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
2674 xmlNodePtr node;
2675 if ((reader == NULL) || (reader->node == NULL))
2676 return(NULL);
2677 if (reader->curnode != NULL)
2678 node = reader->curnode;
2679 else
2680 node = reader->node;
2681 if (node->type == XML_NAMESPACE_DECL)
2682 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
2683 if ((node->type != XML_ELEMENT_NODE) &&
2684 (node->type != XML_ATTRIBUTE_NODE))
2685 return(NULL);
2686 if (node->ns != NULL)
2687 return(CONSTSTR(node->ns->href));
2688 return(NULL);
2689}
2690
2691/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002692 * xmlTextReaderBaseUri:
2693 * @reader: the xmlTextReaderPtr used
2694 *
2695 * The base URI of the node.
2696 *
2697 * Returns the base URI or NULL if not available
2698 */
2699xmlChar *
2700xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
2701 if ((reader == NULL) || (reader->node == NULL))
2702 return(NULL);
2703 return(xmlNodeGetBase(NULL, reader->node));
2704}
2705
2706/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002707 * xmlTextReaderConstBaseUri:
2708 * @reader: the xmlTextReaderPtr used
2709 *
2710 * The base URI of the node.
2711 *
2712 * Returns the base URI or NULL if not available, the string
2713 * will be deallocated with the reader
2714 */
2715const xmlChar *
2716xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
2717 xmlChar *tmp;
2718 const xmlChar *ret;
2719
2720 if ((reader == NULL) || (reader->node == NULL))
2721 return(NULL);
2722 tmp = xmlNodeGetBase(NULL, reader->node);
2723 if (tmp == NULL)
2724 return(NULL);
2725 ret = CONSTSTR(tmp);
2726 xmlFree(tmp);
2727 return(ret);
2728}
2729
2730/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002731 * xmlTextReaderDepth:
2732 * @reader: the xmlTextReaderPtr used
2733 *
2734 * The depth of the node in the tree.
2735 *
2736 * Returns the depth or -1 in case of error
2737 */
2738int
2739xmlTextReaderDepth(xmlTextReaderPtr reader) {
2740 if (reader == NULL)
2741 return(-1);
2742 if (reader->node == NULL)
2743 return(0);
2744
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002745 if (reader->curnode != NULL) {
2746 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
2747 (reader->curnode->type == XML_NAMESPACE_DECL))
2748 return(reader->depth + 1);
2749 return(reader->depth + 2);
2750 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002751 return(reader->depth);
2752}
2753
2754/**
2755 * xmlTextReaderHasAttributes:
2756 * @reader: the xmlTextReaderPtr used
2757 *
2758 * Whether the node has attributes.
2759 *
2760 * Returns 1 if true, 0 if false, and -1 in case or error
2761 */
2762int
2763xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002764 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002765 if (reader == NULL)
2766 return(-1);
2767 if (reader->node == NULL)
2768 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002769 if (reader->curnode != NULL)
2770 node = reader->curnode;
2771 else
2772 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002773
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002774 if ((node->type == XML_ELEMENT_NODE) &&
2775 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002776 return(1);
2777 /* TODO: handle the xmlDecl */
2778 return(0);
2779}
2780
2781/**
2782 * xmlTextReaderHasValue:
2783 * @reader: the xmlTextReaderPtr used
2784 *
2785 * Whether the node can have a text value.
2786 *
2787 * Returns 1 if true, 0 if false, and -1 in case or error
2788 */
2789int
2790xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002791 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002792 if (reader == NULL)
2793 return(-1);
2794 if (reader->node == NULL)
2795 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002796 if (reader->curnode != NULL)
2797 node = reader->curnode;
2798 else
2799 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002800
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002801 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002802 case XML_ATTRIBUTE_NODE:
2803 case XML_TEXT_NODE:
2804 case XML_CDATA_SECTION_NODE:
2805 case XML_PI_NODE:
2806 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00002807 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002808 return(1);
2809 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002810 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002811 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002812 return(0);
2813}
2814
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002815/**
2816 * xmlTextReaderValue:
2817 * @reader: the xmlTextReaderPtr used
2818 *
2819 * Provides the text value of the node if present
2820 *
2821 * Returns the string or NULL if not available. The retsult must be deallocated
2822 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002823 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002824xmlChar *
2825xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002826 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002827 if (reader == NULL)
2828 return(NULL);
2829 if (reader->node == NULL)
2830 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002831 if (reader->curnode != NULL)
2832 node = reader->curnode;
2833 else
2834 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002835
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002836 switch (node->type) {
2837 case XML_NAMESPACE_DECL:
2838 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002839 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002840 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002841
2842 if (attr->parent != NULL)
2843 return (xmlNodeListGetString
2844 (attr->parent->doc, attr->children, 1));
2845 else
2846 return (xmlNodeListGetString(NULL, attr->children, 1));
2847 break;
2848 }
2849 case XML_TEXT_NODE:
2850 case XML_CDATA_SECTION_NODE:
2851 case XML_PI_NODE:
2852 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002853 if (node->content != NULL)
2854 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002855 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002856 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002857 }
2858 return(NULL);
2859}
2860
2861/**
2862 * xmlTextReaderIsDefault:
2863 * @reader: the xmlTextReaderPtr used
2864 *
2865 * Whether an Attribute node was generated from the default value
2866 * defined in the DTD or schema.
2867 *
2868 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
2869 */
2870int
2871xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
2872 if (reader == NULL)
2873 return(-1);
2874 return(0);
2875}
2876
2877/**
2878 * xmlTextReaderQuoteChar:
2879 * @reader: the xmlTextReaderPtr used
2880 *
2881 * The quotation mark character used to enclose the value of an attribute.
2882 *
2883 * Returns " or ' and -1 in case of error
2884 */
2885int
2886xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
2887 if (reader == NULL)
2888 return(-1);
2889 /* TODO maybe lookup the attribute value for " first */
2890 return((int) '"');
2891}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002892
2893/**
2894 * xmlTextReaderXmlLang:
2895 * @reader: the xmlTextReaderPtr used
2896 *
2897 * The xml:lang scope within which the node resides.
2898 *
2899 * Returns the xml:lang value or NULL if none exists.
2900 */
2901xmlChar *
2902xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
2903 if (reader == NULL)
2904 return(NULL);
2905 if (reader->node == NULL)
2906 return(NULL);
2907 return(xmlNodeGetLang(reader->node));
2908}
2909
Daniel Veillard67df8092002-12-16 22:04:11 +00002910/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002911 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00002912 * @reader: the xmlTextReaderPtr used
2913 *
2914 * The xml:lang scope within which the node resides.
2915 *
2916 * Returns the xml:lang value or NULL if none exists.
2917 */
2918const xmlChar *
2919xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
2920 xmlChar *tmp;
2921 const xmlChar *ret;
2922
2923 if (reader == NULL)
2924 return(NULL);
2925 if (reader->node == NULL)
2926 return(NULL);
2927 tmp = xmlNodeGetLang(reader->node);
2928 if (tmp == NULL)
2929 return(NULL);
2930 ret = CONSTSTR(tmp);
2931 xmlFree(tmp);
2932 return(ret);
2933}
2934
2935/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00002936 * xmlTextReaderConstString:
2937 * @reader: the xmlTextReaderPtr used
2938 * @str: the string to intern.
2939 *
2940 * Get an interned string from the reader, allows for example to
2941 * speedup string name comparisons
2942 *
2943 * Returns an interned copy of the string or NULL in case of error. The
2944 * string will be deallocated with the reader.
2945 */
2946const xmlChar *
2947xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
2948 if (reader == NULL)
2949 return(NULL);
2950 return(CONSTSTR(str));
2951}
2952
2953/**
Daniel Veillard67df8092002-12-16 22:04:11 +00002954 * xmlTextReaderNormalization:
2955 * @reader: the xmlTextReaderPtr used
2956 *
2957 * The value indicating whether to normalize white space and attribute values.
2958 * Since attribute value and end of line normalizations are a MUST in the XML
2959 * specification only the value true is accepted. The broken bahaviour of
2960 * accepting out of range character entities like &#0; is of course not
2961 * supported either.
2962 *
2963 * Returns 1 or -1 in case of error.
2964 */
2965int
2966xmlTextReaderNormalization(xmlTextReaderPtr reader) {
2967 if (reader == NULL)
2968 return(-1);
2969 return(1);
2970}
2971
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002972/************************************************************************
2973 * *
2974 * Extensions to the base APIs *
2975 * *
2976 ************************************************************************/
2977
2978/**
2979 * xmlTextReaderSetParserProp:
2980 * @reader: the xmlTextReaderPtr used
2981 * @prop: the xmlParserProperties to set
2982 * @value: usually 0 or 1 to (de)activate it
2983 *
2984 * Change the parser processing behaviour by changing some of its internal
2985 * properties. Note that some properties can only be changed before any
2986 * read has been done.
2987 *
2988 * Returns 0 if the call was successful, or -1 in case of error
2989 */
2990int
2991xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
2992 xmlParserProperties p = (xmlParserProperties) prop;
2993 xmlParserCtxtPtr ctxt;
2994
2995 if ((reader == NULL) || (reader->ctxt == NULL))
2996 return(-1);
2997 ctxt = reader->ctxt;
2998
2999 switch (p) {
3000 case XML_PARSER_LOADDTD:
3001 if (value != 0) {
3002 if (ctxt->loadsubset == 0) {
3003 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3004 return(-1);
3005 ctxt->loadsubset = XML_DETECT_IDS;
3006 }
3007 } else {
3008 ctxt->loadsubset = 0;
3009 }
3010 return(0);
3011 case XML_PARSER_DEFAULTATTRS:
3012 if (value != 0) {
3013 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3014 } else {
3015 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3016 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3017 }
3018 return(0);
3019 case XML_PARSER_VALIDATE:
3020 if (value != 0) {
3021 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003022 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003023 } else {
3024 ctxt->validate = 0;
3025 }
3026 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003027 case XML_PARSER_SUBST_ENTITIES:
3028 if (value != 0) {
3029 ctxt->replaceEntities = 1;
3030 } else {
3031 ctxt->replaceEntities = 0;
3032 }
3033 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003034 }
3035 return(-1);
3036}
3037
3038/**
3039 * xmlTextReaderGetParserProp:
3040 * @reader: the xmlTextReaderPtr used
3041 * @prop: the xmlParserProperties to get
3042 *
3043 * Read the parser internal property.
3044 *
3045 * Returns the value, usually 0 or 1, or -1 in case of error.
3046 */
3047int
3048xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3049 xmlParserProperties p = (xmlParserProperties) prop;
3050 xmlParserCtxtPtr ctxt;
3051
3052 if ((reader == NULL) || (reader->ctxt == NULL))
3053 return(-1);
3054 ctxt = reader->ctxt;
3055
3056 switch (p) {
3057 case XML_PARSER_LOADDTD:
3058 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3059 return(1);
3060 return(0);
3061 case XML_PARSER_DEFAULTATTRS:
3062 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3063 return(1);
3064 return(0);
3065 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003066 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003067 case XML_PARSER_SUBST_ENTITIES:
3068 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003069 }
3070 return(-1);
3071}
3072
Daniel Veillarde18fc182002-12-28 22:56:33 +00003073/**
3074 * xmlTextReaderCurrentNode:
3075 * @reader: the xmlTextReaderPtr used
3076 *
3077 * Hacking interface allowing to get the xmlNodePtr correponding to the
3078 * current node being accessed by the xmlTextReader. This is dangerous
3079 * because the underlying node may be destroyed on the next Reads.
3080 *
3081 * Returns the xmlNodePtr or NULL in case of error.
3082 */
3083xmlNodePtr
3084xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3085 if (reader == NULL)
3086 return(NULL);
3087
3088 if (reader->curnode != NULL)
3089 return(reader->curnode);
3090 return(reader->node);
3091}
3092
3093/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003094 * xmlTextReaderPreserve:
3095 * @reader: the xmlTextReaderPtr used
3096 *
3097 *
3098 * current node being accessed by the xmlTextReader. This is dangerous
3099 * because the underlying node may be destroyed on the next Reads.
3100 *
3101 * Returns the xmlNodePtr or NULL in case of error.
3102 */
3103xmlNodePtr
3104xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3105 xmlNodePtr cur, parent;
3106
3107 if (reader == NULL)
3108 return(NULL);
3109
3110 if (reader->curnode != NULL)
3111 cur = reader->curnode;
3112 else
3113 cur = reader->node;
3114 if (cur == NULL)
3115 return(NULL);
3116 if (cur->_private == (void *)xmlTextReaderIsEmpty)
3117 cur->_private = (void *)xmlTextReaderIsEmptyPreserved;
3118 else
3119 cur->_private = (void *)xmlTextReaderIsPreserved;
3120
3121 parent = cur->parent;;
3122 while (parent != NULL) {
3123 parent->_private = (void *)xmlTextReaderIsPreserved;
3124 parent = parent->parent;
3125 }
3126 return(cur);
3127}
3128
3129/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003130 * xmlTextReaderCurrentDoc:
3131 * @reader: the xmlTextReaderPtr used
3132 *
3133 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003134 * current document being accessed by the xmlTextReader.
3135 * NOTE: as a result of this call, the reader will not destroy the
3136 * associated XML document and calling xmlFreeDoc() on the result
3137 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003138 *
3139 * Returns the xmlDocPtr or NULL in case of error.
3140 */
3141xmlDocPtr
3142xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003143 if ((reader == NULL) || (reader->ctxt == NULL) ||
3144 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003145 return(NULL);
3146
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003147 reader->preserve = 1;
3148 if ((reader->ctxt->myDoc->dict != NULL) &&
3149 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3150 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003151 return(reader->ctxt->myDoc);
3152}
3153
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003154#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003155/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003156 * xmlTextReaderRelaxNGSetSchema:
3157 * @reader: the xmlTextReaderPtr used
3158 * @schema: a precompiled RelaxNG schema
3159 *
3160 * Use RelaxNG to validate the document as it is processed.
3161 * Activation is only possible before the first Read().
3162 * if @schema is NULL, then RelaxNG validation is desactivated.
3163 @ The @schema should not be freed until the reader is deallocated
3164 * or its use has been deactivated.
3165 *
3166 * Returns 0 in case the RelaxNG validation could be (des)activated and
3167 * -1 in case of error.
3168 */
3169int
3170xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3171 if (schema == NULL) {
3172 if (reader->rngSchemas != NULL) {
3173 xmlRelaxNGFree(reader->rngSchemas);
3174 reader->rngSchemas = NULL;
3175 }
3176 if (reader->rngValidCtxt != NULL) {
3177 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3178 reader->rngValidCtxt = NULL;
3179 }
3180 return(0);
3181 }
3182 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3183 return(-1);
3184 if (reader->rngSchemas != NULL) {
3185 xmlRelaxNGFree(reader->rngSchemas);
3186 reader->rngSchemas = NULL;
3187 }
3188 if (reader->rngValidCtxt != NULL) {
3189 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3190 reader->rngValidCtxt = NULL;
3191 }
3192 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3193 if (reader->rngValidCtxt == NULL)
3194 return(-1);
3195 if (reader->errorFunc != NULL) {
3196 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3197 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3198 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3199 reader->errorFuncArg);
3200 }
3201 reader->rngValidErrors = 0;
3202 reader->rngFullNode = NULL;
3203 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3204 return(0);
3205}
3206
3207/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003208 * xmlTextReaderRelaxNGValidate:
3209 * @reader: the xmlTextReaderPtr used
3210 * @rng: the path to a RelaxNG schema or NULL
3211 *
3212 * Use RelaxNG to validate the document as it is processed.
3213 * Activation is only possible before the first Read().
3214 * if @rng is NULL, then RelaxNG validation is desactivated.
3215 *
3216 * Returns 0 in case the RelaxNG validation could be (des)activated and
3217 * -1 in case of error.
3218 */
3219int
3220xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3221 xmlRelaxNGParserCtxtPtr ctxt;
3222
3223 if (reader == NULL)
3224 return(-1);
3225
3226 if (rng == NULL) {
3227 if (reader->rngSchemas != NULL) {
3228 xmlRelaxNGFree(reader->rngSchemas);
3229 reader->rngSchemas = NULL;
3230 }
3231 if (reader->rngValidCtxt != NULL) {
3232 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3233 reader->rngValidCtxt = NULL;
3234 }
3235 return(0);
3236 }
3237 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3238 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003239 if (reader->rngSchemas != NULL) {
3240 xmlRelaxNGFree(reader->rngSchemas);
3241 reader->rngSchemas = NULL;
3242 }
3243 if (reader->rngValidCtxt != NULL) {
3244 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3245 reader->rngValidCtxt = NULL;
3246 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003247 ctxt = xmlRelaxNGNewParserCtxt(rng);
3248 if (reader->errorFunc != NULL) {
3249 xmlRelaxNGSetParserErrors(ctxt,
3250 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3251 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3252 reader->errorFuncArg);
3253 }
3254 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3255 xmlRelaxNGFreeParserCtxt(ctxt);
3256 if (reader->rngSchemas == NULL)
3257 return(-1);
3258 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3259 if (reader->rngValidCtxt == NULL)
3260 return(-1);
3261 if (reader->errorFunc != NULL) {
3262 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3263 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3264 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3265 reader->errorFuncArg);
3266 }
3267 reader->rngValidErrors = 0;
3268 reader->rngFullNode = NULL;
3269 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3270 return(0);
3271}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003272#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003273
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003274/************************************************************************
3275 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003276 * Error Handling Extensions *
3277 * *
3278 ************************************************************************/
3279
3280/* helper to build a xmlMalloc'ed string from a format and va_list */
3281static char *
3282xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3283 int size;
3284 int chars;
3285 char *larger;
3286 char *str;
3287
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003288 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003289 if (str == NULL) {
3290 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3291 return NULL;
3292 }
3293
3294 size = 150;
3295
3296 while (1) {
3297 chars = vsnprintf(str, size, msg, ap);
3298 if ((chars > -1) && (chars < size))
3299 break;
3300 if (chars > -1)
3301 size += chars + 1;
3302 else
3303 size += 100;
3304 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3305 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3306 xmlFree(str);
3307 return NULL;
3308 }
3309 str = larger;
3310 }
3311
3312 return str;
3313}
3314
Daniel Veillard417be3a2003-01-20 21:26:34 +00003315/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003316 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003317 * @locator: the xmlTextReaderLocatorPtr used
3318 *
3319 * Obtain the line number for the given locator.
3320 *
3321 * Returns the line number or -1 in case of error.
3322 */
3323int
3324xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3325 /* we know that locator is a xmlParserCtxtPtr */
3326 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3327 int ret = -1;
3328
3329 if (ctx->node != NULL) {
3330 ret = xmlGetLineNo(ctx->node);
3331 }
3332 else {
3333 /* inspired from error.c */
3334 xmlParserInputPtr input;
3335 input = ctx->input;
3336 if ((input->filename == NULL) && (ctx->inputNr > 1))
3337 input = ctx->inputTab[ctx->inputNr - 2];
3338 if (input != NULL) {
3339 ret = input->line;
3340 }
3341 else {
3342 ret = -1;
3343 }
3344 }
3345
3346 return ret;
3347}
3348
3349/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003350 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003351 * @locator: the xmlTextReaderLocatorPtr used
3352 *
3353 * Obtain the base URI for the given locator.
3354 *
3355 * Returns the base URI or NULL in case of error.
3356 */
3357xmlChar *
3358xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3359 /* we know that locator is a xmlParserCtxtPtr */
3360 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3361 xmlChar *ret = NULL;
3362
3363 if (ctx->node != NULL) {
3364 ret = xmlNodeGetBase(NULL,ctx->node);
3365 }
3366 else {
3367 /* inspired from error.c */
3368 xmlParserInputPtr input;
3369 input = ctx->input;
3370 if ((input->filename == NULL) && (ctx->inputNr > 1))
3371 input = ctx->inputTab[ctx->inputNr - 2];
3372 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003373 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003374 }
3375 else {
3376 ret = NULL;
3377 }
3378 }
3379
3380 return ret;
3381}
3382
Daniel Veillard26f70262003-01-16 22:45:08 +00003383static void
William M. Brack899e64a2003-09-26 18:03:42 +00003384xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003385 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3386 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3387
3388 if (str != NULL) {
3389 reader->errorFunc(reader->errorFuncArg,
3390 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003391 severity,
3392 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003393 xmlFree(str);
3394 }
3395}
3396
3397static void
3398xmlTextReaderError(void *ctxt, const char *msg, ...) {
3399 va_list ap;
3400
3401 va_start(ap,msg);
3402 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003403 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003404 xmlTextReaderBuildMessage(msg,ap));
3405 va_end(ap);
3406
3407}
3408
3409static void
3410xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3411 va_list ap;
3412
3413 va_start(ap,msg);
3414 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003415 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003416 xmlTextReaderBuildMessage(msg,ap));
3417 va_end(ap);
3418}
3419
3420static void
3421xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3422 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003423 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003424
Daniel Veillard417be3a2003-01-20 21:26:34 +00003425 if ((len > 1) && (msg[len - 2] != ':')) {
3426 /*
3427 * some callbacks only report locator information:
3428 * skip them (mimicking behaviour in error.c)
3429 */
3430 va_start(ap,msg);
3431 xmlTextReaderGenericError(ctxt,
3432 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3433 xmlTextReaderBuildMessage(msg,ap));
3434 va_end(ap);
3435 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003436}
3437
3438static void
3439xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3440 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003441 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003442
Daniel Veillard417be3a2003-01-20 21:26:34 +00003443 if ((len != 0) && (msg[len - 1] != ':')) {
3444 /*
3445 * some callbacks only report locator information:
3446 * skip them (mimicking behaviour in error.c)
3447 */
3448 va_start(ap,msg);
3449 xmlTextReaderGenericError(ctxt,
3450 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3451 xmlTextReaderBuildMessage(msg,ap));
3452 va_end(ap);
3453 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003454}
3455
3456/**
3457 * xmlTextReaderSetErrorHandler:
3458 * @reader: the xmlTextReaderPtr used
3459 * @f: the callback function to call on error and warnings
3460 * @arg: a user argument to pass to the callback function
3461 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003462 * Register a callback function that will be called on error and warnings.
3463 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003464 * If @f is NULL, the default error and warning handlers are restored.
3465 */
3466void
3467xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3468 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003469 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003470 if (f != NULL) {
3471 reader->ctxt->sax->error = xmlTextReaderError;
3472 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3473 reader->ctxt->sax->warning = xmlTextReaderWarning;
3474 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3475 reader->errorFunc = f;
3476 reader->errorFuncArg = arg;
3477 }
3478 else {
3479 /* restore defaults */
3480 reader->ctxt->sax->error = xmlParserError;
3481 reader->ctxt->vctxt.error = xmlParserValidityError;
3482 reader->ctxt->sax->warning = xmlParserWarning;
3483 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3484 reader->errorFunc = NULL;
3485 reader->errorFuncArg = NULL;
3486 }
3487}
3488
Daniel Veillard417be3a2003-01-20 21:26:34 +00003489/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003490 * xmlTextReaderIsValid:
3491 * @reader: the xmlTextReaderPtr used
3492 *
3493 * Retrieve the validity status from the parser context
3494 *
3495 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3496 */
3497int
3498xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003499 if (reader == NULL) return(-1);
3500#ifdef LIBXML_SCHEMAS_ENABLED
3501 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3502 return(reader->rngValidErrors == 0);
3503#endif
3504 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3505 (reader->ctxt != NULL))
3506 return(reader->ctxt->valid);
3507 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003508}
3509
3510/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003511 * xmlTextReaderGetErrorHandler:
3512 * @reader: the xmlTextReaderPtr used
3513 * @f: the callback function or NULL is no callback has been registered
3514 * @arg: a user argument
3515 *
3516 * Retrieve the error callback function and user argument.
3517 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003518void
3519xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3520 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003521 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003522 *f = reader->errorFunc;
3523 *arg = reader->errorFuncArg;
3524}
3525
3526/************************************************************************
3527 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003528 * Utilities *
3529 * *
3530 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00003531#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003532/**
3533 * xmlBase64Decode:
3534 * @in: the input buffer
3535 * @inlen: the size of the input (in), the size read from it (out)
3536 * @to: the output buffer
3537 * @tolen: the size of the output (in), the size written to (out)
3538 *
3539 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00003540 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003541 *
3542 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
3543 * 2 if there wasn't enough space on the output or -1 in case of error.
3544 */
3545static int
3546xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
3547 unsigned char *to, unsigned long *tolen) {
3548 unsigned long incur; /* current index in in[] */
3549 unsigned long inblk; /* last block index in in[] */
3550 unsigned long outcur; /* current index in out[] */
3551 unsigned long inmax; /* size of in[] */
3552 unsigned long outmax; /* size of out[] */
3553 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00003554 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003555 int nbintmp; /* number of byte in intmp[] */
3556 int is_ignore; /* cur should be ignored */
3557 int is_end = 0; /* the end of the base64 was found */
3558 int retval = 1;
3559 int i;
3560
3561 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
3562 return(-1);
3563
3564 incur = 0;
3565 inblk = 0;
3566 outcur = 0;
3567 inmax = *inlen;
3568 outmax = *tolen;
3569 nbintmp = 0;
3570
3571 while (1) {
3572 if (incur >= inmax)
3573 break;
3574 cur = in[incur++];
3575 is_ignore = 0;
3576 if ((cur >= 'A') && (cur <= 'Z'))
3577 cur = cur - 'A';
3578 else if ((cur >= 'a') && (cur <= 'z'))
3579 cur = cur - 'a' + 26;
3580 else if ((cur >= '0') && (cur <= '9'))
3581 cur = cur - '0' + 52;
3582 else if (cur == '+')
3583 cur = 62;
3584 else if (cur == '/')
3585 cur = 63;
3586 else if (cur == '.')
3587 cur = 0;
3588 else if (cur == '=') /*no op , end of the base64 stream */
3589 is_end = 1;
3590 else {
3591 is_ignore = 1;
3592 if (nbintmp == 0)
3593 inblk = incur;
3594 }
3595
3596 if (!is_ignore) {
3597 int nbouttmp = 3;
3598 int is_break = 0;
3599
3600 if (is_end) {
3601 if (nbintmp == 0)
3602 break;
3603 if ((nbintmp == 1) || (nbintmp == 2))
3604 nbouttmp = 1;
3605 else
3606 nbouttmp = 2;
3607 nbintmp = 3;
3608 is_break = 1;
3609 }
3610 intmp[nbintmp++] = cur;
3611 /*
3612 * if intmp is full, push the 4byte sequence as a 3 byte
3613 * sequence out
3614 */
3615 if (nbintmp == 4) {
3616 nbintmp = 0;
3617 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
3618 outtmp[1] =
3619 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
3620 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
3621 if (outcur + 3 >= outmax) {
3622 retval = 2;
3623 break;
3624 }
3625
3626 for (i = 0; i < nbouttmp; i++)
3627 to[outcur++] = outtmp[i];
3628 inblk = incur;
3629 }
3630
3631 if (is_break) {
3632 retval = 0;
3633 break;
3634 }
3635 }
3636 }
3637
3638 *tolen = outcur;
3639 *inlen = inblk;
3640 return (retval);
3641}
3642
3643/*
3644 * Test routine for the xmlBase64Decode function
3645 */
3646#if 0
3647int main(int argc, char **argv) {
3648 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
3649 char output[100];
3650 char output2[100];
3651 char output3[100];
3652 unsigned long inlen = strlen(input);
3653 unsigned long outlen = 100;
3654 int ret;
3655 unsigned long cons, tmp, tmp2, prod;
3656
3657 /*
3658 * Direct
3659 */
3660 ret = xmlBase64Decode(input, &inlen, output, &outlen);
3661
3662 output[outlen] = 0;
3663 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
3664
3665 /*
3666 * output chunking
3667 */
3668 cons = 0;
3669 prod = 0;
3670 while (cons < inlen) {
3671 tmp = 5;
3672 tmp2 = inlen - cons;
3673
3674 printf("%ld %ld\n", cons, prod);
3675 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
3676 cons += tmp2;
3677 prod += tmp;
3678 printf("%ld %ld\n", cons, prod);
3679 }
3680 output2[outlen] = 0;
3681 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
3682
3683 /*
3684 * input chunking
3685 */
3686 cons = 0;
3687 prod = 0;
3688 while (cons < inlen) {
3689 tmp = 100 - prod;
3690 tmp2 = inlen - cons;
3691 if (tmp2 > 5)
3692 tmp2 = 5;
3693
3694 printf("%ld %ld\n", cons, prod);
3695 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
3696 cons += tmp2;
3697 prod += tmp;
3698 printf("%ld %ld\n", cons, prod);
3699 }
3700 output3[outlen] = 0;
3701 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
3702 return(0);
3703
3704}
3705#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00003706#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00003707#endif /* LIBXML_READER_ENABLED */