blob: 662ee269dd58fe408d47fddd48c5fc2622346124 [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);
1033
1034 do {
1035 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1036 return(1);
Daniel Veillarda37aab82003-06-09 09:10:36 +00001037 if (reader->ctxt->nodeNr <= reader->depth)
1038 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001039 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1040 return(1);
1041 val = xmlTextReaderPushData(reader);
1042 if (val < 0)
1043 return(-1);
1044 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1045 return(1);
1046}
1047
1048/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001049 * xmlTextReaderRead:
1050 * @reader: the xmlTextReaderPtr used
1051 *
1052 * Moves the position of the current instance to the next node in
1053 * the stream, exposing its properties.
1054 *
1055 * Returns 1 if the node was read successfully, 0 if there is no more
1056 * nodes to read, or -1 in case of error
1057 */
1058int
1059xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001060 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001061 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001062 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001063
1064 if ((reader == NULL) || (reader->ctxt == NULL))
1065 return(-1);
1066 if (reader->ctxt->wellFormed != 1)
1067 return(-1);
1068
1069#ifdef DEBUG_READER
1070 fprintf(stderr, "\nREAD ");
1071 DUMP_READER
1072#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001073 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001074 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1075 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001076 /*
1077 * Initial state
1078 */
1079 do {
1080 val = xmlTextReaderPushData(reader);
1081 if (val < 0)
1082 return(-1);
1083 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001084 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1085 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001086 if (reader->ctxt->myDoc != NULL)
1087 reader->ctxt->myDoc->_private = reader;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001088 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001089 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001090 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001091 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001092 if (reader->node == NULL)
1093 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001094 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001095 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001096 if (reader->ctxt->myDoc != NULL) {
1097 reader->node = reader->ctxt->myDoc->children;
1098 }
1099 if (reader->node == NULL)
1100 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001101 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001102 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001103 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001104 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001105 }
1106 oldstate = reader->state;
1107 olddepth = reader->ctxt->nodeNr;
1108 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001109
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001110get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001111 /*
1112 * If we are not backtracking on ancestors or examined nodes,
1113 * that the parser didn't finished or that we arent at the end
1114 * of stream, continue processing.
1115 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001116 while ((reader->node->next == NULL) &&
1117 (reader->ctxt->nodeNr == olddepth) &&
1118 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001119 (reader->node->children == NULL) ||
1120 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001121 ((reader->node->children != NULL) &&
1122 (reader->node->children->type == XML_TEXT_NODE) &&
1123 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001124 (reader->node->type == XML_DTD_NODE) ||
1125 (reader->node->type == XML_DOCUMENT_NODE) ||
1126 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001127 ((reader->ctxt->node == NULL) ||
1128 (reader->ctxt->node == reader->node) ||
1129 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001130 (reader->ctxt->instate != XML_PARSER_EOF)) {
1131 val = xmlTextReaderPushData(reader);
1132 if (val < 0)
1133 return(-1);
1134 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001135 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001136 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001137 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001138 if ((reader->node->children != NULL) &&
1139 (reader->node->type != XML_ENTITY_REF_NODE) &&
1140 (reader->node->type != XML_DTD_NODE)) {
1141 reader->node = reader->node->children;
1142 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001143 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001144 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001145 }
1146 }
1147 if (reader->node->next != NULL) {
1148 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001149 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001150 (reader->node->children == NULL) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001151 (reader->node->_private != (void *)xmlTextReaderIsEmpty) &&
1152 (reader->node->_private != (void *)xmlTextReaderIsEmptyPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001153 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001154 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001155 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001156#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001157 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001158 (reader->node->type == XML_ELEMENT_NODE))
1159 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001160#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001161 reader->node = reader->node->next;
1162 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001163
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001164 /*
1165 * Cleanup of the old node
1166 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001167 if ((reader->node->prev != NULL) &&
1168 (reader->node->prev->type != XML_DTD_NODE)) {
1169 xmlNodePtr tmp = reader->node->prev;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001170 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
1171 (tmp->_private != xmlTextReaderIsPreserved)) {
1172 xmlUnlinkNode(tmp);
1173 xmlTextReaderFreeNode(reader, tmp);
1174 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001175 }
1176
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001177 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001178 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001179 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001180 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001181 (reader->node->children == NULL) &&
1182 (reader->node->_private != (void *)xmlTextReaderIsEmpty)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001183 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001184 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001185 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001186#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001187 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001188 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001189#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001190 reader->node = reader->node->parent;
1191 if ((reader->node == NULL) ||
1192 (reader->node->type == XML_DOCUMENT_NODE) ||
1193#ifdef LIBXML_DOCB_ENABLED
1194 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1195#endif
1196 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001197 if (reader->mode != XML_TEXTREADER_DONE) {
1198 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1199 reader->mode = XML_TEXTREADER_DONE;
1200 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001201 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001202 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001203
1204 /*
1205 * Cleanup of the old node
1206 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001207 if ((oldnode->type != XML_DTD_NODE) &&
1208 (oldnode->_private != xmlTextReaderIsEmptyPreserved) &&
1209 (oldnode->_private != xmlTextReaderIsPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001210 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001211 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001212 }
1213
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001214 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001215 }
1216 reader->depth--;
1217 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001218
1219node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001220 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001221
1222 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001223 * If we are in the middle of a piece of CDATA make sure it's finished
1224 */
1225 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001226 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001227 ((reader->node->type == XML_TEXT_NODE) ||
1228 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1229 xmlTextReaderExpand(reader);
1230 }
1231
1232 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001233 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001234 */
1235 if ((reader->node != NULL) &&
1236 (reader->node->type == XML_ENTITY_REF_NODE) &&
1237 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1238 /*
1239 * Case where the underlying tree is not availble, lookup the entity
1240 * and walk it.
1241 */
1242 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1243 (reader->ctxt->sax->getEntity != NULL)) {
1244 reader->node->children = (xmlNodePtr)
1245 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1246 }
1247
1248 if ((reader->node->children != NULL) &&
1249 (reader->node->children->type == XML_ENTITY_DECL) &&
1250 (reader->node->children->children != NULL)) {
1251 xmlTextReaderEntPush(reader, reader->node);
1252 reader->node = reader->node->children->children;
1253 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001254#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001255 } else if ((reader->node != NULL) &&
1256 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001257 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001258 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001259#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001260 }
1261 if ((reader->node != NULL) &&
1262 (reader->node->type == XML_ENTITY_DECL) &&
1263 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1264 reader->node = xmlTextReaderEntPop(reader);
1265 reader->depth++;
1266 goto get_next_node;
1267 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001268#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001269 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001270 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001271
1272 if ((node->type == XML_ELEMENT_NODE) &&
1273 ((reader->state != XML_TEXTREADER_END) &&
1274 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1275 xmlTextReaderValidatePush(reader);
1276 } else if ((node->type == XML_TEXT_NODE) ||
1277 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001278 xmlTextReaderValidateCData(reader, node->content,
1279 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001280 }
1281 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001282#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001283 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001284node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001285 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001286 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001287}
1288
Daniel Veillard67df8092002-12-16 22:04:11 +00001289/**
1290 * xmlTextReaderReadState:
1291 * @reader: the xmlTextReaderPtr used
1292 *
1293 * Gets the read state of the reader.
1294 *
1295 * Returns the state value, or -1 in case of error
1296 */
1297int
1298xmlTextReaderReadState(xmlTextReaderPtr reader) {
1299 if (reader == NULL)
1300 return(-1);
1301 return(reader->mode);
1302}
1303
1304/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001305 * xmlTextReaderExpand:
1306 * @reader: the xmlTextReaderPtr used
1307 *
1308 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001309 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001310 *
1311 * Returns a node pointer valid until the next xmlTextReaderRead() call
1312 * or NULL in case of error.
1313 */
1314xmlNodePtr
1315xmlTextReaderExpand(xmlTextReaderPtr reader) {
1316 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1317 return(NULL);
1318 if (xmlTextReaderDoExpand(reader) < 0)
1319 return(NULL);
1320 return(reader->node);
1321}
1322
1323/**
1324 * xmlTextReaderNext:
1325 * @reader: the xmlTextReaderPtr used
1326 *
1327 * Skip to the node following the current one in document order while
1328 * avoiding the subtree if any.
1329 *
1330 * Returns 1 if the node was read successfully, 0 if there is no more
1331 * nodes to read, or -1 in case of error
1332 */
1333int
1334xmlTextReaderNext(xmlTextReaderPtr reader) {
1335 int ret;
1336 xmlNodePtr cur;
1337
1338 if (reader == NULL)
1339 return(-1);
1340 cur = reader->node;
1341 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1342 return(xmlTextReaderRead(reader));
1343 if (reader->state == XML_TEXTREADER_END)
1344 return(xmlTextReaderRead(reader));
1345 if (cur->_private == (void *)xmlTextReaderIsEmpty)
1346 return(xmlTextReaderRead(reader));
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001347 if (cur->_private == (void *)xmlTextReaderIsEmptyPreserved)
1348 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001349 do {
1350 ret = xmlTextReaderRead(reader);
1351 if (ret != 1)
1352 return(ret);
1353 } while (reader->node != cur);
1354 return(xmlTextReaderRead(reader));
1355}
1356
1357/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001358 * xmlTextReaderReadInnerXml:
1359 * @reader: the xmlTextReaderPtr used
1360 *
1361 * Reads the contents of the current node, including child nodes and markup.
1362 *
1363 * Returns a string containing the XML content, or NULL if the current node
1364 * is neither an element nor attribute, or has no child nodes. The
1365 * string must be deallocated by the caller.
1366 */
1367xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001368xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001369 TODO
1370 return(NULL);
1371}
1372
1373/**
1374 * xmlTextReaderReadOuterXml:
1375 * @reader: the xmlTextReaderPtr used
1376 *
1377 * Reads the contents of the current node, including child nodes and markup.
1378 *
1379 * Returns a string containing the XML content, or NULL if the current node
1380 * is neither an element nor attribute, or has no child nodes. The
1381 * string must be deallocated by the caller.
1382 */
1383xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001384xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001385 TODO
1386 return(NULL);
1387}
1388
1389/**
1390 * xmlTextReaderReadString:
1391 * @reader: the xmlTextReaderPtr used
1392 *
1393 * Reads the contents of an element or a text node as a string.
1394 *
1395 * Returns a string containing the contents of the Element or Text node,
1396 * or NULL if the reader is positioned on any other type of node.
1397 * The string must be deallocated by the caller.
1398 */
1399xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001400xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001401 TODO
1402 return(NULL);
1403}
1404
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001405#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001406/**
1407 * xmlTextReaderReadBase64:
1408 * @reader: the xmlTextReaderPtr used
1409 * @array: a byte array to store the content.
1410 * @offset: the zero-based index into array where the method should
1411 * begin to write.
1412 * @len: the number of bytes to write.
1413 *
1414 * Reads and decodes the Base64 encoded contents of an element and
1415 * stores the result in a byte buffer.
1416 *
1417 * Returns the number of bytes written to array, or zero if the current
1418 * instance is not positioned on an element or -1 in case of error.
1419 */
1420int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001421xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1422 unsigned char *array ATTRIBUTE_UNUSED,
1423 int offset ATTRIBUTE_UNUSED,
1424 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001425 if ((reader == NULL) || (reader->ctxt == NULL))
1426 return(-1);
1427 if (reader->ctxt->wellFormed != 1)
1428 return(-1);
1429
1430 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1431 return(0);
1432 TODO
1433 return(0);
1434}
1435
1436/**
1437 * xmlTextReaderReadBinHex:
1438 * @reader: the xmlTextReaderPtr used
1439 * @array: a byte array to store the content.
1440 * @offset: the zero-based index into array where the method should
1441 * begin to write.
1442 * @len: the number of bytes to write.
1443 *
1444 * Reads and decodes the BinHex encoded contents of an element and
1445 * stores the result in a byte buffer.
1446 *
1447 * Returns the number of bytes written to array, or zero if the current
1448 * instance is not positioned on an element or -1 in case of error.
1449 */
1450int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001451xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1452 unsigned char *array ATTRIBUTE_UNUSED,
1453 int offset ATTRIBUTE_UNUSED,
1454 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001455 if ((reader == NULL) || (reader->ctxt == NULL))
1456 return(-1);
1457 if (reader->ctxt->wellFormed != 1)
1458 return(-1);
1459
1460 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1461 return(0);
1462 TODO
1463 return(0);
1464}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001465#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001466
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001467/************************************************************************
1468 * *
1469 * Constructor and destructors *
1470 * *
1471 ************************************************************************/
1472/**
1473 * xmlNewTextReader:
1474 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001475 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001476 *
1477 * Create an xmlTextReader structure fed with @input
1478 *
1479 * Returns the new xmlTextReaderPtr or NULL in case of error
1480 */
1481xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001482xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001483 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001484
1485 if (input == NULL)
1486 return(NULL);
1487 ret = xmlMalloc(sizeof(xmlTextReader));
1488 if (ret == NULL) {
1489 xmlGenericError(xmlGenericErrorContext,
1490 "xmlNewTextReader : malloc failed\n");
1491 return(NULL);
1492 }
1493 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001494 ret->entTab = NULL;
1495 ret->entMax = 0;
1496 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001497 ret->input = input;
1498 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1499 if (ret->sax == NULL) {
1500 xmlFree(ret);
1501 xmlGenericError(xmlGenericErrorContext,
1502 "xmlNewTextReader : malloc failed\n");
1503 return(NULL);
1504 }
Daniel Veillard81273902003-09-30 00:43:48 +00001505 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001506 ret->startElement = ret->sax->startElement;
1507 ret->sax->startElement = xmlTextReaderStartElement;
1508 ret->endElement = ret->sax->endElement;
1509 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001510#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001511 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001512#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001513 ret->startElementNs = ret->sax->startElementNs;
1514 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1515 ret->endElementNs = ret->sax->endElementNs;
1516 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001517#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001518 } else {
1519 ret->startElementNs = NULL;
1520 ret->endElementNs = NULL;
1521 }
Daniel Veillard81273902003-09-30 00:43:48 +00001522#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001523 ret->characters = ret->sax->characters;
1524 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001525 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001526 ret->cdataBlock = ret->sax->cdataBlock;
1527 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001528
Daniel Veillard67df8092002-12-16 22:04:11 +00001529 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001530 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001531 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001532 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001533 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001534 }
1535 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001536 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001537 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001538 ret->base = 0;
1539 ret->cur = 4;
1540 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001541 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001542 ret->base = 0;
1543 ret->cur = 0;
1544 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001545 if (ret->ctxt == NULL) {
1546 xmlGenericError(xmlGenericErrorContext,
1547 "xmlNewTextReader : malloc failed\n");
1548 xmlFree(ret->sax);
1549 xmlFree(ret);
1550 return(NULL);
1551 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001552 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001553 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001554 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001555 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001556 /*
1557 * use the parser dictionnary to allocate all elements and attributes names
1558 */
1559 ret->ctxt->docdict = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001560 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001561}
1562
1563/**
1564 * xmlNewTextReaderFilename:
1565 * @URI: the URI of the resource to process
1566 *
1567 * Create an xmlTextReader structure fed with the resource at @URI
1568 *
1569 * Returns the new xmlTextReaderPtr or NULL in case of error
1570 */
1571xmlTextReaderPtr
1572xmlNewTextReaderFilename(const char *URI) {
1573 xmlParserInputBufferPtr input;
1574 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001575 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001576
1577 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1578 if (input == NULL)
1579 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001580 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001581 if (ret == NULL) {
1582 xmlFreeParserInputBuffer(input);
1583 return(NULL);
1584 }
1585 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001586 if (ret->ctxt->directory == NULL)
1587 directory = xmlParserGetDirectory(URI);
1588 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1589 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1590 if (directory != NULL)
1591 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001592 return(ret);
1593}
1594
1595/**
1596 * xmlFreeTextReader:
1597 * @reader: the xmlTextReaderPtr
1598 *
1599 * Deallocate all the resources associated to the reader
1600 */
1601void
1602xmlFreeTextReader(xmlTextReaderPtr reader) {
1603 if (reader == NULL)
1604 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001605#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001606 if (reader->rngSchemas != NULL) {
1607 xmlRelaxNGFree(reader->rngSchemas);
1608 reader->rngSchemas = NULL;
1609 }
1610 if (reader->rngValidCtxt != NULL) {
1611 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1612 reader->rngValidCtxt = NULL;
1613 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001614#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001615 if (reader->ctxt != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001616 if (reader->ctxt->myDoc != NULL) {
1617 if (reader->preserve == 0)
1618 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1619 reader->ctxt->myDoc = NULL;
1620 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001621 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1622 (reader->ctxt->vctxt.vstateMax > 0)){
1623 xmlFree(reader->ctxt->vctxt.vstateTab);
1624 reader->ctxt->vctxt.vstateTab = 0;
1625 reader->ctxt->vctxt.vstateMax = 0;
1626 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001627 if (reader->allocs & XML_TEXTREADER_CTXT)
1628 xmlFreeParserCtxt(reader->ctxt);
1629 }
1630 if (reader->sax != NULL)
1631 xmlFree(reader->sax);
1632 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1633 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001634 if (reader->faketext != NULL) {
1635 xmlFreeNode(reader->faketext);
1636 }
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001637 if (reader->entTab != NULL)
1638 xmlFree(reader->entTab);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001639 xmlFree(reader);
1640}
1641
1642/************************************************************************
1643 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001644 * Methods for XmlTextReader *
1645 * *
1646 ************************************************************************/
1647/**
1648 * xmlTextReaderClose:
1649 * @reader: the xmlTextReaderPtr used
1650 *
1651 * This method releases any resources allocated by the current instance
1652 * changes the state to Closed and close any underlying input.
1653 *
1654 * Returns 0 or -1 in case of error
1655 */
1656int
1657xmlTextReaderClose(xmlTextReaderPtr reader) {
1658 if (reader == NULL)
1659 return(-1);
1660 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001661 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001662 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1663 if (reader->ctxt != NULL) {
1664 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001665 if (reader->preserve == 0)
1666 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001667 reader->ctxt->myDoc = NULL;
1668 }
1669 if (reader->allocs & XML_TEXTREADER_CTXT) {
1670 xmlFreeParserCtxt(reader->ctxt);
1671 reader->allocs -= XML_TEXTREADER_CTXT;
1672 }
1673 }
1674 if (reader->sax != NULL) {
1675 xmlFree(reader->sax);
1676 reader->sax = NULL;
1677 }
1678 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1679 xmlFreeParserInputBuffer(reader->input);
1680 reader->allocs -= XML_TEXTREADER_INPUT;
1681 }
1682 return(0);
1683}
1684
1685/**
1686 * xmlTextReaderGetAttributeNo:
1687 * @reader: the xmlTextReaderPtr used
1688 * @no: the zero-based index of the attribute relative to the containing element
1689 *
1690 * Provides the value of the attribute with the specified index relative
1691 * to the containing element.
1692 *
1693 * Returns a string containing the value of the specified attribute, or NULL
1694 * in case of error. The string must be deallocated by the caller.
1695 */
1696xmlChar *
1697xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1698 xmlChar *ret;
1699 int i;
1700 xmlAttrPtr cur;
1701 xmlNsPtr ns;
1702
1703 if (reader == NULL)
1704 return(NULL);
1705 if (reader->node == NULL)
1706 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001707 if (reader->curnode != NULL)
1708 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001709 /* TODO: handle the xmlDecl */
1710 if (reader->node->type != XML_ELEMENT_NODE)
1711 return(NULL);
1712
1713 ns = reader->node->nsDef;
1714 for (i = 0;(i < no) && (ns != NULL);i++) {
1715 ns = ns->next;
1716 }
1717 if (ns != NULL)
1718 return(xmlStrdup(ns->href));
1719
1720 cur = reader->node->properties;
1721 if (cur == NULL)
1722 return(NULL);
1723 for (;i < no;i++) {
1724 cur = cur->next;
1725 if (cur == NULL)
1726 return(NULL);
1727 }
1728 /* TODO walk the DTD if present */
1729
1730 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1731 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1732 return(ret);
1733}
1734
1735/**
1736 * xmlTextReaderGetAttribute:
1737 * @reader: the xmlTextReaderPtr used
1738 * @name: the qualified name of the attribute.
1739 *
1740 * Provides the value of the attribute with the specified qualified name.
1741 *
1742 * Returns a string containing the value of the specified attribute, or NULL
1743 * in case of error. The string must be deallocated by the caller.
1744 */
1745xmlChar *
1746xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1747 xmlChar *prefix = NULL;
1748 xmlChar *localname;
1749 xmlNsPtr ns;
1750 xmlChar *ret = NULL;
1751
1752 if ((reader == NULL) || (name == NULL))
1753 return(NULL);
1754 if (reader->node == NULL)
1755 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001756 if (reader->curnode != NULL)
1757 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001758
1759 /* TODO: handle the xmlDecl */
1760 if (reader->node->type != XML_ELEMENT_NODE)
1761 return(NULL);
1762
1763 localname = xmlSplitQName2(name, &prefix);
1764 if (localname == NULL)
1765 return(xmlGetProp(reader->node, name));
1766
1767 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1768 if (ns != NULL)
1769 ret = xmlGetNsProp(reader->node, localname, ns->href);
1770
1771 if (localname != NULL)
1772 xmlFree(localname);
1773 if (prefix != NULL)
1774 xmlFree(prefix);
1775 return(ret);
1776}
1777
1778
1779/**
1780 * xmlTextReaderGetAttributeNs:
1781 * @reader: the xmlTextReaderPtr used
1782 * @localName: the local name of the attribute.
1783 * @namespaceURI: the namespace URI of the attribute.
1784 *
1785 * Provides the value of the specified attribute
1786 *
1787 * Returns a string containing the value of the specified attribute, or NULL
1788 * in case of error. The string must be deallocated by the caller.
1789 */
1790xmlChar *
1791xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
1792 const xmlChar *namespaceURI) {
1793 if ((reader == NULL) || (localName == NULL))
1794 return(NULL);
1795 if (reader->node == NULL)
1796 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001797 if (reader->curnode != NULL)
1798 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001799
1800 /* TODO: handle the xmlDecl */
1801 if (reader->node->type != XML_ELEMENT_NODE)
1802 return(NULL);
1803
1804 return(xmlGetNsProp(reader->node, localName, namespaceURI));
1805}
1806
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001807/**
1808 * xmlTextReaderGetRemainder:
1809 * @reader: the xmlTextReaderPtr used
1810 *
1811 * Method to get the remainder of the buffered XML. this method stops the
1812 * parser, set its state to End Of File and return the input stream with
1813 * what is left that the parser did not use.
1814 *
1815 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
1816 * in case of error.
1817 */
1818xmlParserInputBufferPtr
1819xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
1820 xmlParserInputBufferPtr ret = NULL;
1821
1822 if (reader == NULL)
1823 return(NULL);
1824 if (reader->node == NULL)
1825 return(NULL);
1826
1827 reader->node = NULL;
1828 reader->curnode = NULL;
1829 reader->mode = XML_TEXTREADER_MODE_EOF;
1830 if (reader->ctxt != NULL) {
1831 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001832 if (reader->preserve == 0)
1833 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001834 reader->ctxt->myDoc = NULL;
1835 }
1836 if (reader->allocs & XML_TEXTREADER_CTXT) {
1837 xmlFreeParserCtxt(reader->ctxt);
1838 reader->allocs -= XML_TEXTREADER_CTXT;
1839 }
1840 }
1841 if (reader->sax != NULL) {
1842 xmlFree(reader->sax);
1843 reader->sax = NULL;
1844 }
1845 if (reader->allocs & XML_TEXTREADER_INPUT) {
1846 ret = reader->input;
1847 reader->allocs -= XML_TEXTREADER_INPUT;
1848 } else {
1849 /*
1850 * Hum, one may need to duplicate the data structure because
1851 * without reference counting the input may be freed twice:
1852 * - by the layer which allocated it.
1853 * - by the layer to which would have been returned to.
1854 */
1855 TODO
1856 return(NULL);
1857 }
1858 return(ret);
1859}
1860
1861/**
1862 * xmlTextReaderLookupNamespace:
1863 * @reader: the xmlTextReaderPtr used
1864 * @prefix: the prefix whose namespace URI is to be resolved. To return
1865 * the default namespace, specify NULL
1866 *
1867 * Resolves a namespace prefix in the scope of the current element.
1868 *
1869 * Returns a string containing the namespace URI to which the prefix maps
1870 * or NULL in case of error. The string must be deallocated by the caller.
1871 */
1872xmlChar *
1873xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
1874 xmlNsPtr ns;
1875
1876 if (reader == NULL)
1877 return(NULL);
1878 if (reader->node == NULL)
1879 return(NULL);
1880
1881 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1882 if (ns == NULL)
1883 return(NULL);
1884 return(xmlStrdup(ns->href));
1885}
1886
1887/**
1888 * xmlTextReaderMoveToAttributeNo:
1889 * @reader: the xmlTextReaderPtr used
1890 * @no: the zero-based index of the attribute relative to the containing
1891 * element.
1892 *
1893 * Moves the position of the current instance to the attribute with
1894 * the specified index relative to the containing element.
1895 *
1896 * Returns 1 in case of success, -1 in case of error, 0 if not found
1897 */
1898int
1899xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
1900 int i;
1901 xmlAttrPtr cur;
1902 xmlNsPtr ns;
1903
1904 if (reader == NULL)
1905 return(-1);
1906 if (reader->node == NULL)
1907 return(-1);
1908 /* TODO: handle the xmlDecl */
1909 if (reader->node->type != XML_ELEMENT_NODE)
1910 return(-1);
1911
1912 reader->curnode = NULL;
1913
1914 ns = reader->node->nsDef;
1915 for (i = 0;(i < no) && (ns != NULL);i++) {
1916 ns = ns->next;
1917 }
1918 if (ns != NULL) {
1919 reader->curnode = (xmlNodePtr) ns;
1920 return(1);
1921 }
1922
1923 cur = reader->node->properties;
1924 if (cur == NULL)
1925 return(0);
1926 for (;i < no;i++) {
1927 cur = cur->next;
1928 if (cur == NULL)
1929 return(0);
1930 }
1931 /* TODO walk the DTD if present */
1932
1933 reader->curnode = (xmlNodePtr) cur;
1934 return(1);
1935}
1936
1937/**
1938 * xmlTextReaderMoveToAttribute:
1939 * @reader: the xmlTextReaderPtr used
1940 * @name: the qualified name of the attribute.
1941 *
1942 * Moves the position of the current instance to the attribute with
1943 * the specified qualified name.
1944 *
1945 * Returns 1 in case of success, -1 in case of error, 0 if not found
1946 */
1947int
1948xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1949 xmlChar *prefix = NULL;
1950 xmlChar *localname;
1951 xmlNsPtr ns;
1952 xmlAttrPtr prop;
1953
1954 if ((reader == NULL) || (name == NULL))
1955 return(-1);
1956 if (reader->node == NULL)
1957 return(-1);
1958
1959 /* TODO: handle the xmlDecl */
1960 if (reader->node->type != XML_ELEMENT_NODE)
1961 return(0);
1962
1963 localname = xmlSplitQName2(name, &prefix);
1964 if (localname == NULL) {
1965 /*
1966 * Namespace default decl
1967 */
1968 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
1969 ns = reader->node->nsDef;
1970 while (ns != NULL) {
1971 if (ns->prefix == NULL) {
1972 reader->curnode = (xmlNodePtr) ns;
1973 return(1);
1974 }
1975 ns = ns->next;
1976 }
1977 return(0);
1978 }
1979
1980 prop = reader->node->properties;
1981 while (prop != NULL) {
1982 /*
1983 * One need to have
1984 * - same attribute names
1985 * - and the attribute carrying that namespace
1986 */
1987 if ((xmlStrEqual(prop->name, name)) &&
1988 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
1989 reader->curnode = (xmlNodePtr) prop;
1990 return(1);
1991 }
1992 prop = prop->next;
1993 }
1994 return(0);
1995 }
1996
1997 /*
1998 * Namespace default decl
1999 */
2000 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2001 ns = reader->node->nsDef;
2002 while (ns != NULL) {
2003 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2004 reader->curnode = (xmlNodePtr) ns;
2005 goto found;
2006 }
2007 ns = ns->next;
2008 }
2009 goto not_found;
2010 }
2011 prop = reader->node->properties;
2012 while (prop != NULL) {
2013 /*
2014 * One need to have
2015 * - same attribute names
2016 * - and the attribute carrying that namespace
2017 */
2018 if ((xmlStrEqual(prop->name, localname)) &&
2019 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2020 reader->curnode = (xmlNodePtr) prop;
2021 goto found;
2022 }
2023 prop = prop->next;
2024 }
2025not_found:
2026 if (localname != NULL)
2027 xmlFree(localname);
2028 if (prefix != NULL)
2029 xmlFree(prefix);
2030 return(0);
2031
2032found:
2033 if (localname != NULL)
2034 xmlFree(localname);
2035 if (prefix != NULL)
2036 xmlFree(prefix);
2037 return(1);
2038}
2039
2040/**
2041 * xmlTextReaderMoveToAttributeNs:
2042 * @reader: the xmlTextReaderPtr used
2043 * @localName: the local name of the attribute.
2044 * @namespaceURI: the namespace URI of the attribute.
2045 *
2046 * Moves the position of the current instance to the attribute with the
2047 * specified local name and namespace URI.
2048 *
2049 * Returns 1 in case of success, -1 in case of error, 0 if not found
2050 */
2051int
2052xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2053 const xmlChar *localName, const xmlChar *namespaceURI) {
2054 xmlAttrPtr prop;
2055 xmlNodePtr node;
2056
2057 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2058 return(-1);
2059 if (reader->node == NULL)
2060 return(-1);
2061 if (reader->node->type != XML_ELEMENT_NODE)
2062 return(0);
2063 node = reader->node;
2064
2065 /*
2066 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2067 * namespace name associated to "xmlns"
2068 */
2069 prop = node->properties;
2070 while (prop != NULL) {
2071 /*
2072 * One need to have
2073 * - same attribute names
2074 * - and the attribute carrying that namespace
2075 */
2076 if (xmlStrEqual(prop->name, localName) &&
2077 ((prop->ns != NULL) &&
2078 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2079 reader->curnode = (xmlNodePtr) prop;
2080 return(1);
2081 }
2082 prop = prop->next;
2083 }
2084 return(0);
2085}
2086
2087/**
2088 * xmlTextReaderMoveToFirstAttribute:
2089 * @reader: the xmlTextReaderPtr used
2090 *
2091 * Moves the position of the current instance to the first attribute
2092 * associated with the current node.
2093 *
2094 * Returns 1 in case of success, -1 in case of error, 0 if not found
2095 */
2096int
2097xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2098 if (reader == NULL)
2099 return(-1);
2100 if (reader->node == NULL)
2101 return(-1);
2102 if (reader->node->type != XML_ELEMENT_NODE)
2103 return(0);
2104
2105 if (reader->node->nsDef != NULL) {
2106 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2107 return(1);
2108 }
2109 if (reader->node->properties != NULL) {
2110 reader->curnode = (xmlNodePtr) reader->node->properties;
2111 return(1);
2112 }
2113 return(0);
2114}
2115
2116/**
2117 * xmlTextReaderMoveToNextAttribute:
2118 * @reader: the xmlTextReaderPtr used
2119 *
2120 * Moves the position of the current instance to the next attribute
2121 * associated with the current node.
2122 *
2123 * Returns 1 in case of success, -1 in case of error, 0 if not found
2124 */
2125int
2126xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2127 if (reader == NULL)
2128 return(-1);
2129 if (reader->node == NULL)
2130 return(-1);
2131 if (reader->node->type != XML_ELEMENT_NODE)
2132 return(0);
2133 if (reader->curnode == NULL)
2134 return(xmlTextReaderMoveToFirstAttribute(reader));
2135
2136 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2137 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2138 if (ns->next != NULL) {
2139 reader->curnode = (xmlNodePtr) ns->next;
2140 return(1);
2141 }
2142 if (reader->node->properties != NULL) {
2143 reader->curnode = (xmlNodePtr) reader->node->properties;
2144 return(1);
2145 }
2146 return(0);
2147 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2148 (reader->curnode->next != NULL)) {
2149 reader->curnode = reader->curnode->next;
2150 return(1);
2151 }
2152 return(0);
2153}
2154
2155/**
2156 * xmlTextReaderMoveToElement:
2157 * @reader: the xmlTextReaderPtr used
2158 *
2159 * Moves the position of the current instance to the node that
2160 * contains the current Attribute node.
2161 *
2162 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2163 */
2164int
2165xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2166 if (reader == NULL)
2167 return(-1);
2168 if (reader->node == NULL)
2169 return(-1);
2170 if (reader->node->type != XML_ELEMENT_NODE)
2171 return(0);
2172 if (reader->curnode != NULL) {
2173 reader->curnode = NULL;
2174 return(1);
2175 }
2176 return(0);
2177}
2178
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002179/**
2180 * xmlTextReaderReadAttributeValue:
2181 * @reader: the xmlTextReaderPtr used
2182 *
2183 * Parses an attribute value into one or more Text and EntityReference nodes.
2184 *
2185 * Returns 1 in case of success, 0 if the reader was not positionned on an
2186 * ttribute node or all the attribute values have been read, or -1
2187 * in case of error.
2188 */
2189int
2190xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2191 if (reader == NULL)
2192 return(-1);
2193 if (reader->node == NULL)
2194 return(-1);
2195 if (reader->curnode == NULL)
2196 return(0);
2197 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2198 if (reader->curnode->children == NULL)
2199 return(0);
2200 reader->curnode = reader->curnode->children;
2201 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2202 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2203
2204 if (reader->faketext == NULL) {
2205 reader->faketext = xmlNewDocText(reader->node->doc,
2206 ns->href);
2207 } else {
2208 if (reader->faketext->content != NULL)
2209 xmlFree(reader->faketext->content);
2210 reader->faketext->content = xmlStrdup(ns->href);
2211 }
2212 reader->curnode = reader->faketext;
2213 } else {
2214 if (reader->curnode->next == NULL)
2215 return(0);
2216 reader->curnode = reader->curnode->next;
2217 }
2218 return(1);
2219}
2220
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002221/************************************************************************
2222 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002223 * Acces API to the current node *
2224 * *
2225 ************************************************************************/
2226/**
2227 * xmlTextReaderAttributeCount:
2228 * @reader: the xmlTextReaderPtr used
2229 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002230 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002231 *
2232 * Returns 0 i no attributes, -1 in case of error or the attribute count
2233 */
2234int
2235xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2236 int ret;
2237 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002238 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002239 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002240
2241 if (reader == NULL)
2242 return(-1);
2243 if (reader->node == NULL)
2244 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002245
2246 if (reader->curnode != NULL)
2247 node = reader->curnode;
2248 else
2249 node = reader->node;
2250
2251 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002252 return(0);
2253 if ((reader->state == XML_TEXTREADER_END) ||
2254 (reader->state == XML_TEXTREADER_BACKTRACK))
2255 return(0);
2256 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002257 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002258 while (attr != NULL) {
2259 ret++;
2260 attr = attr->next;
2261 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002262 ns = node->nsDef;
2263 while (ns != NULL) {
2264 ret++;
2265 ns = ns->next;
2266 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002267 return(ret);
2268}
2269
2270/**
2271 * xmlTextReaderNodeType:
2272 * @reader: the xmlTextReaderPtr used
2273 *
2274 * Get the node type of the current node
2275 * Reference:
2276 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2277 *
2278 * Returns the xmlNodeType of the current node or -1 in case of error
2279 */
2280int
2281xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002282 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002283
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002284 if (reader == NULL)
2285 return(-1);
2286 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002287 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002288 if (reader->curnode != NULL)
2289 node = reader->curnode;
2290 else
2291 node = reader->node;
2292 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002293 case XML_ELEMENT_NODE:
2294 if ((reader->state == XML_TEXTREADER_END) ||
2295 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002296 return(XML_READER_TYPE_END_ELEMENT);
2297 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002298 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002299 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002300 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002301 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002302 if (xmlIsBlankNode(reader->node)) {
2303 if (xmlNodeGetSpacePreserve(reader->node))
2304 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2305 else
2306 return(XML_READER_TYPE_WHITESPACE);
2307 } else {
2308 return(XML_READER_TYPE_TEXT);
2309 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002310 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002311 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002312 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002313 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002314 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002315 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002316 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002317 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002318 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002319 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002320 case XML_DOCUMENT_NODE:
2321 case XML_HTML_DOCUMENT_NODE:
2322#ifdef LIBXML_DOCB_ENABLED
2323 case XML_DOCB_DOCUMENT_NODE:
2324#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002325 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002326 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002327 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002328 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002329 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002330 case XML_DOCUMENT_TYPE_NODE:
2331 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002332 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002333
2334 case XML_ELEMENT_DECL:
2335 case XML_ATTRIBUTE_DECL:
2336 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002337 case XML_XINCLUDE_START:
2338 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002339 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002340 }
2341 return(-1);
2342}
2343
2344/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002345 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002346 * @reader: the xmlTextReaderPtr used
2347 *
2348 * Check if the current node is empty
2349 *
2350 * Returns 1 if empty, 0 if not and -1 in case of error
2351 */
2352int
2353xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2354 if ((reader == NULL) || (reader->node == NULL))
2355 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002356 if (reader->node->type != XML_ELEMENT_NODE)
2357 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002358 if (reader->curnode != NULL)
2359 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002360 if (reader->node->children != NULL)
2361 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002362 if (reader->state == XML_TEXTREADER_END)
2363 return(0);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002364 return((reader->node->_private == (void *)xmlTextReaderIsEmpty) ||
2365 (reader->node->_private == (void *)xmlTextReaderIsEmptyPreserved));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002366}
2367
2368/**
2369 * xmlTextReaderLocalName:
2370 * @reader: the xmlTextReaderPtr used
2371 *
2372 * The local name of the node.
2373 *
2374 * Returns the local name or NULL if not available
2375 */
2376xmlChar *
2377xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002378 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002379 if ((reader == NULL) || (reader->node == NULL))
2380 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002381 if (reader->curnode != NULL)
2382 node = reader->curnode;
2383 else
2384 node = reader->node;
2385 if (node->type == XML_NAMESPACE_DECL) {
2386 xmlNsPtr ns = (xmlNsPtr) node;
2387 if (ns->prefix == NULL)
2388 return(xmlStrdup(BAD_CAST "xmlns"));
2389 else
2390 return(xmlStrdup(ns->prefix));
2391 }
2392 if ((node->type != XML_ELEMENT_NODE) &&
2393 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002394 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002395 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002396}
2397
2398/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002399 * xmlTextReaderConstLocalName:
2400 * @reader: the xmlTextReaderPtr used
2401 *
2402 * The local name of the node.
2403 *
2404 * Returns the local name or NULL if not available, the
2405 * string will be deallocated with the reader.
2406 */
2407const xmlChar *
2408xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2409 xmlNodePtr node;
2410 if ((reader == NULL) || (reader->node == NULL))
2411 return(NULL);
2412 if (reader->curnode != NULL)
2413 node = reader->curnode;
2414 else
2415 node = reader->node;
2416 if (node->type == XML_NAMESPACE_DECL) {
2417 xmlNsPtr ns = (xmlNsPtr) node;
2418 if (ns->prefix == NULL)
2419 return(CONSTSTR(BAD_CAST "xmlns"));
2420 else
2421 return(ns->prefix);
2422 }
2423 if ((node->type != XML_ELEMENT_NODE) &&
2424 (node->type != XML_ATTRIBUTE_NODE))
2425 return(xmlTextReaderConstName(reader));
2426 return(node->name);
2427}
2428
2429/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002430 * xmlTextReaderName:
2431 * @reader: the xmlTextReaderPtr used
2432 *
2433 * The qualified name of the node, equal to Prefix :LocalName.
2434 *
2435 * Returns the local name or NULL if not available
2436 */
2437xmlChar *
2438xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002439 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002440 xmlChar *ret;
2441
2442 if ((reader == NULL) || (reader->node == NULL))
2443 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002444 if (reader->curnode != NULL)
2445 node = reader->curnode;
2446 else
2447 node = reader->node;
2448 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002449 case XML_ELEMENT_NODE:
2450 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002451 if ((node->ns == NULL) ||
2452 (node->ns->prefix == NULL))
2453 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002454
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002455 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002456 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002457 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002458 return(ret);
2459 case XML_TEXT_NODE:
2460 return(xmlStrdup(BAD_CAST "#text"));
2461 case XML_CDATA_SECTION_NODE:
2462 return(xmlStrdup(BAD_CAST "#cdata-section"));
2463 case XML_ENTITY_NODE:
2464 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002465 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002466 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002467 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002468 case XML_COMMENT_NODE:
2469 return(xmlStrdup(BAD_CAST "#comment"));
2470 case XML_DOCUMENT_NODE:
2471 case XML_HTML_DOCUMENT_NODE:
2472#ifdef LIBXML_DOCB_ENABLED
2473 case XML_DOCB_DOCUMENT_NODE:
2474#endif
2475 return(xmlStrdup(BAD_CAST "#document"));
2476 case XML_DOCUMENT_FRAG_NODE:
2477 return(xmlStrdup(BAD_CAST "#document-fragment"));
2478 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002479 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002480 case XML_DOCUMENT_TYPE_NODE:
2481 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002482 return(xmlStrdup(node->name));
2483 case XML_NAMESPACE_DECL: {
2484 xmlNsPtr ns = (xmlNsPtr) node;
2485
2486 ret = xmlStrdup(BAD_CAST "xmlns");
2487 if (ns->prefix == NULL)
2488 return(ret);
2489 ret = xmlStrcat(ret, BAD_CAST ":");
2490 ret = xmlStrcat(ret, ns->prefix);
2491 return(ret);
2492 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002493
2494 case XML_ELEMENT_DECL:
2495 case XML_ATTRIBUTE_DECL:
2496 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002497 case XML_XINCLUDE_START:
2498 case XML_XINCLUDE_END:
2499 return(NULL);
2500 }
2501 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002502}
2503
2504/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002505 * xmlTextReaderConstName:
2506 * @reader: the xmlTextReaderPtr used
2507 *
2508 * The qualified name of the node, equal to Prefix :LocalName.
2509 *
2510 * Returns the local name or NULL if not available, the string is
2511 * deallocated with the reader.
2512 */
2513const xmlChar *
2514xmlTextReaderConstName(xmlTextReaderPtr reader) {
2515 xmlNodePtr node;
2516
2517 if ((reader == NULL) || (reader->node == NULL))
2518 return(NULL);
2519 if (reader->curnode != NULL)
2520 node = reader->curnode;
2521 else
2522 node = reader->node;
2523 switch (node->type) {
2524 case XML_ELEMENT_NODE:
2525 case XML_ATTRIBUTE_NODE:
2526 if ((node->ns == NULL) ||
2527 (node->ns->prefix == NULL))
2528 return(node->name);
2529 return(CONSTQSTR(node->ns->prefix, node->name));
2530 case XML_TEXT_NODE:
2531 return(CONSTSTR(BAD_CAST "#text"));
2532 case XML_CDATA_SECTION_NODE:
2533 return(CONSTSTR(BAD_CAST "#cdata-section"));
2534 case XML_ENTITY_NODE:
2535 case XML_ENTITY_REF_NODE:
2536 return(CONSTSTR(node->name));
2537 case XML_PI_NODE:
2538 return(CONSTSTR(node->name));
2539 case XML_COMMENT_NODE:
2540 return(CONSTSTR(BAD_CAST "#comment"));
2541 case XML_DOCUMENT_NODE:
2542 case XML_HTML_DOCUMENT_NODE:
2543#ifdef LIBXML_DOCB_ENABLED
2544 case XML_DOCB_DOCUMENT_NODE:
2545#endif
2546 return(CONSTSTR(BAD_CAST "#document"));
2547 case XML_DOCUMENT_FRAG_NODE:
2548 return(CONSTSTR(BAD_CAST "#document-fragment"));
2549 case XML_NOTATION_NODE:
2550 return(CONSTSTR(node->name));
2551 case XML_DOCUMENT_TYPE_NODE:
2552 case XML_DTD_NODE:
2553 return(CONSTSTR(node->name));
2554 case XML_NAMESPACE_DECL: {
2555 xmlNsPtr ns = (xmlNsPtr) node;
2556
2557 if (ns->prefix == NULL)
2558 return(CONSTSTR(BAD_CAST "xmlns"));
2559 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2560 }
2561
2562 case XML_ELEMENT_DECL:
2563 case XML_ATTRIBUTE_DECL:
2564 case XML_ENTITY_DECL:
2565 case XML_XINCLUDE_START:
2566 case XML_XINCLUDE_END:
2567 return(NULL);
2568 }
2569 return(NULL);
2570}
2571
2572/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002573 * xmlTextReaderPrefix:
2574 * @reader: the xmlTextReaderPtr used
2575 *
2576 * A shorthand reference to the namespace associated with the node.
2577 *
2578 * Returns the prefix or NULL if not available
2579 */
2580xmlChar *
2581xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002582 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002583 if ((reader == NULL) || (reader->node == NULL))
2584 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002585 if (reader->curnode != NULL)
2586 node = reader->curnode;
2587 else
2588 node = reader->node;
2589 if (node->type == XML_NAMESPACE_DECL) {
2590 xmlNsPtr ns = (xmlNsPtr) node;
2591 if (ns->prefix == NULL)
2592 return(NULL);
2593 return(xmlStrdup(BAD_CAST "xmlns"));
2594 }
2595 if ((node->type != XML_ELEMENT_NODE) &&
2596 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002597 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002598 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002599 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002600 return(NULL);
2601}
2602
2603/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002604 * xmlTextReaderConstPrefix:
2605 * @reader: the xmlTextReaderPtr used
2606 *
2607 * A shorthand reference to the namespace associated with the node.
2608 *
2609 * Returns the prefix or NULL if not available, the string is deallocated
2610 * with the reader.
2611 */
2612const xmlChar *
2613xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2614 xmlNodePtr node;
2615 if ((reader == NULL) || (reader->node == NULL))
2616 return(NULL);
2617 if (reader->curnode != NULL)
2618 node = reader->curnode;
2619 else
2620 node = reader->node;
2621 if (node->type == XML_NAMESPACE_DECL) {
2622 xmlNsPtr ns = (xmlNsPtr) node;
2623 if (ns->prefix == NULL)
2624 return(NULL);
2625 return(CONSTSTR(BAD_CAST "xmlns"));
2626 }
2627 if ((node->type != XML_ELEMENT_NODE) &&
2628 (node->type != XML_ATTRIBUTE_NODE))
2629 return(NULL);
2630 if ((node->ns != NULL) && (node->ns->prefix != NULL))
2631 return(CONSTSTR(node->ns->prefix));
2632 return(NULL);
2633}
2634
2635/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002636 * xmlTextReaderNamespaceUri:
2637 * @reader: the xmlTextReaderPtr used
2638 *
2639 * The URI defining the namespace associated with the node.
2640 *
2641 * Returns the namespace URI or NULL if not available
2642 */
2643xmlChar *
2644xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002645 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002646 if ((reader == NULL) || (reader->node == NULL))
2647 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002648 if (reader->curnode != NULL)
2649 node = reader->curnode;
2650 else
2651 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00002652 if (node->type == XML_NAMESPACE_DECL)
2653 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002654 if ((node->type != XML_ELEMENT_NODE) &&
2655 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002656 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002657 if (node->ns != NULL)
2658 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002659 return(NULL);
2660}
2661
2662/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002663 * xmlTextReaderConstNamespaceUri:
2664 * @reader: the xmlTextReaderPtr used
2665 *
2666 * The URI defining the namespace associated with the node.
2667 *
2668 * Returns the namespace URI or NULL if not available, the string
2669 * will be deallocated with the reader
2670 */
2671const xmlChar *
2672xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
2673 xmlNodePtr node;
2674 if ((reader == NULL) || (reader->node == NULL))
2675 return(NULL);
2676 if (reader->curnode != NULL)
2677 node = reader->curnode;
2678 else
2679 node = reader->node;
2680 if (node->type == XML_NAMESPACE_DECL)
2681 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
2682 if ((node->type != XML_ELEMENT_NODE) &&
2683 (node->type != XML_ATTRIBUTE_NODE))
2684 return(NULL);
2685 if (node->ns != NULL)
2686 return(CONSTSTR(node->ns->href));
2687 return(NULL);
2688}
2689
2690/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002691 * xmlTextReaderBaseUri:
2692 * @reader: the xmlTextReaderPtr used
2693 *
2694 * The base URI of the node.
2695 *
2696 * Returns the base URI or NULL if not available
2697 */
2698xmlChar *
2699xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
2700 if ((reader == NULL) || (reader->node == NULL))
2701 return(NULL);
2702 return(xmlNodeGetBase(NULL, reader->node));
2703}
2704
2705/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002706 * xmlTextReaderConstBaseUri:
2707 * @reader: the xmlTextReaderPtr used
2708 *
2709 * The base URI of the node.
2710 *
2711 * Returns the base URI or NULL if not available, the string
2712 * will be deallocated with the reader
2713 */
2714const xmlChar *
2715xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
2716 xmlChar *tmp;
2717 const xmlChar *ret;
2718
2719 if ((reader == NULL) || (reader->node == NULL))
2720 return(NULL);
2721 tmp = xmlNodeGetBase(NULL, reader->node);
2722 if (tmp == NULL)
2723 return(NULL);
2724 ret = CONSTSTR(tmp);
2725 xmlFree(tmp);
2726 return(ret);
2727}
2728
2729/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002730 * xmlTextReaderDepth:
2731 * @reader: the xmlTextReaderPtr used
2732 *
2733 * The depth of the node in the tree.
2734 *
2735 * Returns the depth or -1 in case of error
2736 */
2737int
2738xmlTextReaderDepth(xmlTextReaderPtr reader) {
2739 if (reader == NULL)
2740 return(-1);
2741 if (reader->node == NULL)
2742 return(0);
2743
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002744 if (reader->curnode != NULL) {
2745 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
2746 (reader->curnode->type == XML_NAMESPACE_DECL))
2747 return(reader->depth + 1);
2748 return(reader->depth + 2);
2749 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002750 return(reader->depth);
2751}
2752
2753/**
2754 * xmlTextReaderHasAttributes:
2755 * @reader: the xmlTextReaderPtr used
2756 *
2757 * Whether the node has attributes.
2758 *
2759 * Returns 1 if true, 0 if false, and -1 in case or error
2760 */
2761int
2762xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002763 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002764 if (reader == NULL)
2765 return(-1);
2766 if (reader->node == NULL)
2767 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002768 if (reader->curnode != NULL)
2769 node = reader->curnode;
2770 else
2771 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002772
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002773 if ((node->type == XML_ELEMENT_NODE) &&
2774 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002775 return(1);
2776 /* TODO: handle the xmlDecl */
2777 return(0);
2778}
2779
2780/**
2781 * xmlTextReaderHasValue:
2782 * @reader: the xmlTextReaderPtr used
2783 *
2784 * Whether the node can have a text value.
2785 *
2786 * Returns 1 if true, 0 if false, and -1 in case or error
2787 */
2788int
2789xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002790 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002791 if (reader == NULL)
2792 return(-1);
2793 if (reader->node == NULL)
2794 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002795 if (reader->curnode != NULL)
2796 node = reader->curnode;
2797 else
2798 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002799
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002800 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002801 case XML_ATTRIBUTE_NODE:
2802 case XML_TEXT_NODE:
2803 case XML_CDATA_SECTION_NODE:
2804 case XML_PI_NODE:
2805 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00002806 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002807 return(1);
2808 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002809 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002810 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002811 return(0);
2812}
2813
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002814/**
2815 * xmlTextReaderValue:
2816 * @reader: the xmlTextReaderPtr used
2817 *
2818 * Provides the text value of the node if present
2819 *
2820 * Returns the string or NULL if not available. The retsult must be deallocated
2821 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002822 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002823xmlChar *
2824xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002825 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002826 if (reader == NULL)
2827 return(NULL);
2828 if (reader->node == NULL)
2829 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002830 if (reader->curnode != NULL)
2831 node = reader->curnode;
2832 else
2833 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002834
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002835 switch (node->type) {
2836 case XML_NAMESPACE_DECL:
2837 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002838 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002839 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002840
2841 if (attr->parent != NULL)
2842 return (xmlNodeListGetString
2843 (attr->parent->doc, attr->children, 1));
2844 else
2845 return (xmlNodeListGetString(NULL, attr->children, 1));
2846 break;
2847 }
2848 case XML_TEXT_NODE:
2849 case XML_CDATA_SECTION_NODE:
2850 case XML_PI_NODE:
2851 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002852 if (node->content != NULL)
2853 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002854 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002855 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002856 }
2857 return(NULL);
2858}
2859
2860/**
2861 * xmlTextReaderIsDefault:
2862 * @reader: the xmlTextReaderPtr used
2863 *
2864 * Whether an Attribute node was generated from the default value
2865 * defined in the DTD or schema.
2866 *
2867 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
2868 */
2869int
2870xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
2871 if (reader == NULL)
2872 return(-1);
2873 return(0);
2874}
2875
2876/**
2877 * xmlTextReaderQuoteChar:
2878 * @reader: the xmlTextReaderPtr used
2879 *
2880 * The quotation mark character used to enclose the value of an attribute.
2881 *
2882 * Returns " or ' and -1 in case of error
2883 */
2884int
2885xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
2886 if (reader == NULL)
2887 return(-1);
2888 /* TODO maybe lookup the attribute value for " first */
2889 return((int) '"');
2890}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002891
2892/**
2893 * xmlTextReaderXmlLang:
2894 * @reader: the xmlTextReaderPtr used
2895 *
2896 * The xml:lang scope within which the node resides.
2897 *
2898 * Returns the xml:lang value or NULL if none exists.
2899 */
2900xmlChar *
2901xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
2902 if (reader == NULL)
2903 return(NULL);
2904 if (reader->node == NULL)
2905 return(NULL);
2906 return(xmlNodeGetLang(reader->node));
2907}
2908
Daniel Veillard67df8092002-12-16 22:04:11 +00002909/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002910 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00002911 * @reader: the xmlTextReaderPtr used
2912 *
2913 * The xml:lang scope within which the node resides.
2914 *
2915 * Returns the xml:lang value or NULL if none exists.
2916 */
2917const xmlChar *
2918xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
2919 xmlChar *tmp;
2920 const xmlChar *ret;
2921
2922 if (reader == NULL)
2923 return(NULL);
2924 if (reader->node == NULL)
2925 return(NULL);
2926 tmp = xmlNodeGetLang(reader->node);
2927 if (tmp == NULL)
2928 return(NULL);
2929 ret = CONSTSTR(tmp);
2930 xmlFree(tmp);
2931 return(ret);
2932}
2933
2934/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00002935 * xmlTextReaderConstString:
2936 * @reader: the xmlTextReaderPtr used
2937 * @str: the string to intern.
2938 *
2939 * Get an interned string from the reader, allows for example to
2940 * speedup string name comparisons
2941 *
2942 * Returns an interned copy of the string or NULL in case of error. The
2943 * string will be deallocated with the reader.
2944 */
2945const xmlChar *
2946xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
2947 if (reader == NULL)
2948 return(NULL);
2949 return(CONSTSTR(str));
2950}
2951
2952/**
Daniel Veillard67df8092002-12-16 22:04:11 +00002953 * xmlTextReaderNormalization:
2954 * @reader: the xmlTextReaderPtr used
2955 *
2956 * The value indicating whether to normalize white space and attribute values.
2957 * Since attribute value and end of line normalizations are a MUST in the XML
2958 * specification only the value true is accepted. The broken bahaviour of
2959 * accepting out of range character entities like &#0; is of course not
2960 * supported either.
2961 *
2962 * Returns 1 or -1 in case of error.
2963 */
2964int
2965xmlTextReaderNormalization(xmlTextReaderPtr reader) {
2966 if (reader == NULL)
2967 return(-1);
2968 return(1);
2969}
2970
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002971/************************************************************************
2972 * *
2973 * Extensions to the base APIs *
2974 * *
2975 ************************************************************************/
2976
2977/**
2978 * xmlTextReaderSetParserProp:
2979 * @reader: the xmlTextReaderPtr used
2980 * @prop: the xmlParserProperties to set
2981 * @value: usually 0 or 1 to (de)activate it
2982 *
2983 * Change the parser processing behaviour by changing some of its internal
2984 * properties. Note that some properties can only be changed before any
2985 * read has been done.
2986 *
2987 * Returns 0 if the call was successful, or -1 in case of error
2988 */
2989int
2990xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
2991 xmlParserProperties p = (xmlParserProperties) prop;
2992 xmlParserCtxtPtr ctxt;
2993
2994 if ((reader == NULL) || (reader->ctxt == NULL))
2995 return(-1);
2996 ctxt = reader->ctxt;
2997
2998 switch (p) {
2999 case XML_PARSER_LOADDTD:
3000 if (value != 0) {
3001 if (ctxt->loadsubset == 0) {
3002 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3003 return(-1);
3004 ctxt->loadsubset = XML_DETECT_IDS;
3005 }
3006 } else {
3007 ctxt->loadsubset = 0;
3008 }
3009 return(0);
3010 case XML_PARSER_DEFAULTATTRS:
3011 if (value != 0) {
3012 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3013 } else {
3014 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3015 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3016 }
3017 return(0);
3018 case XML_PARSER_VALIDATE:
3019 if (value != 0) {
3020 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003021 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003022 } else {
3023 ctxt->validate = 0;
3024 }
3025 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003026 case XML_PARSER_SUBST_ENTITIES:
3027 if (value != 0) {
3028 ctxt->replaceEntities = 1;
3029 } else {
3030 ctxt->replaceEntities = 0;
3031 }
3032 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003033 }
3034 return(-1);
3035}
3036
3037/**
3038 * xmlTextReaderGetParserProp:
3039 * @reader: the xmlTextReaderPtr used
3040 * @prop: the xmlParserProperties to get
3041 *
3042 * Read the parser internal property.
3043 *
3044 * Returns the value, usually 0 or 1, or -1 in case of error.
3045 */
3046int
3047xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3048 xmlParserProperties p = (xmlParserProperties) prop;
3049 xmlParserCtxtPtr ctxt;
3050
3051 if ((reader == NULL) || (reader->ctxt == NULL))
3052 return(-1);
3053 ctxt = reader->ctxt;
3054
3055 switch (p) {
3056 case XML_PARSER_LOADDTD:
3057 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3058 return(1);
3059 return(0);
3060 case XML_PARSER_DEFAULTATTRS:
3061 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3062 return(1);
3063 return(0);
3064 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003065 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003066 case XML_PARSER_SUBST_ENTITIES:
3067 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003068 }
3069 return(-1);
3070}
3071
Daniel Veillarde18fc182002-12-28 22:56:33 +00003072/**
3073 * xmlTextReaderCurrentNode:
3074 * @reader: the xmlTextReaderPtr used
3075 *
3076 * Hacking interface allowing to get the xmlNodePtr correponding to the
3077 * current node being accessed by the xmlTextReader. This is dangerous
3078 * because the underlying node may be destroyed on the next Reads.
3079 *
3080 * Returns the xmlNodePtr or NULL in case of error.
3081 */
3082xmlNodePtr
3083xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3084 if (reader == NULL)
3085 return(NULL);
3086
3087 if (reader->curnode != NULL)
3088 return(reader->curnode);
3089 return(reader->node);
3090}
3091
3092/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003093 * xmlTextReaderPreserve:
3094 * @reader: the xmlTextReaderPtr used
3095 *
3096 *
3097 * current node being accessed by the xmlTextReader. This is dangerous
3098 * because the underlying node may be destroyed on the next Reads.
3099 *
3100 * Returns the xmlNodePtr or NULL in case of error.
3101 */
3102xmlNodePtr
3103xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3104 xmlNodePtr cur, parent;
3105
3106 if (reader == NULL)
3107 return(NULL);
3108
3109 if (reader->curnode != NULL)
3110 cur = reader->curnode;
3111 else
3112 cur = reader->node;
3113 if (cur == NULL)
3114 return(NULL);
3115 if (cur->_private == (void *)xmlTextReaderIsEmpty)
3116 cur->_private = (void *)xmlTextReaderIsEmptyPreserved;
3117 else
3118 cur->_private = (void *)xmlTextReaderIsPreserved;
3119
3120 parent = cur->parent;;
3121 while (parent != NULL) {
3122 parent->_private = (void *)xmlTextReaderIsPreserved;
3123 parent = parent->parent;
3124 }
3125 return(cur);
3126}
3127
3128/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003129 * xmlTextReaderCurrentDoc:
3130 * @reader: the xmlTextReaderPtr used
3131 *
3132 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003133 * current document being accessed by the xmlTextReader.
3134 * NOTE: as a result of this call, the reader will not destroy the
3135 * associated XML document and calling xmlFreeDoc() on the result
3136 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003137 *
3138 * Returns the xmlDocPtr or NULL in case of error.
3139 */
3140xmlDocPtr
3141xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003142 if ((reader == NULL) || (reader->ctxt == NULL) ||
3143 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003144 return(NULL);
3145
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003146 reader->preserve = 1;
3147 if ((reader->ctxt->myDoc->dict != NULL) &&
3148 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3149 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003150 return(reader->ctxt->myDoc);
3151}
3152
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003153#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003154/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003155 * xmlTextReaderRelaxNGSetSchema:
3156 * @reader: the xmlTextReaderPtr used
3157 * @schema: a precompiled RelaxNG schema
3158 *
3159 * Use RelaxNG to validate the document as it is processed.
3160 * Activation is only possible before the first Read().
3161 * if @schema is NULL, then RelaxNG validation is desactivated.
3162 @ The @schema should not be freed until the reader is deallocated
3163 * or its use has been deactivated.
3164 *
3165 * Returns 0 in case the RelaxNG validation could be (des)activated and
3166 * -1 in case of error.
3167 */
3168int
3169xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3170 if (schema == NULL) {
3171 if (reader->rngSchemas != NULL) {
3172 xmlRelaxNGFree(reader->rngSchemas);
3173 reader->rngSchemas = NULL;
3174 }
3175 if (reader->rngValidCtxt != NULL) {
3176 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3177 reader->rngValidCtxt = NULL;
3178 }
3179 return(0);
3180 }
3181 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3182 return(-1);
3183 if (reader->rngSchemas != NULL) {
3184 xmlRelaxNGFree(reader->rngSchemas);
3185 reader->rngSchemas = NULL;
3186 }
3187 if (reader->rngValidCtxt != NULL) {
3188 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3189 reader->rngValidCtxt = NULL;
3190 }
3191 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3192 if (reader->rngValidCtxt == NULL)
3193 return(-1);
3194 if (reader->errorFunc != NULL) {
3195 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3196 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3197 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3198 reader->errorFuncArg);
3199 }
3200 reader->rngValidErrors = 0;
3201 reader->rngFullNode = NULL;
3202 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3203 return(0);
3204}
3205
3206/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003207 * xmlTextReaderRelaxNGValidate:
3208 * @reader: the xmlTextReaderPtr used
3209 * @rng: the path to a RelaxNG schema or NULL
3210 *
3211 * Use RelaxNG to validate the document as it is processed.
3212 * Activation is only possible before the first Read().
3213 * if @rng is NULL, then RelaxNG validation is desactivated.
3214 *
3215 * Returns 0 in case the RelaxNG validation could be (des)activated and
3216 * -1 in case of error.
3217 */
3218int
3219xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3220 xmlRelaxNGParserCtxtPtr ctxt;
3221
3222 if (reader == NULL)
3223 return(-1);
3224
3225 if (rng == NULL) {
3226 if (reader->rngSchemas != NULL) {
3227 xmlRelaxNGFree(reader->rngSchemas);
3228 reader->rngSchemas = NULL;
3229 }
3230 if (reader->rngValidCtxt != NULL) {
3231 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3232 reader->rngValidCtxt = NULL;
3233 }
3234 return(0);
3235 }
3236 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3237 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003238 if (reader->rngSchemas != NULL) {
3239 xmlRelaxNGFree(reader->rngSchemas);
3240 reader->rngSchemas = NULL;
3241 }
3242 if (reader->rngValidCtxt != NULL) {
3243 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3244 reader->rngValidCtxt = NULL;
3245 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003246 ctxt = xmlRelaxNGNewParserCtxt(rng);
3247 if (reader->errorFunc != NULL) {
3248 xmlRelaxNGSetParserErrors(ctxt,
3249 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3250 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3251 reader->errorFuncArg);
3252 }
3253 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3254 xmlRelaxNGFreeParserCtxt(ctxt);
3255 if (reader->rngSchemas == NULL)
3256 return(-1);
3257 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3258 if (reader->rngValidCtxt == NULL)
3259 return(-1);
3260 if (reader->errorFunc != NULL) {
3261 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3262 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3263 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3264 reader->errorFuncArg);
3265 }
3266 reader->rngValidErrors = 0;
3267 reader->rngFullNode = NULL;
3268 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3269 return(0);
3270}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003271#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003272
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003273/************************************************************************
3274 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003275 * Error Handling Extensions *
3276 * *
3277 ************************************************************************/
3278
3279/* helper to build a xmlMalloc'ed string from a format and va_list */
3280static char *
3281xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3282 int size;
3283 int chars;
3284 char *larger;
3285 char *str;
3286
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003287 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003288 if (str == NULL) {
3289 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3290 return NULL;
3291 }
3292
3293 size = 150;
3294
3295 while (1) {
3296 chars = vsnprintf(str, size, msg, ap);
3297 if ((chars > -1) && (chars < size))
3298 break;
3299 if (chars > -1)
3300 size += chars + 1;
3301 else
3302 size += 100;
3303 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3304 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3305 xmlFree(str);
3306 return NULL;
3307 }
3308 str = larger;
3309 }
3310
3311 return str;
3312}
3313
Daniel Veillard417be3a2003-01-20 21:26:34 +00003314/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003315 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003316 * @locator: the xmlTextReaderLocatorPtr used
3317 *
3318 * Obtain the line number for the given locator.
3319 *
3320 * Returns the line number or -1 in case of error.
3321 */
3322int
3323xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3324 /* we know that locator is a xmlParserCtxtPtr */
3325 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3326 int ret = -1;
3327
3328 if (ctx->node != NULL) {
3329 ret = xmlGetLineNo(ctx->node);
3330 }
3331 else {
3332 /* inspired from error.c */
3333 xmlParserInputPtr input;
3334 input = ctx->input;
3335 if ((input->filename == NULL) && (ctx->inputNr > 1))
3336 input = ctx->inputTab[ctx->inputNr - 2];
3337 if (input != NULL) {
3338 ret = input->line;
3339 }
3340 else {
3341 ret = -1;
3342 }
3343 }
3344
3345 return ret;
3346}
3347
3348/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003349 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003350 * @locator: the xmlTextReaderLocatorPtr used
3351 *
3352 * Obtain the base URI for the given locator.
3353 *
3354 * Returns the base URI or NULL in case of error.
3355 */
3356xmlChar *
3357xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3358 /* we know that locator is a xmlParserCtxtPtr */
3359 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3360 xmlChar *ret = NULL;
3361
3362 if (ctx->node != NULL) {
3363 ret = xmlNodeGetBase(NULL,ctx->node);
3364 }
3365 else {
3366 /* inspired from error.c */
3367 xmlParserInputPtr input;
3368 input = ctx->input;
3369 if ((input->filename == NULL) && (ctx->inputNr > 1))
3370 input = ctx->inputTab[ctx->inputNr - 2];
3371 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003372 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003373 }
3374 else {
3375 ret = NULL;
3376 }
3377 }
3378
3379 return ret;
3380}
3381
Daniel Veillard26f70262003-01-16 22:45:08 +00003382static void
William M. Brack899e64a2003-09-26 18:03:42 +00003383xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003384 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3385 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3386
3387 if (str != NULL) {
3388 reader->errorFunc(reader->errorFuncArg,
3389 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003390 severity,
3391 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003392 xmlFree(str);
3393 }
3394}
3395
3396static void
3397xmlTextReaderError(void *ctxt, const char *msg, ...) {
3398 va_list ap;
3399
3400 va_start(ap,msg);
3401 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003402 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003403 xmlTextReaderBuildMessage(msg,ap));
3404 va_end(ap);
3405
3406}
3407
3408static void
3409xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3410 va_list ap;
3411
3412 va_start(ap,msg);
3413 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003414 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003415 xmlTextReaderBuildMessage(msg,ap));
3416 va_end(ap);
3417}
3418
3419static void
3420xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3421 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003422 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003423
Daniel Veillard417be3a2003-01-20 21:26:34 +00003424 if ((len > 1) && (msg[len - 2] != ':')) {
3425 /*
3426 * some callbacks only report locator information:
3427 * skip them (mimicking behaviour in error.c)
3428 */
3429 va_start(ap,msg);
3430 xmlTextReaderGenericError(ctxt,
3431 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3432 xmlTextReaderBuildMessage(msg,ap));
3433 va_end(ap);
3434 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003435}
3436
3437static void
3438xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3439 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003440 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003441
Daniel Veillard417be3a2003-01-20 21:26:34 +00003442 if ((len != 0) && (msg[len - 1] != ':')) {
3443 /*
3444 * some callbacks only report locator information:
3445 * skip them (mimicking behaviour in error.c)
3446 */
3447 va_start(ap,msg);
3448 xmlTextReaderGenericError(ctxt,
3449 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3450 xmlTextReaderBuildMessage(msg,ap));
3451 va_end(ap);
3452 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003453}
3454
3455/**
3456 * xmlTextReaderSetErrorHandler:
3457 * @reader: the xmlTextReaderPtr used
3458 * @f: the callback function to call on error and warnings
3459 * @arg: a user argument to pass to the callback function
3460 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003461 * Register a callback function that will be called on error and warnings.
3462 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003463 * If @f is NULL, the default error and warning handlers are restored.
3464 */
3465void
3466xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3467 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003468 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003469 if (f != NULL) {
3470 reader->ctxt->sax->error = xmlTextReaderError;
3471 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3472 reader->ctxt->sax->warning = xmlTextReaderWarning;
3473 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3474 reader->errorFunc = f;
3475 reader->errorFuncArg = arg;
3476 }
3477 else {
3478 /* restore defaults */
3479 reader->ctxt->sax->error = xmlParserError;
3480 reader->ctxt->vctxt.error = xmlParserValidityError;
3481 reader->ctxt->sax->warning = xmlParserWarning;
3482 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3483 reader->errorFunc = NULL;
3484 reader->errorFuncArg = NULL;
3485 }
3486}
3487
Daniel Veillard417be3a2003-01-20 21:26:34 +00003488/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003489 * xmlTextReaderIsValid:
3490 * @reader: the xmlTextReaderPtr used
3491 *
3492 * Retrieve the validity status from the parser context
3493 *
3494 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3495 */
3496int
3497xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003498 if (reader == NULL) return(-1);
3499#ifdef LIBXML_SCHEMAS_ENABLED
3500 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3501 return(reader->rngValidErrors == 0);
3502#endif
3503 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3504 (reader->ctxt != NULL))
3505 return(reader->ctxt->valid);
3506 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003507}
3508
3509/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003510 * xmlTextReaderGetErrorHandler:
3511 * @reader: the xmlTextReaderPtr used
3512 * @f: the callback function or NULL is no callback has been registered
3513 * @arg: a user argument
3514 *
3515 * Retrieve the error callback function and user argument.
3516 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003517void
3518xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3519 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003520 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003521 *f = reader->errorFunc;
3522 *arg = reader->errorFuncArg;
3523}
3524
3525/************************************************************************
3526 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003527 * Utilities *
3528 * *
3529 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00003530#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003531/**
3532 * xmlBase64Decode:
3533 * @in: the input buffer
3534 * @inlen: the size of the input (in), the size read from it (out)
3535 * @to: the output buffer
3536 * @tolen: the size of the output (in), the size written to (out)
3537 *
3538 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00003539 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003540 *
3541 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
3542 * 2 if there wasn't enough space on the output or -1 in case of error.
3543 */
3544static int
3545xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
3546 unsigned char *to, unsigned long *tolen) {
3547 unsigned long incur; /* current index in in[] */
3548 unsigned long inblk; /* last block index in in[] */
3549 unsigned long outcur; /* current index in out[] */
3550 unsigned long inmax; /* size of in[] */
3551 unsigned long outmax; /* size of out[] */
3552 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00003553 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003554 int nbintmp; /* number of byte in intmp[] */
3555 int is_ignore; /* cur should be ignored */
3556 int is_end = 0; /* the end of the base64 was found */
3557 int retval = 1;
3558 int i;
3559
3560 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
3561 return(-1);
3562
3563 incur = 0;
3564 inblk = 0;
3565 outcur = 0;
3566 inmax = *inlen;
3567 outmax = *tolen;
3568 nbintmp = 0;
3569
3570 while (1) {
3571 if (incur >= inmax)
3572 break;
3573 cur = in[incur++];
3574 is_ignore = 0;
3575 if ((cur >= 'A') && (cur <= 'Z'))
3576 cur = cur - 'A';
3577 else if ((cur >= 'a') && (cur <= 'z'))
3578 cur = cur - 'a' + 26;
3579 else if ((cur >= '0') && (cur <= '9'))
3580 cur = cur - '0' + 52;
3581 else if (cur == '+')
3582 cur = 62;
3583 else if (cur == '/')
3584 cur = 63;
3585 else if (cur == '.')
3586 cur = 0;
3587 else if (cur == '=') /*no op , end of the base64 stream */
3588 is_end = 1;
3589 else {
3590 is_ignore = 1;
3591 if (nbintmp == 0)
3592 inblk = incur;
3593 }
3594
3595 if (!is_ignore) {
3596 int nbouttmp = 3;
3597 int is_break = 0;
3598
3599 if (is_end) {
3600 if (nbintmp == 0)
3601 break;
3602 if ((nbintmp == 1) || (nbintmp == 2))
3603 nbouttmp = 1;
3604 else
3605 nbouttmp = 2;
3606 nbintmp = 3;
3607 is_break = 1;
3608 }
3609 intmp[nbintmp++] = cur;
3610 /*
3611 * if intmp is full, push the 4byte sequence as a 3 byte
3612 * sequence out
3613 */
3614 if (nbintmp == 4) {
3615 nbintmp = 0;
3616 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
3617 outtmp[1] =
3618 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
3619 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
3620 if (outcur + 3 >= outmax) {
3621 retval = 2;
3622 break;
3623 }
3624
3625 for (i = 0; i < nbouttmp; i++)
3626 to[outcur++] = outtmp[i];
3627 inblk = incur;
3628 }
3629
3630 if (is_break) {
3631 retval = 0;
3632 break;
3633 }
3634 }
3635 }
3636
3637 *tolen = outcur;
3638 *inlen = inblk;
3639 return (retval);
3640}
3641
3642/*
3643 * Test routine for the xmlBase64Decode function
3644 */
3645#if 0
3646int main(int argc, char **argv) {
3647 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
3648 char output[100];
3649 char output2[100];
3650 char output3[100];
3651 unsigned long inlen = strlen(input);
3652 unsigned long outlen = 100;
3653 int ret;
3654 unsigned long cons, tmp, tmp2, prod;
3655
3656 /*
3657 * Direct
3658 */
3659 ret = xmlBase64Decode(input, &inlen, output, &outlen);
3660
3661 output[outlen] = 0;
3662 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
3663
3664 /*
3665 * output chunking
3666 */
3667 cons = 0;
3668 prod = 0;
3669 while (cons < inlen) {
3670 tmp = 5;
3671 tmp2 = inlen - cons;
3672
3673 printf("%ld %ld\n", cons, prod);
3674 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
3675 cons += tmp2;
3676 prod += tmp;
3677 printf("%ld %ld\n", cons, prod);
3678 }
3679 output2[outlen] = 0;
3680 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
3681
3682 /*
3683 * input chunking
3684 */
3685 cons = 0;
3686 prod = 0;
3687 while (cons < inlen) {
3688 tmp = 100 - prod;
3689 tmp2 = inlen - cons;
3690 if (tmp2 > 5)
3691 tmp2 = 5;
3692
3693 printf("%ld %ld\n", cons, prod);
3694 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
3695 cons += tmp2;
3696 prod += tmp;
3697 printf("%ld %ld\n", cons, prod);
3698 }
3699 output3[outlen] = 0;
3700 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
3701 return(0);
3702
3703}
3704#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00003705#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00003706#endif /* LIBXML_READER_ENABLED */