blob: 1f1176b6af5428c8f54f8baf99ce7443ff264fbd [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard7704fb12003-01-03 16:19:51 +000015 * - provide an API to preserve part of the tree
16 * - Streaming XInclude support
Daniel Veillard067bae52003-01-05 01:27:54 +000017 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000018 * - setting(s) for NoBlanks
19 * - performances and tuning ...
20 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#define IN_LIBXML
22#include "libxml.h"
23
Daniel Veillard81273902003-09-30 00:43:48 +000024#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000026#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000027
28#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#include <libxml/xmlmemory.h>
36#include <libxml/xmlIO.h>
37#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000038#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000039#include <libxml/relaxng.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000040
41/* #define DEBUG_CALLBACKS */
42/* #define DEBUG_READER */
43
44/**
45 * TODO:
46 *
47 * macro to flag unimplemented blocks
48 */
49#define TODO \
50 xmlGenericError(xmlGenericErrorContext, \
51 "Unimplemented block at %s:%d\n", \
52 __FILE__, __LINE__);
53
54#ifdef DEBUG_READER
55#define DUMP_READER xmlTextReaderDebug(reader);
56#else
57#define DUMP_READER
58#endif
59
Daniel Veillarda880b122003-04-21 21:36:41 +000060#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000061/************************************************************************
62 * *
63 * The parser: maps the Text Reader API on top of the existing *
64 * parsing routines building a tree *
65 * *
66 ************************************************************************/
67
68#define XML_TEXTREADER_INPUT 1
69#define XML_TEXTREADER_CTXT 2
70
71typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000072 XML_TEXTREADER_MODE_INITIAL = 0,
73 XML_TEXTREADER_MODE_INTERACTIVE = 1,
74 XML_TEXTREADER_MODE_ERROR = 2,
75 XML_TEXTREADER_MODE_EOF =3,
76 XML_TEXTREADER_MODE_CLOSED = 4,
77 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000078} xmlTextReaderMode;
79
80typedef enum {
81 XML_TEXTREADER_NONE = -1,
82 XML_TEXTREADER_START= 0,
83 XML_TEXTREADER_ELEMENT= 1,
84 XML_TEXTREADER_END= 2,
85 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000086 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000087 XML_TEXTREADER_DONE= 5,
88 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000089} xmlTextReaderState;
90
Daniel Veillardf4e55762003-04-15 23:32:22 +000091typedef enum {
92 XML_TEXTREADER_NOT_VALIDATE = 0,
93 XML_TEXTREADER_VALIDATE_DTD = 1,
94 XML_TEXTREADER_VALIDATE_RNG = 2
95} xmlTextReaderValidate;
96
Daniel Veillarde1ca5032002-12-09 14:13:43 +000097struct _xmlTextReader {
98 int mode; /* the parsing mode */
Daniel Veillardf4e55762003-04-15 23:32:22 +000099 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000100 int allocs; /* what structure were deallocated */
101 xmlTextReaderState state;
102 xmlParserCtxtPtr ctxt; /* the parser context */
103 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
104 xmlParserInputBufferPtr input; /* the input */
105 startElementSAXFunc startElement;/* initial SAX callbacks */
106 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000107 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000108 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000109 charactersSAXFunc characters;
110 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000111 unsigned int base; /* base of the segment in the input */
112 unsigned int cur; /* current position in the input */
113 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000114 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000115 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000116 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000117 int preserve;/* preserve the resulting document */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000118
119 /* entity stack when traversing entities content */
120 xmlNodePtr ent; /* Current Entity Ref Node */
121 int entNr; /* Depth of the entities stack */
122 int entMax; /* Max depth of the entities stack */
123 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000124
125 /* error handling */
126 xmlTextReaderErrorFunc errorFunc; /* callback function */
127 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000128
129#ifdef LIBXML_SCHEMAS_ENABLED
130 /* Handling of RelaxNG validation */
131 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
132 xmlRelaxNGValidCtxtPtr rngValidCtxt; /* The Relax NG validation context */
133 int rngValidErrors; /* The number of errors detected */
134 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
135#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000136};
137
Daniel Veillard067bae52003-01-05 01:27:54 +0000138static const char *xmlTextReaderIsEmpty = "This element is empty";
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000139static const char *xmlTextReaderIsEmptyPreserved = "Preserve this element";
140static const char *xmlTextReaderIsPreserved = "Preserve this element";
Daniel Veillard067bae52003-01-05 01:27:54 +0000141
Daniel Veillarde72c5082003-09-19 12:44:05 +0000142/**
143 * CONSTSTR:
144 *
145 * Macro used to return an interned string
146 */
147#define CONSTSTR(str) xmlDictLookup(reader->ctxt->dict, (str), -1)
148#define CONSTQSTR(p, str) xmlDictQLookup(reader->ctxt->dict, (p), (str))
149
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000150/************************************************************************
151 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000152 * Our own version of the freeing routines as we recycle nodes *
153 * *
154 ************************************************************************/
155/**
156 * DICT_FREE:
157 * @str: a string
158 *
159 * Free a string if it is not owned by the "dict" dictionnary in the
160 * current scope
161 */
162#define DICT_FREE(str) \
163 if ((str) && ((!dict) || \
164 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
165 xmlFree((char *)(str));
166
167static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
168static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
169
170/**
171 * xmlTextReaderFreeProp:
172 * @reader: the xmlTextReaderPtr used
173 * @cur: the node
174 *
175 * Free a node.
176 */
177static void
178xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
179 xmlDictPtr dict;
180
181 dict = reader->ctxt->dict;
182 if (cur == NULL) return;
183
184 /* Check for ID removal -> leading to invalid references ! */
185 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
186 ((cur->parent->doc->intSubset != NULL) ||
187 (cur->parent->doc->extSubset != NULL))) {
188 if (xmlIsID(cur->parent->doc, cur->parent, cur))
189 xmlRemoveID(cur->parent->doc, cur);
190 }
191 if (cur->children != NULL)
192 xmlTextReaderFreeNodeList(reader, cur->children);
193
194 DICT_FREE(cur->name);
195 if ((reader != NULL) && (reader->ctxt != NULL) &&
196 (reader->ctxt->freeAttrsNr < 100)) {
197 cur->next = reader->ctxt->freeAttrs;
198 reader->ctxt->freeAttrs = cur;
199 reader->ctxt->freeAttrsNr++;
200 } else {
201 xmlFree(cur);
202 }
203}
204
205/**
206 * xmlTextReaderFreePropList:
207 * @reader: the xmlTextReaderPtr used
208 * @cur: the first property in the list
209 *
210 * Free a property and all its siblings, all the children are freed too.
211 */
212static void
213xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
214 xmlAttrPtr next;
215 if (cur == NULL) return;
216 while (cur != NULL) {
217 next = cur->next;
218 xmlTextReaderFreeProp(reader, cur);
219 cur = next;
220 }
221}
222
223/**
224 * xmlTextReaderFreeNodeList:
225 * @reader: the xmlTextReaderPtr used
226 * @cur: the first node in the list
227 *
228 * Free a node and all its siblings, this is a recursive behaviour, all
229 * the children are freed too.
230 */
231static void
232xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
233 xmlNodePtr next;
234 xmlDictPtr dict;
235
236 dict = reader->ctxt->dict;
237 if (cur == NULL) return;
238 if (cur->type == XML_NAMESPACE_DECL) {
239 xmlFreeNsList((xmlNsPtr) cur);
240 return;
241 }
242 if ((cur->type == XML_DOCUMENT_NODE) ||
243 (cur->type == XML_HTML_DOCUMENT_NODE)) {
244 xmlFreeDoc((xmlDocPtr) cur);
245 return;
246 }
247 while (cur != NULL) {
248 next = cur->next;
249 /* unroll to speed up freeing the document */
250 if (cur->type != XML_DTD_NODE) {
251
252 if ((cur->children != NULL) &&
253 (cur->type != XML_ENTITY_REF_NODE))
254 xmlTextReaderFreeNodeList(reader, cur->children);
255 if (((cur->type == XML_ELEMENT_NODE) ||
256 (cur->type == XML_XINCLUDE_START) ||
257 (cur->type == XML_XINCLUDE_END)) &&
258 (cur->properties != NULL))
259 xmlTextReaderFreePropList(reader, cur->properties);
260 if ((cur->type != XML_ELEMENT_NODE) &&
261 (cur->type != XML_XINCLUDE_START) &&
262 (cur->type != XML_XINCLUDE_END) &&
263 (cur->type != XML_ENTITY_REF_NODE)) {
264 DICT_FREE(cur->content);
265 }
266 if (((cur->type == XML_ELEMENT_NODE) ||
267 (cur->type == XML_XINCLUDE_START) ||
268 (cur->type == XML_XINCLUDE_END)) &&
269 (cur->nsDef != NULL))
270 xmlFreeNsList(cur->nsDef);
271
272 /*
273 * we don't free element names here they are interned now
274 */
275 if ((cur->type != XML_TEXT_NODE) &&
276 (cur->type != XML_COMMENT_NODE))
277 DICT_FREE(cur->name);
278 if (((cur->type == XML_ELEMENT_NODE) ||
279 (cur->type == XML_TEXT_NODE)) &&
280 (reader != NULL) && (reader->ctxt != NULL) &&
281 (reader->ctxt->freeElemsNr < 100)) {
282 cur->next = reader->ctxt->freeElems;
283 reader->ctxt->freeElems = cur;
284 reader->ctxt->freeElemsNr++;
285 } else {
286 xmlFree(cur);
287 }
288 }
289 cur = next;
290 }
291}
292
293/**
294 * xmlTextReaderFreeNode:
295 * @reader: the xmlTextReaderPtr used
296 * @cur: the node
297 *
298 * Free a node, this is a recursive behaviour, all the children are freed too.
299 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
300 */
301static void
302xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
303 xmlDictPtr dict;
304
305 dict = reader->ctxt->dict;
306 if (cur->type == XML_DTD_NODE) {
307 xmlFreeDtd((xmlDtdPtr) cur);
308 return;
309 }
310 if (cur->type == XML_NAMESPACE_DECL) {
311 xmlFreeNs((xmlNsPtr) cur);
312 return;
313 }
314 if (cur->type == XML_ATTRIBUTE_NODE) {
315 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
316 return;
317 }
318
319 if ((cur->children != NULL) &&
320 (cur->type != XML_ENTITY_REF_NODE))
321 xmlTextReaderFreeNodeList(reader, cur->children);
322 if (((cur->type == XML_ELEMENT_NODE) ||
323 (cur->type == XML_XINCLUDE_START) ||
324 (cur->type == XML_XINCLUDE_END)) &&
325 (cur->properties != NULL))
326 xmlTextReaderFreePropList(reader, cur->properties);
327 if ((cur->type != XML_ELEMENT_NODE) &&
328 (cur->type != XML_XINCLUDE_START) &&
329 (cur->type != XML_XINCLUDE_END) &&
330 (cur->type != XML_ENTITY_REF_NODE)) {
331 DICT_FREE(cur->content);
332 }
333 if (((cur->type == XML_ELEMENT_NODE) ||
334 (cur->type == XML_XINCLUDE_START) ||
335 (cur->type == XML_XINCLUDE_END)) &&
336 (cur->nsDef != NULL))
337 xmlFreeNsList(cur->nsDef);
338
339 /*
340 * we don't free names here they are interned now
341 */
342 if ((cur->type != XML_TEXT_NODE) &&
343 (cur->type != XML_COMMENT_NODE))
344 DICT_FREE(cur->name);
345 if (((cur->type == XML_ELEMENT_NODE) ||
346 (cur->type == XML_TEXT_NODE)) &&
347 (reader != NULL) && (reader->ctxt != NULL) &&
348 (reader->ctxt->freeElemsNr < 100)) {
349 cur->next = reader->ctxt->freeElems;
350 reader->ctxt->freeElems = cur;
351 reader->ctxt->freeElemsNr++;
352 } else {
353 xmlFree(cur);
354 }
355}
356
357/**
358 * xmlTextReaderFreeDoc:
359 * @reader: the xmlTextReaderPtr used
360 * @cur: pointer to the document
361 *
362 * Free up all the structures used by a document, tree included.
363 */
364static void
365xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
366 xmlDtdPtr extSubset, intSubset;
367
368 if (cur == NULL) return;
369
370 /*
371 * Do this before freeing the children list to avoid ID lookups
372 */
373 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
374 cur->ids = NULL;
375 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
376 cur->refs = NULL;
377 extSubset = cur->extSubset;
378 intSubset = cur->intSubset;
379 if (intSubset == extSubset)
380 extSubset = NULL;
381 if (extSubset != NULL) {
382 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
383 cur->extSubset = NULL;
384 xmlFreeDtd(extSubset);
385 }
386 if (intSubset != NULL) {
387 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
388 cur->intSubset = NULL;
389 xmlFreeDtd(intSubset);
390 }
391
392 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
393
394 if (cur->version != NULL) xmlFree((char *) cur->version);
395 if (cur->name != NULL) xmlFree((char *) cur->name);
396 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
397 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
398 if (cur->URL != NULL) xmlFree((char *) cur->URL);
399 xmlFree(cur);
400}
401
402/************************************************************************
403 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000404 * The reader core parser *
405 * *
406 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000407#ifdef DEBUG_READER
408static void
409xmlTextReaderDebug(xmlTextReaderPtr reader) {
410 if ((reader == NULL) || (reader->ctxt == NULL)) {
411 fprintf(stderr, "xmlTextReader NULL\n");
412 return;
413 }
414 fprintf(stderr, "xmlTextReader: state %d depth %d ",
415 reader->state, reader->depth);
416 if (reader->node == NULL) {
417 fprintf(stderr, "node = NULL\n");
418 } else {
419 fprintf(stderr, "node %s\n", reader->node->name);
420 }
421 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
422 reader->base, reader->cur, reader->ctxt->nodeNr);
423 if (reader->input->buffer == NULL) {
424 fprintf(stderr, "buffer is NULL\n");
425 } else {
426#ifdef LIBXML_DEBUG_ENABLED
427 xmlDebugDumpString(stderr,
428 &reader->input->buffer->content[reader->cur]);
429#endif
430 fprintf(stderr, "\n");
431 }
432}
433#endif
434
435/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000436 * xmlTextReaderEntPush:
437 * @reader: the xmlTextReaderPtr used
438 * @value: the entity reference node
439 *
440 * Pushes a new entity reference node on top of the entities stack
441 *
442 * Returns 0 in case of error, the index in the stack otherwise
443 */
444static int
445xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
446{
447 if (reader->entMax <= 0) {
448 reader->entMax = 10;
449 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
450 sizeof(reader->entTab[0]));
451 if (reader->entTab == NULL) {
452 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
453 return (0);
454 }
455 }
456 if (reader->entNr >= reader->entMax) {
457 reader->entMax *= 2;
458 reader->entTab =
459 (xmlNodePtr *) xmlRealloc(reader->entTab,
460 reader->entMax *
461 sizeof(reader->entTab[0]));
462 if (reader->entTab == NULL) {
463 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
464 return (0);
465 }
466 }
467 reader->entTab[reader->entNr] = value;
468 reader->ent = value;
469 return (reader->entNr++);
470}
471
472/**
473 * xmlTextReaderEntPop:
474 * @reader: the xmlTextReaderPtr used
475 *
476 * Pops the top element entity from the entities stack
477 *
478 * Returns the entity just removed
479 */
480static xmlNodePtr
481xmlTextReaderEntPop(xmlTextReaderPtr reader)
482{
483 xmlNodePtr ret;
484
485 if (reader->entNr <= 0)
486 return (0);
487 reader->entNr--;
488 if (reader->entNr > 0)
489 reader->ent = reader->entTab[reader->entNr - 1];
490 else
491 reader->ent = NULL;
492 ret = reader->entTab[reader->entNr];
493 reader->entTab[reader->entNr] = 0;
494 return (ret);
495}
496
497/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000498 * xmlTextReaderStartElement:
499 * @ctx: the user data (XML parser context)
500 * @fullname: The element name, including namespace prefix
501 * @atts: An array of name/value attributes pairs, NULL terminated
502 *
503 * called when an opening tag has been processed.
504 */
505static void
506xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
507 const xmlChar **atts) {
508 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
509 xmlTextReaderPtr reader = ctxt->_private;
510
511#ifdef DEBUG_CALLBACKS
512 printf("xmlTextReaderStartElement(%s)\n", fullname);
513#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000514 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000515 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000516 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
517 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
518 (ctxt->input->cur[1] == '>'))
519 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000520 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000521 if (reader != NULL)
522 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000523}
524
525/**
526 * xmlTextReaderEndElement:
527 * @ctx: the user data (XML parser context)
528 * @fullname: The element name, including namespace prefix
529 *
530 * called when an ending tag has been processed.
531 */
532static void
533xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
534 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
535 xmlTextReaderPtr reader = ctxt->_private;
536
537#ifdef DEBUG_CALLBACKS
538 printf("xmlTextReaderEndElement(%s)\n", fullname);
539#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000540 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000541 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000542 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000543}
544
545/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000546 * xmlTextReaderStartElementNs:
547 * @ctx: the user data (XML parser context)
548 * @localname: the local name of the element
549 * @prefix: the element namespace prefix if available
550 * @URI: the element namespace name if available
551 * @nb_namespaces: number of namespace definitions on that node
552 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
553 * @nb_attributes: the number of attributes on that node
554 * nb_defaulted: the number of defaulted attributes.
555 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
556 * attribute values.
557 *
558 * called when an opening tag has been processed.
559 */
560static void
561xmlTextReaderStartElementNs(void *ctx,
562 const xmlChar *localname,
563 const xmlChar *prefix,
564 const xmlChar *URI,
565 int nb_namespaces,
566 const xmlChar **namespaces,
567 int nb_attributes,
568 int nb_defaulted,
569 const xmlChar **attributes)
570{
571 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
572 xmlTextReaderPtr reader = ctxt->_private;
573
574#ifdef DEBUG_CALLBACKS
575 printf("xmlTextReaderStartElementNs(%s)\n", fullname);
576#endif
577 if ((reader != NULL) && (reader->startElementNs != NULL)) {
578 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
579 namespaces, nb_attributes, nb_defaulted,
580 attributes);
581 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
582 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
583 (ctxt->input->cur[1] == '>'))
584 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
585 }
586 if (reader != NULL)
587 reader->state = XML_TEXTREADER_ELEMENT;
588}
589
590/**
591 * xmlTextReaderEndElementNs:
592 * @ctx: the user data (XML parser context)
593 * @localname: the local name of the element
594 * @prefix: the element namespace prefix if available
595 * @URI: the element namespace name if available
596 *
597 * called when an ending tag has been processed.
598 */
599static void
600xmlTextReaderEndElementNs(void *ctx,
601 const xmlChar * localname,
602 const xmlChar * prefix,
603 const xmlChar * URI)
604{
605 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
606 xmlTextReaderPtr reader = ctxt->_private;
607
608#ifdef DEBUG_CALLBACKS
609 printf("xmlTextReaderEndElementNs(%s)\n", fullname);
610#endif
611 if ((reader != NULL) && (reader->endElementNs != NULL)) {
612 reader->endElementNs(ctx, localname, prefix, URI);
613 }
614}
615
616
617/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000618 * xmlTextReaderCharacters:
619 * @ctx: the user data (XML parser context)
620 * @ch: a xmlChar string
621 * @len: the number of xmlChar
622 *
623 * receiving some chars from the parser.
624 */
625static void
626xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
627{
628 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
629 xmlTextReaderPtr reader = ctxt->_private;
630
631#ifdef DEBUG_CALLBACKS
632 printf("xmlTextReaderCharacters()\n");
633#endif
634 if ((reader != NULL) && (reader->characters != NULL)) {
635 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000636 }
637}
638
639/**
640 * xmlTextReaderCDataBlock:
641 * @ctx: the user data (XML parser context)
642 * @value: The pcdata content
643 * @len: the block length
644 *
645 * called when a pcdata block has been parsed
646 */
647static void
648xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
649{
650 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
651 xmlTextReaderPtr reader = ctxt->_private;
652
653#ifdef DEBUG_CALLBACKS
654 printf("xmlTextReaderCDataBlock()\n");
655#endif
656 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
657 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 }
659}
660
661/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000662 * xmlTextReaderPushData:
663 * @reader: the xmlTextReaderPtr used
664 *
665 * Push data down the progressive parser until a significant callback
666 * got raised.
667 *
668 * Returns -1 in case of failure, 0 otherwise
669 */
670static int
671xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000672 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000673 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000674 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000675
676 if ((reader->input == NULL) || (reader->input->buffer == NULL))
677 return(-1);
678
Daniel Veillardea7751d2002-12-20 00:16:24 +0000679 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000680 reader->state = XML_TEXTREADER_NONE;
681 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000682
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000683 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000684 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000685 /*
686 * Refill the buffer unless we are at the end of the stream
687 */
688 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
689 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000690 if ((val == 0) &&
691 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
692 if (inbuf->use == reader->cur) {
693 reader->mode = XML_TEXTREADER_MODE_EOF;
694 reader->state = oldstate;
695 if ((oldstate != XML_TEXTREADER_START) ||
696 (reader->ctxt->myDoc != NULL))
697 return(val);
698 }
699 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000700 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000701 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000702 if ((oldstate != XML_TEXTREADER_START) ||
703 (reader->ctxt->myDoc != NULL))
704 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000705 } else if (val == 0) {
706 /* mark the end of the stream and process the remains */
707 reader->mode = XML_TEXTREADER_MODE_EOF;
708 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000709 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000710
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000711 } else
712 break;
713 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000714 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000715 * parse by block of CHUNK_SIZE bytes, various tests show that
716 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000717 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000718 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000719 val = xmlParseChunk(reader->ctxt,
720 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000721 CHUNK_SIZE, 0);
722 reader->cur += CHUNK_SIZE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000723 if (val != 0)
724 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000725 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000726 s = inbuf->use - reader->cur;
727 val = xmlParseChunk(reader->ctxt,
728 (const char *) &inbuf->content[reader->cur],
729 s, 0);
730 reader->cur += s;
731 if (val != 0)
732 return(-1);
733 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000734 }
735 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000736
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000737 /*
738 * Discard the consumed input when needed and possible
739 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000740 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000741 if ((reader->cur >= 4096) &&
742 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000743 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000744 if (val >= 0) {
745 reader->cur -= val;
746 }
747 }
748 }
749
750 /*
751 * At the end of the stream signal that the work is done to the Push
752 * parser.
753 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000754 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000755 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000756 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000757 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000758 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000759 s, 1);
760 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000761 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000762 if (val != 0) return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000763 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000764 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000765 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000766 return(0);
767}
768
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000769#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000770/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000771 * xmlTextReaderValidatePush:
772 * @reader: the xmlTextReaderPtr used
773 *
774 * Push the current node for validation
775 */
776static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000777xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000778 xmlNodePtr node = reader->node;
779
Daniel Veillardf4e55762003-04-15 23:32:22 +0000780 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
781 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
782 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
783 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
784 reader->ctxt->myDoc, node, node->name);
785 } else {
786 /* TODO use the BuildQName interface */
787 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000788
Daniel Veillardf4e55762003-04-15 23:32:22 +0000789 qname = xmlStrdup(node->ns->prefix);
790 qname = xmlStrcat(qname, BAD_CAST ":");
791 qname = xmlStrcat(qname, node->name);
792 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
793 reader->ctxt->myDoc, node, qname);
794 if (qname != NULL)
795 xmlFree(qname);
796 }
797#ifdef LIBXML_SCHEMAS_ENABLED
798 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
799 (reader->rngValidCtxt != NULL)) {
800 int ret;
801
802 if (reader->rngFullNode != NULL) return;
803 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
804 reader->ctxt->myDoc,
805 node);
806 if (ret == 0) {
807 /*
808 * this element requires a full tree
809 */
810 node = xmlTextReaderExpand(reader);
811 if (node == NULL) {
812printf("Expand failed !\n");
813 ret = -1;
814 } else {
815 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
816 reader->ctxt->myDoc,
817 node);
818 reader->rngFullNode = node;
819 }
820 }
821 if (ret != 1)
822 reader->rngValidErrors++;
823#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000824 }
825}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000826
827/**
828 * xmlTextReaderValidateCData:
829 * @reader: the xmlTextReaderPtr used
830 * @data: pointer to the CData
831 * @len: lenght of the CData block in bytes.
832 *
833 * Push some CData for validation
834 */
835static void
836xmlTextReaderValidateCData(xmlTextReaderPtr reader,
837 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000838 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
839 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
840 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
841 data, len);
842#ifdef LIBXML_SCHEMAS_ENABLED
843 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
844 (reader->rngValidCtxt != NULL)) {
845 int ret;
846
847 if (reader->rngFullNode != NULL) return;
848 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
849 if (ret != 1)
850 reader->rngValidErrors++;
851#endif
852 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000853}
854
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000855/**
856 * xmlTextReaderValidatePop:
857 * @reader: the xmlTextReaderPtr used
858 *
859 * Pop the current node from validation
860 */
861static void
862xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
863 xmlNodePtr node = reader->node;
864
Daniel Veillardf4e55762003-04-15 23:32:22 +0000865 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
866 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
867 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
868 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
869 reader->ctxt->myDoc, node, node->name);
870 } else {
871 /* TODO use the BuildQName interface */
872 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000873
Daniel Veillardf4e55762003-04-15 23:32:22 +0000874 qname = xmlStrdup(node->ns->prefix);
875 qname = xmlStrcat(qname, BAD_CAST ":");
876 qname = xmlStrcat(qname, node->name);
877 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
878 reader->ctxt->myDoc, node, qname);
879 if (qname != NULL)
880 xmlFree(qname);
881 }
882#ifdef LIBXML_SCHEMAS_ENABLED
883 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
884 (reader->rngValidCtxt != NULL)) {
885 int ret;
886
887 if (reader->rngFullNode != NULL) {
888 if (node == reader->rngFullNode)
889 reader->rngFullNode = NULL;
890 return;
891 }
892 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
893 reader->ctxt->myDoc,
894 node);
895 if (ret != 1)
896 reader->rngValidErrors++;
897#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000898 }
899}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000900
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000901/**
902 * xmlTextReaderValidateEntity:
903 * @reader: the xmlTextReaderPtr used
904 *
905 * Handle the validation when an entity reference is encountered and
906 * entity substitution is not activated. As a result the parser interface
907 * must walk through the entity and do the validation calls
908 */
909static void
910xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
911 xmlNodePtr oldnode = reader->node;
912 xmlNodePtr node = reader->node;
913 xmlParserCtxtPtr ctxt = reader->ctxt;
914
915 do {
916 if (node->type == XML_ENTITY_REF_NODE) {
917 /*
918 * Case where the underlying tree is not availble, lookup the entity
919 * and walk it.
920 */
921 if ((node->children == NULL) && (ctxt->sax != NULL) &&
922 (ctxt->sax->getEntity != NULL)) {
923 node->children = (xmlNodePtr)
924 ctxt->sax->getEntity(ctxt, node->name);
925 }
926
927 if ((node->children != NULL) &&
928 (node->children->type == XML_ENTITY_DECL) &&
929 (node->children->children != NULL)) {
930 xmlTextReaderEntPush(reader, node);
931 node = node->children->children;
932 continue;
933 } else {
934 /*
935 * The error has probably be raised already.
936 */
937 if (node == oldnode)
938 break;
939 node = node->next;
940 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000941#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000942 } else if (node->type == XML_ELEMENT_NODE) {
943 reader->node = node;
944 xmlTextReaderValidatePush(reader);
945 } else if ((node->type == XML_TEXT_NODE) ||
946 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000947 xmlTextReaderValidateCData(reader, node->content,
948 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000949#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000950 }
951
952 /*
953 * go to next node
954 */
955 if (node->children != NULL) {
956 node = node->children;
957 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +0000958 } else if (node->type == XML_ELEMENT_NODE) {
959 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000960 }
961 if (node->next != NULL) {
962 node = node->next;
963 continue;
964 }
965 do {
966 node = node->parent;
967 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000968 xmlNodePtr tmp;
969 while ((tmp = node->last) != NULL) {
970 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
971 (tmp->_private != xmlTextReaderIsPreserved)) {
972 xmlUnlinkNode(tmp);
973 xmlTextReaderFreeNode(reader, tmp);
974 } else
975 break;
976 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000977 reader->node = node;
978 xmlTextReaderValidatePop(reader);
979 }
980 if ((node->type == XML_ENTITY_DECL) &&
981 (reader->ent != NULL) && (reader->ent->children == node)) {
982 node = xmlTextReaderEntPop(reader);
983 }
984 if (node == oldnode)
985 break;
986 if (node->next != NULL) {
987 node = node->next;
988 break;
989 }
990 } while ((node != NULL) && (node != oldnode));
991 } while ((node != NULL) && (node != oldnode));
992 reader->node = oldnode;
993}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000994#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000995
996
997/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +0000998 * xmlTextReaderGetSuccessor:
999 * @cur: the current node
1000 *
1001 * Get the successor of a node if available.
1002 *
1003 * Returns the successor node or NULL
1004 */
1005static xmlNodePtr
1006xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1007 if (cur == NULL) return(NULL) ; /* ERROR */
1008 if (cur->next != NULL) return(cur->next) ;
1009 do {
1010 cur = cur->parent;
1011 if (cur == NULL) return(NULL);
1012 if (cur->next != NULL) return(cur->next);
1013 } while (cur != NULL);
1014 return(cur);
1015}
1016
1017/**
1018 * xmlTextReaderDoExpand:
1019 * @reader: the xmlTextReaderPtr used
1020 *
1021 * Makes sure that the current node is fully read as well as all its
1022 * descendant. It means the full DOM subtree must be available at the
1023 * end of the call.
1024 *
1025 * Returns 1 if the node was expanded successfully, 0 if there is no more
1026 * nodes to read, or -1 in case of error
1027 */
1028static int
1029xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1030 int val;
1031
1032 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1033 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001034 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001035 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1036
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001037 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1038 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001039 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001040 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001041 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1042 return(1);
1043 val = xmlTextReaderPushData(reader);
1044 if (val < 0)
1045 return(-1);
1046 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1047 return(1);
1048}
1049
1050/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001051 * xmlTextReaderRead:
1052 * @reader: the xmlTextReaderPtr used
1053 *
1054 * Moves the position of the current instance to the next node in
1055 * the stream, exposing its properties.
1056 *
1057 * Returns 1 if the node was read successfully, 0 if there is no more
1058 * nodes to read, or -1 in case of error
1059 */
1060int
1061xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001062 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001063 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001064 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001065
1066 if ((reader == NULL) || (reader->ctxt == NULL))
1067 return(-1);
1068 if (reader->ctxt->wellFormed != 1)
1069 return(-1);
1070
1071#ifdef DEBUG_READER
1072 fprintf(stderr, "\nREAD ");
1073 DUMP_READER
1074#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001075 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001076 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1077 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001078 /*
1079 * Initial state
1080 */
1081 do {
1082 val = xmlTextReaderPushData(reader);
1083 if (val < 0)
1084 return(-1);
1085 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001086 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1087 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001088 if (reader->ctxt->myDoc != NULL)
1089 reader->ctxt->myDoc->_private = reader;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001090 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001091 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001092 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001093 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001094 if (reader->node == NULL)
1095 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001096 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001097 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001098 if (reader->ctxt->myDoc != NULL) {
1099 reader->node = reader->ctxt->myDoc->children;
1100 }
1101 if (reader->node == NULL)
1102 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001103 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001104 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001105 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001106 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001107 }
1108 oldstate = reader->state;
1109 olddepth = reader->ctxt->nodeNr;
1110 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001111
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001112get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001113 /*
1114 * If we are not backtracking on ancestors or examined nodes,
1115 * that the parser didn't finished or that we arent at the end
1116 * of stream, continue processing.
1117 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001118 while ((reader->node->next == NULL) &&
1119 (reader->ctxt->nodeNr == olddepth) &&
1120 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001121 (reader->node->children == NULL) ||
1122 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001123 ((reader->node->children != NULL) &&
1124 (reader->node->children->type == XML_TEXT_NODE) &&
1125 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001126 (reader->node->type == XML_DTD_NODE) ||
1127 (reader->node->type == XML_DOCUMENT_NODE) ||
1128 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001129 ((reader->ctxt->node == NULL) ||
1130 (reader->ctxt->node == reader->node) ||
1131 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001132 (reader->ctxt->instate != XML_PARSER_EOF)) {
1133 val = xmlTextReaderPushData(reader);
1134 if (val < 0)
1135 return(-1);
1136 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001137 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001138 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001139 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001140 if ((reader->node->children != NULL) &&
1141 (reader->node->type != XML_ENTITY_REF_NODE) &&
1142 (reader->node->type != XML_DTD_NODE)) {
1143 reader->node = reader->node->children;
1144 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001145 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001146 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001147 }
1148 }
1149 if (reader->node->next != NULL) {
1150 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001151 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001152 (reader->node->children == NULL) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001153 (reader->node->_private != (void *)xmlTextReaderIsEmpty) &&
1154 (reader->node->_private != (void *)xmlTextReaderIsEmptyPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001155 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001156 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001157 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001158#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001159 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001160 (reader->node->type == XML_ELEMENT_NODE))
1161 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001162#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001163 reader->node = reader->node->next;
1164 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001165
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001166 /*
1167 * Cleanup of the old node
1168 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001169 if ((reader->node->prev != NULL) &&
1170 (reader->node->prev->type != XML_DTD_NODE)) {
1171 xmlNodePtr tmp = reader->node->prev;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001172 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
1173 (tmp->_private != xmlTextReaderIsPreserved)) {
1174 xmlUnlinkNode(tmp);
1175 xmlTextReaderFreeNode(reader, tmp);
1176 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001177 }
1178
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001179 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001180 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001181 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001182 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001183 (reader->node->children == NULL) &&
1184 (reader->node->_private != (void *)xmlTextReaderIsEmpty)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001185 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001186 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001187 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001188#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001189 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001190 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001191#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001192 reader->node = reader->node->parent;
1193 if ((reader->node == NULL) ||
1194 (reader->node->type == XML_DOCUMENT_NODE) ||
1195#ifdef LIBXML_DOCB_ENABLED
1196 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1197#endif
1198 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001199 if (reader->mode != XML_TEXTREADER_DONE) {
1200 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1201 reader->mode = XML_TEXTREADER_DONE;
1202 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001203 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001204 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001205
1206 /*
1207 * Cleanup of the old node
1208 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001209 if ((oldnode->type != XML_DTD_NODE) &&
1210 (oldnode->_private != xmlTextReaderIsEmptyPreserved) &&
1211 (oldnode->_private != xmlTextReaderIsPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001212 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001213 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001214 }
1215
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001216 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001217 }
1218 reader->depth--;
1219 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001220
1221node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001222 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001223
1224 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001225 * If we are in the middle of a piece of CDATA make sure it's finished
1226 */
1227 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001228 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001229 ((reader->node->type == XML_TEXT_NODE) ||
1230 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1231 xmlTextReaderExpand(reader);
1232 }
1233
1234 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001235 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001236 */
1237 if ((reader->node != NULL) &&
1238 (reader->node->type == XML_ENTITY_REF_NODE) &&
1239 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1240 /*
1241 * Case where the underlying tree is not availble, lookup the entity
1242 * and walk it.
1243 */
1244 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1245 (reader->ctxt->sax->getEntity != NULL)) {
1246 reader->node->children = (xmlNodePtr)
1247 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1248 }
1249
1250 if ((reader->node->children != NULL) &&
1251 (reader->node->children->type == XML_ENTITY_DECL) &&
1252 (reader->node->children->children != NULL)) {
1253 xmlTextReaderEntPush(reader, reader->node);
1254 reader->node = reader->node->children->children;
1255 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001256#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001257 } else if ((reader->node != NULL) &&
1258 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001259 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001260 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001261#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001262 }
1263 if ((reader->node != NULL) &&
1264 (reader->node->type == XML_ENTITY_DECL) &&
1265 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1266 reader->node = xmlTextReaderEntPop(reader);
1267 reader->depth++;
1268 goto get_next_node;
1269 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001270#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001271 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001272 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001273
1274 if ((node->type == XML_ELEMENT_NODE) &&
1275 ((reader->state != XML_TEXTREADER_END) &&
1276 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1277 xmlTextReaderValidatePush(reader);
1278 } else if ((node->type == XML_TEXT_NODE) ||
1279 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001280 xmlTextReaderValidateCData(reader, node->content,
1281 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001282 }
1283 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001284#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001285 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001286node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001287 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001289}
1290
Daniel Veillard67df8092002-12-16 22:04:11 +00001291/**
1292 * xmlTextReaderReadState:
1293 * @reader: the xmlTextReaderPtr used
1294 *
1295 * Gets the read state of the reader.
1296 *
1297 * Returns the state value, or -1 in case of error
1298 */
1299int
1300xmlTextReaderReadState(xmlTextReaderPtr reader) {
1301 if (reader == NULL)
1302 return(-1);
1303 return(reader->mode);
1304}
1305
1306/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001307 * xmlTextReaderExpand:
1308 * @reader: the xmlTextReaderPtr used
1309 *
1310 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001311 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001312 *
1313 * Returns a node pointer valid until the next xmlTextReaderRead() call
1314 * or NULL in case of error.
1315 */
1316xmlNodePtr
1317xmlTextReaderExpand(xmlTextReaderPtr reader) {
1318 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1319 return(NULL);
1320 if (xmlTextReaderDoExpand(reader) < 0)
1321 return(NULL);
1322 return(reader->node);
1323}
1324
1325/**
1326 * xmlTextReaderNext:
1327 * @reader: the xmlTextReaderPtr used
1328 *
1329 * Skip to the node following the current one in document order while
1330 * avoiding the subtree if any.
1331 *
1332 * Returns 1 if the node was read successfully, 0 if there is no more
1333 * nodes to read, or -1 in case of error
1334 */
1335int
1336xmlTextReaderNext(xmlTextReaderPtr reader) {
1337 int ret;
1338 xmlNodePtr cur;
1339
1340 if (reader == NULL)
1341 return(-1);
1342 cur = reader->node;
1343 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1344 return(xmlTextReaderRead(reader));
1345 if (reader->state == XML_TEXTREADER_END)
1346 return(xmlTextReaderRead(reader));
1347 if (cur->_private == (void *)xmlTextReaderIsEmpty)
1348 return(xmlTextReaderRead(reader));
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001349 if (cur->_private == (void *)xmlTextReaderIsEmptyPreserved)
1350 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001351 do {
1352 ret = xmlTextReaderRead(reader);
1353 if (ret != 1)
1354 return(ret);
1355 } while (reader->node != cur);
1356 return(xmlTextReaderRead(reader));
1357}
1358
1359/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001360 * xmlTextReaderReadInnerXml:
1361 * @reader: the xmlTextReaderPtr used
1362 *
1363 * Reads the contents of the current node, including child nodes and markup.
1364 *
1365 * Returns a string containing the XML content, or NULL if the current node
1366 * is neither an element nor attribute, or has no child nodes. The
1367 * string must be deallocated by the caller.
1368 */
1369xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001370xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001371 TODO
1372 return(NULL);
1373}
1374
1375/**
1376 * xmlTextReaderReadOuterXml:
1377 * @reader: the xmlTextReaderPtr used
1378 *
1379 * Reads the contents of the current node, including child nodes and markup.
1380 *
1381 * Returns a string containing the XML content, or NULL if the current node
1382 * is neither an element nor attribute, or has no child nodes. The
1383 * string must be deallocated by the caller.
1384 */
1385xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001386xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001387 TODO
1388 return(NULL);
1389}
1390
1391/**
1392 * xmlTextReaderReadString:
1393 * @reader: the xmlTextReaderPtr used
1394 *
1395 * Reads the contents of an element or a text node as a string.
1396 *
1397 * Returns a string containing the contents of the Element or Text node,
1398 * or NULL if the reader is positioned on any other type of node.
1399 * The string must be deallocated by the caller.
1400 */
1401xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001402xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001403 TODO
1404 return(NULL);
1405}
1406
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001407#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001408/**
1409 * xmlTextReaderReadBase64:
1410 * @reader: the xmlTextReaderPtr used
1411 * @array: a byte array to store the content.
1412 * @offset: the zero-based index into array where the method should
1413 * begin to write.
1414 * @len: the number of bytes to write.
1415 *
1416 * Reads and decodes the Base64 encoded contents of an element and
1417 * stores the result in a byte buffer.
1418 *
1419 * Returns the number of bytes written to array, or zero if the current
1420 * instance is not positioned on an element or -1 in case of error.
1421 */
1422int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001423xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1424 unsigned char *array ATTRIBUTE_UNUSED,
1425 int offset ATTRIBUTE_UNUSED,
1426 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001427 if ((reader == NULL) || (reader->ctxt == NULL))
1428 return(-1);
1429 if (reader->ctxt->wellFormed != 1)
1430 return(-1);
1431
1432 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1433 return(0);
1434 TODO
1435 return(0);
1436}
1437
1438/**
1439 * xmlTextReaderReadBinHex:
1440 * @reader: the xmlTextReaderPtr used
1441 * @array: a byte array to store the content.
1442 * @offset: the zero-based index into array where the method should
1443 * begin to write.
1444 * @len: the number of bytes to write.
1445 *
1446 * Reads and decodes the BinHex encoded contents of an element and
1447 * stores the result in a byte buffer.
1448 *
1449 * Returns the number of bytes written to array, or zero if the current
1450 * instance is not positioned on an element or -1 in case of error.
1451 */
1452int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001453xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1454 unsigned char *array ATTRIBUTE_UNUSED,
1455 int offset ATTRIBUTE_UNUSED,
1456 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001457 if ((reader == NULL) || (reader->ctxt == NULL))
1458 return(-1);
1459 if (reader->ctxt->wellFormed != 1)
1460 return(-1);
1461
1462 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1463 return(0);
1464 TODO
1465 return(0);
1466}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001467#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001468
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001469/************************************************************************
1470 * *
1471 * Constructor and destructors *
1472 * *
1473 ************************************************************************/
1474/**
1475 * xmlNewTextReader:
1476 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001477 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001478 *
1479 * Create an xmlTextReader structure fed with @input
1480 *
1481 * Returns the new xmlTextReaderPtr or NULL in case of error
1482 */
1483xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001484xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001486
1487 if (input == NULL)
1488 return(NULL);
1489 ret = xmlMalloc(sizeof(xmlTextReader));
1490 if (ret == NULL) {
1491 xmlGenericError(xmlGenericErrorContext,
1492 "xmlNewTextReader : malloc failed\n");
1493 return(NULL);
1494 }
1495 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001496 ret->entTab = NULL;
1497 ret->entMax = 0;
1498 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001499 ret->input = input;
1500 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1501 if (ret->sax == NULL) {
1502 xmlFree(ret);
1503 xmlGenericError(xmlGenericErrorContext,
1504 "xmlNewTextReader : malloc failed\n");
1505 return(NULL);
1506 }
Daniel Veillard81273902003-09-30 00:43:48 +00001507 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001508 ret->startElement = ret->sax->startElement;
1509 ret->sax->startElement = xmlTextReaderStartElement;
1510 ret->endElement = ret->sax->endElement;
1511 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001512#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001513 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001514#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001515 ret->startElementNs = ret->sax->startElementNs;
1516 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1517 ret->endElementNs = ret->sax->endElementNs;
1518 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001519#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001520 } else {
1521 ret->startElementNs = NULL;
1522 ret->endElementNs = NULL;
1523 }
Daniel Veillard81273902003-09-30 00:43:48 +00001524#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001525 ret->characters = ret->sax->characters;
1526 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001527 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001528 ret->cdataBlock = ret->sax->cdataBlock;
1529 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001530
Daniel Veillard67df8092002-12-16 22:04:11 +00001531 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001532 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001533 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001534 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001535 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001536 }
1537 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001538 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001539 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001540 ret->base = 0;
1541 ret->cur = 4;
1542 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001543 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001544 ret->base = 0;
1545 ret->cur = 0;
1546 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001547 if (ret->ctxt == NULL) {
1548 xmlGenericError(xmlGenericErrorContext,
1549 "xmlNewTextReader : malloc failed\n");
1550 xmlFree(ret->sax);
1551 xmlFree(ret);
1552 return(NULL);
1553 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001554 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001555 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001556 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001557 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001558 /*
1559 * use the parser dictionnary to allocate all elements and attributes names
1560 */
1561 ret->ctxt->docdict = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001562 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001563}
1564
1565/**
1566 * xmlNewTextReaderFilename:
1567 * @URI: the URI of the resource to process
1568 *
1569 * Create an xmlTextReader structure fed with the resource at @URI
1570 *
1571 * Returns the new xmlTextReaderPtr or NULL in case of error
1572 */
1573xmlTextReaderPtr
1574xmlNewTextReaderFilename(const char *URI) {
1575 xmlParserInputBufferPtr input;
1576 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001577 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001578
1579 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1580 if (input == NULL)
1581 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001582 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001583 if (ret == NULL) {
1584 xmlFreeParserInputBuffer(input);
1585 return(NULL);
1586 }
1587 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001588 if (ret->ctxt->directory == NULL)
1589 directory = xmlParserGetDirectory(URI);
1590 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1591 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1592 if (directory != NULL)
1593 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001594 return(ret);
1595}
1596
1597/**
1598 * xmlFreeTextReader:
1599 * @reader: the xmlTextReaderPtr
1600 *
1601 * Deallocate all the resources associated to the reader
1602 */
1603void
1604xmlFreeTextReader(xmlTextReaderPtr reader) {
1605 if (reader == NULL)
1606 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001607#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001608 if (reader->rngSchemas != NULL) {
1609 xmlRelaxNGFree(reader->rngSchemas);
1610 reader->rngSchemas = NULL;
1611 }
1612 if (reader->rngValidCtxt != NULL) {
1613 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1614 reader->rngValidCtxt = NULL;
1615 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001616#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001617 if (reader->ctxt != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001618 if (reader->ctxt->myDoc != NULL) {
1619 if (reader->preserve == 0)
1620 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1621 reader->ctxt->myDoc = NULL;
1622 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001623 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1624 (reader->ctxt->vctxt.vstateMax > 0)){
1625 xmlFree(reader->ctxt->vctxt.vstateTab);
1626 reader->ctxt->vctxt.vstateTab = 0;
1627 reader->ctxt->vctxt.vstateMax = 0;
1628 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001629 if (reader->allocs & XML_TEXTREADER_CTXT)
1630 xmlFreeParserCtxt(reader->ctxt);
1631 }
1632 if (reader->sax != NULL)
1633 xmlFree(reader->sax);
1634 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1635 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001636 if (reader->faketext != NULL) {
1637 xmlFreeNode(reader->faketext);
1638 }
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001639 if (reader->entTab != NULL)
1640 xmlFree(reader->entTab);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001641 xmlFree(reader);
1642}
1643
1644/************************************************************************
1645 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001646 * Methods for XmlTextReader *
1647 * *
1648 ************************************************************************/
1649/**
1650 * xmlTextReaderClose:
1651 * @reader: the xmlTextReaderPtr used
1652 *
1653 * This method releases any resources allocated by the current instance
1654 * changes the state to Closed and close any underlying input.
1655 *
1656 * Returns 0 or -1 in case of error
1657 */
1658int
1659xmlTextReaderClose(xmlTextReaderPtr reader) {
1660 if (reader == NULL)
1661 return(-1);
1662 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001663 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001664 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1665 if (reader->ctxt != NULL) {
1666 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001667 if (reader->preserve == 0)
1668 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001669 reader->ctxt->myDoc = NULL;
1670 }
1671 if (reader->allocs & XML_TEXTREADER_CTXT) {
1672 xmlFreeParserCtxt(reader->ctxt);
1673 reader->allocs -= XML_TEXTREADER_CTXT;
1674 }
1675 }
1676 if (reader->sax != NULL) {
1677 xmlFree(reader->sax);
1678 reader->sax = NULL;
1679 }
1680 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1681 xmlFreeParserInputBuffer(reader->input);
1682 reader->allocs -= XML_TEXTREADER_INPUT;
1683 }
1684 return(0);
1685}
1686
1687/**
1688 * xmlTextReaderGetAttributeNo:
1689 * @reader: the xmlTextReaderPtr used
1690 * @no: the zero-based index of the attribute relative to the containing element
1691 *
1692 * Provides the value of the attribute with the specified index relative
1693 * to the containing element.
1694 *
1695 * Returns a string containing the value of the specified attribute, or NULL
1696 * in case of error. The string must be deallocated by the caller.
1697 */
1698xmlChar *
1699xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1700 xmlChar *ret;
1701 int i;
1702 xmlAttrPtr cur;
1703 xmlNsPtr ns;
1704
1705 if (reader == NULL)
1706 return(NULL);
1707 if (reader->node == NULL)
1708 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001709 if (reader->curnode != NULL)
1710 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001711 /* TODO: handle the xmlDecl */
1712 if (reader->node->type != XML_ELEMENT_NODE)
1713 return(NULL);
1714
1715 ns = reader->node->nsDef;
1716 for (i = 0;(i < no) && (ns != NULL);i++) {
1717 ns = ns->next;
1718 }
1719 if (ns != NULL)
1720 return(xmlStrdup(ns->href));
1721
1722 cur = reader->node->properties;
1723 if (cur == NULL)
1724 return(NULL);
1725 for (;i < no;i++) {
1726 cur = cur->next;
1727 if (cur == NULL)
1728 return(NULL);
1729 }
1730 /* TODO walk the DTD if present */
1731
1732 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1733 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1734 return(ret);
1735}
1736
1737/**
1738 * xmlTextReaderGetAttribute:
1739 * @reader: the xmlTextReaderPtr used
1740 * @name: the qualified name of the attribute.
1741 *
1742 * Provides the value of the attribute with the specified qualified name.
1743 *
1744 * Returns a string containing the value of the specified attribute, or NULL
1745 * in case of error. The string must be deallocated by the caller.
1746 */
1747xmlChar *
1748xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1749 xmlChar *prefix = NULL;
1750 xmlChar *localname;
1751 xmlNsPtr ns;
1752 xmlChar *ret = NULL;
1753
1754 if ((reader == NULL) || (name == NULL))
1755 return(NULL);
1756 if (reader->node == NULL)
1757 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001758 if (reader->curnode != NULL)
1759 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001760
1761 /* TODO: handle the xmlDecl */
1762 if (reader->node->type != XML_ELEMENT_NODE)
1763 return(NULL);
1764
1765 localname = xmlSplitQName2(name, &prefix);
1766 if (localname == NULL)
1767 return(xmlGetProp(reader->node, name));
1768
1769 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1770 if (ns != NULL)
1771 ret = xmlGetNsProp(reader->node, localname, ns->href);
1772
1773 if (localname != NULL)
1774 xmlFree(localname);
1775 if (prefix != NULL)
1776 xmlFree(prefix);
1777 return(ret);
1778}
1779
1780
1781/**
1782 * xmlTextReaderGetAttributeNs:
1783 * @reader: the xmlTextReaderPtr used
1784 * @localName: the local name of the attribute.
1785 * @namespaceURI: the namespace URI of the attribute.
1786 *
1787 * Provides the value of the specified attribute
1788 *
1789 * Returns a string containing the value of the specified attribute, or NULL
1790 * in case of error. The string must be deallocated by the caller.
1791 */
1792xmlChar *
1793xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
1794 const xmlChar *namespaceURI) {
1795 if ((reader == NULL) || (localName == NULL))
1796 return(NULL);
1797 if (reader->node == NULL)
1798 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001799 if (reader->curnode != NULL)
1800 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001801
1802 /* TODO: handle the xmlDecl */
1803 if (reader->node->type != XML_ELEMENT_NODE)
1804 return(NULL);
1805
1806 return(xmlGetNsProp(reader->node, localName, namespaceURI));
1807}
1808
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001809/**
1810 * xmlTextReaderGetRemainder:
1811 * @reader: the xmlTextReaderPtr used
1812 *
1813 * Method to get the remainder of the buffered XML. this method stops the
1814 * parser, set its state to End Of File and return the input stream with
1815 * what is left that the parser did not use.
1816 *
1817 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
1818 * in case of error.
1819 */
1820xmlParserInputBufferPtr
1821xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
1822 xmlParserInputBufferPtr ret = NULL;
1823
1824 if (reader == NULL)
1825 return(NULL);
1826 if (reader->node == NULL)
1827 return(NULL);
1828
1829 reader->node = NULL;
1830 reader->curnode = NULL;
1831 reader->mode = XML_TEXTREADER_MODE_EOF;
1832 if (reader->ctxt != NULL) {
1833 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001834 if (reader->preserve == 0)
1835 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001836 reader->ctxt->myDoc = NULL;
1837 }
1838 if (reader->allocs & XML_TEXTREADER_CTXT) {
1839 xmlFreeParserCtxt(reader->ctxt);
1840 reader->allocs -= XML_TEXTREADER_CTXT;
1841 }
1842 }
1843 if (reader->sax != NULL) {
1844 xmlFree(reader->sax);
1845 reader->sax = NULL;
1846 }
1847 if (reader->allocs & XML_TEXTREADER_INPUT) {
1848 ret = reader->input;
1849 reader->allocs -= XML_TEXTREADER_INPUT;
1850 } else {
1851 /*
1852 * Hum, one may need to duplicate the data structure because
1853 * without reference counting the input may be freed twice:
1854 * - by the layer which allocated it.
1855 * - by the layer to which would have been returned to.
1856 */
1857 TODO
1858 return(NULL);
1859 }
1860 return(ret);
1861}
1862
1863/**
1864 * xmlTextReaderLookupNamespace:
1865 * @reader: the xmlTextReaderPtr used
1866 * @prefix: the prefix whose namespace URI is to be resolved. To return
1867 * the default namespace, specify NULL
1868 *
1869 * Resolves a namespace prefix in the scope of the current element.
1870 *
1871 * Returns a string containing the namespace URI to which the prefix maps
1872 * or NULL in case of error. The string must be deallocated by the caller.
1873 */
1874xmlChar *
1875xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
1876 xmlNsPtr ns;
1877
1878 if (reader == NULL)
1879 return(NULL);
1880 if (reader->node == NULL)
1881 return(NULL);
1882
1883 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1884 if (ns == NULL)
1885 return(NULL);
1886 return(xmlStrdup(ns->href));
1887}
1888
1889/**
1890 * xmlTextReaderMoveToAttributeNo:
1891 * @reader: the xmlTextReaderPtr used
1892 * @no: the zero-based index of the attribute relative to the containing
1893 * element.
1894 *
1895 * Moves the position of the current instance to the attribute with
1896 * the specified index relative to the containing element.
1897 *
1898 * Returns 1 in case of success, -1 in case of error, 0 if not found
1899 */
1900int
1901xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
1902 int i;
1903 xmlAttrPtr cur;
1904 xmlNsPtr ns;
1905
1906 if (reader == NULL)
1907 return(-1);
1908 if (reader->node == NULL)
1909 return(-1);
1910 /* TODO: handle the xmlDecl */
1911 if (reader->node->type != XML_ELEMENT_NODE)
1912 return(-1);
1913
1914 reader->curnode = NULL;
1915
1916 ns = reader->node->nsDef;
1917 for (i = 0;(i < no) && (ns != NULL);i++) {
1918 ns = ns->next;
1919 }
1920 if (ns != NULL) {
1921 reader->curnode = (xmlNodePtr) ns;
1922 return(1);
1923 }
1924
1925 cur = reader->node->properties;
1926 if (cur == NULL)
1927 return(0);
1928 for (;i < no;i++) {
1929 cur = cur->next;
1930 if (cur == NULL)
1931 return(0);
1932 }
1933 /* TODO walk the DTD if present */
1934
1935 reader->curnode = (xmlNodePtr) cur;
1936 return(1);
1937}
1938
1939/**
1940 * xmlTextReaderMoveToAttribute:
1941 * @reader: the xmlTextReaderPtr used
1942 * @name: the qualified name of the attribute.
1943 *
1944 * Moves the position of the current instance to the attribute with
1945 * the specified qualified name.
1946 *
1947 * Returns 1 in case of success, -1 in case of error, 0 if not found
1948 */
1949int
1950xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1951 xmlChar *prefix = NULL;
1952 xmlChar *localname;
1953 xmlNsPtr ns;
1954 xmlAttrPtr prop;
1955
1956 if ((reader == NULL) || (name == NULL))
1957 return(-1);
1958 if (reader->node == NULL)
1959 return(-1);
1960
1961 /* TODO: handle the xmlDecl */
1962 if (reader->node->type != XML_ELEMENT_NODE)
1963 return(0);
1964
1965 localname = xmlSplitQName2(name, &prefix);
1966 if (localname == NULL) {
1967 /*
1968 * Namespace default decl
1969 */
1970 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
1971 ns = reader->node->nsDef;
1972 while (ns != NULL) {
1973 if (ns->prefix == NULL) {
1974 reader->curnode = (xmlNodePtr) ns;
1975 return(1);
1976 }
1977 ns = ns->next;
1978 }
1979 return(0);
1980 }
1981
1982 prop = reader->node->properties;
1983 while (prop != NULL) {
1984 /*
1985 * One need to have
1986 * - same attribute names
1987 * - and the attribute carrying that namespace
1988 */
1989 if ((xmlStrEqual(prop->name, name)) &&
1990 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
1991 reader->curnode = (xmlNodePtr) prop;
1992 return(1);
1993 }
1994 prop = prop->next;
1995 }
1996 return(0);
1997 }
1998
1999 /*
2000 * Namespace default decl
2001 */
2002 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2003 ns = reader->node->nsDef;
2004 while (ns != NULL) {
2005 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2006 reader->curnode = (xmlNodePtr) ns;
2007 goto found;
2008 }
2009 ns = ns->next;
2010 }
2011 goto not_found;
2012 }
2013 prop = reader->node->properties;
2014 while (prop != NULL) {
2015 /*
2016 * One need to have
2017 * - same attribute names
2018 * - and the attribute carrying that namespace
2019 */
2020 if ((xmlStrEqual(prop->name, localname)) &&
2021 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2022 reader->curnode = (xmlNodePtr) prop;
2023 goto found;
2024 }
2025 prop = prop->next;
2026 }
2027not_found:
2028 if (localname != NULL)
2029 xmlFree(localname);
2030 if (prefix != NULL)
2031 xmlFree(prefix);
2032 return(0);
2033
2034found:
2035 if (localname != NULL)
2036 xmlFree(localname);
2037 if (prefix != NULL)
2038 xmlFree(prefix);
2039 return(1);
2040}
2041
2042/**
2043 * xmlTextReaderMoveToAttributeNs:
2044 * @reader: the xmlTextReaderPtr used
2045 * @localName: the local name of the attribute.
2046 * @namespaceURI: the namespace URI of the attribute.
2047 *
2048 * Moves the position of the current instance to the attribute with the
2049 * specified local name and namespace URI.
2050 *
2051 * Returns 1 in case of success, -1 in case of error, 0 if not found
2052 */
2053int
2054xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2055 const xmlChar *localName, const xmlChar *namespaceURI) {
2056 xmlAttrPtr prop;
2057 xmlNodePtr node;
2058
2059 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2060 return(-1);
2061 if (reader->node == NULL)
2062 return(-1);
2063 if (reader->node->type != XML_ELEMENT_NODE)
2064 return(0);
2065 node = reader->node;
2066
2067 /*
2068 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2069 * namespace name associated to "xmlns"
2070 */
2071 prop = node->properties;
2072 while (prop != NULL) {
2073 /*
2074 * One need to have
2075 * - same attribute names
2076 * - and the attribute carrying that namespace
2077 */
2078 if (xmlStrEqual(prop->name, localName) &&
2079 ((prop->ns != NULL) &&
2080 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2081 reader->curnode = (xmlNodePtr) prop;
2082 return(1);
2083 }
2084 prop = prop->next;
2085 }
2086 return(0);
2087}
2088
2089/**
2090 * xmlTextReaderMoveToFirstAttribute:
2091 * @reader: the xmlTextReaderPtr used
2092 *
2093 * Moves the position of the current instance to the first attribute
2094 * associated with the current node.
2095 *
2096 * Returns 1 in case of success, -1 in case of error, 0 if not found
2097 */
2098int
2099xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2100 if (reader == NULL)
2101 return(-1);
2102 if (reader->node == NULL)
2103 return(-1);
2104 if (reader->node->type != XML_ELEMENT_NODE)
2105 return(0);
2106
2107 if (reader->node->nsDef != NULL) {
2108 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2109 return(1);
2110 }
2111 if (reader->node->properties != NULL) {
2112 reader->curnode = (xmlNodePtr) reader->node->properties;
2113 return(1);
2114 }
2115 return(0);
2116}
2117
2118/**
2119 * xmlTextReaderMoveToNextAttribute:
2120 * @reader: the xmlTextReaderPtr used
2121 *
2122 * Moves the position of the current instance to the next attribute
2123 * associated with the current node.
2124 *
2125 * Returns 1 in case of success, -1 in case of error, 0 if not found
2126 */
2127int
2128xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2129 if (reader == NULL)
2130 return(-1);
2131 if (reader->node == NULL)
2132 return(-1);
2133 if (reader->node->type != XML_ELEMENT_NODE)
2134 return(0);
2135 if (reader->curnode == NULL)
2136 return(xmlTextReaderMoveToFirstAttribute(reader));
2137
2138 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2139 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2140 if (ns->next != NULL) {
2141 reader->curnode = (xmlNodePtr) ns->next;
2142 return(1);
2143 }
2144 if (reader->node->properties != NULL) {
2145 reader->curnode = (xmlNodePtr) reader->node->properties;
2146 return(1);
2147 }
2148 return(0);
2149 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2150 (reader->curnode->next != NULL)) {
2151 reader->curnode = reader->curnode->next;
2152 return(1);
2153 }
2154 return(0);
2155}
2156
2157/**
2158 * xmlTextReaderMoveToElement:
2159 * @reader: the xmlTextReaderPtr used
2160 *
2161 * Moves the position of the current instance to the node that
2162 * contains the current Attribute node.
2163 *
2164 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2165 */
2166int
2167xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2168 if (reader == NULL)
2169 return(-1);
2170 if (reader->node == NULL)
2171 return(-1);
2172 if (reader->node->type != XML_ELEMENT_NODE)
2173 return(0);
2174 if (reader->curnode != NULL) {
2175 reader->curnode = NULL;
2176 return(1);
2177 }
2178 return(0);
2179}
2180
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002181/**
2182 * xmlTextReaderReadAttributeValue:
2183 * @reader: the xmlTextReaderPtr used
2184 *
2185 * Parses an attribute value into one or more Text and EntityReference nodes.
2186 *
2187 * Returns 1 in case of success, 0 if the reader was not positionned on an
2188 * ttribute node or all the attribute values have been read, or -1
2189 * in case of error.
2190 */
2191int
2192xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2193 if (reader == NULL)
2194 return(-1);
2195 if (reader->node == NULL)
2196 return(-1);
2197 if (reader->curnode == NULL)
2198 return(0);
2199 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2200 if (reader->curnode->children == NULL)
2201 return(0);
2202 reader->curnode = reader->curnode->children;
2203 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2204 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2205
2206 if (reader->faketext == NULL) {
2207 reader->faketext = xmlNewDocText(reader->node->doc,
2208 ns->href);
2209 } else {
2210 if (reader->faketext->content != NULL)
2211 xmlFree(reader->faketext->content);
2212 reader->faketext->content = xmlStrdup(ns->href);
2213 }
2214 reader->curnode = reader->faketext;
2215 } else {
2216 if (reader->curnode->next == NULL)
2217 return(0);
2218 reader->curnode = reader->curnode->next;
2219 }
2220 return(1);
2221}
2222
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002223/************************************************************************
2224 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002225 * Acces API to the current node *
2226 * *
2227 ************************************************************************/
2228/**
2229 * xmlTextReaderAttributeCount:
2230 * @reader: the xmlTextReaderPtr used
2231 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002232 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002233 *
2234 * Returns 0 i no attributes, -1 in case of error or the attribute count
2235 */
2236int
2237xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2238 int ret;
2239 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002240 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002241 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002242
2243 if (reader == NULL)
2244 return(-1);
2245 if (reader->node == NULL)
2246 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002247
2248 if (reader->curnode != NULL)
2249 node = reader->curnode;
2250 else
2251 node = reader->node;
2252
2253 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002254 return(0);
2255 if ((reader->state == XML_TEXTREADER_END) ||
2256 (reader->state == XML_TEXTREADER_BACKTRACK))
2257 return(0);
2258 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002259 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002260 while (attr != NULL) {
2261 ret++;
2262 attr = attr->next;
2263 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002264 ns = node->nsDef;
2265 while (ns != NULL) {
2266 ret++;
2267 ns = ns->next;
2268 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002269 return(ret);
2270}
2271
2272/**
2273 * xmlTextReaderNodeType:
2274 * @reader: the xmlTextReaderPtr used
2275 *
2276 * Get the node type of the current node
2277 * Reference:
2278 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2279 *
2280 * Returns the xmlNodeType of the current node or -1 in case of error
2281 */
2282int
2283xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002284 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002285
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002286 if (reader == NULL)
2287 return(-1);
2288 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002289 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002290 if (reader->curnode != NULL)
2291 node = reader->curnode;
2292 else
2293 node = reader->node;
2294 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002295 case XML_ELEMENT_NODE:
2296 if ((reader->state == XML_TEXTREADER_END) ||
2297 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002298 return(XML_READER_TYPE_END_ELEMENT);
2299 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002300 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002301 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002302 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002303 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002304 if (xmlIsBlankNode(reader->node)) {
2305 if (xmlNodeGetSpacePreserve(reader->node))
2306 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2307 else
2308 return(XML_READER_TYPE_WHITESPACE);
2309 } else {
2310 return(XML_READER_TYPE_TEXT);
2311 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002312 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002313 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002314 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002315 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002316 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002317 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002318 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002319 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002320 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002321 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002322 case XML_DOCUMENT_NODE:
2323 case XML_HTML_DOCUMENT_NODE:
2324#ifdef LIBXML_DOCB_ENABLED
2325 case XML_DOCB_DOCUMENT_NODE:
2326#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002327 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002328 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002329 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002330 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002331 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002332 case XML_DOCUMENT_TYPE_NODE:
2333 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002334 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002335
2336 case XML_ELEMENT_DECL:
2337 case XML_ATTRIBUTE_DECL:
2338 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002339 case XML_XINCLUDE_START:
2340 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002341 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002342 }
2343 return(-1);
2344}
2345
2346/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002347 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002348 * @reader: the xmlTextReaderPtr used
2349 *
2350 * Check if the current node is empty
2351 *
2352 * Returns 1 if empty, 0 if not and -1 in case of error
2353 */
2354int
2355xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2356 if ((reader == NULL) || (reader->node == NULL))
2357 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002358 if (reader->node->type != XML_ELEMENT_NODE)
2359 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002360 if (reader->curnode != NULL)
2361 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002362 if (reader->node->children != NULL)
2363 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002364 if (reader->state == XML_TEXTREADER_END)
2365 return(0);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002366 return((reader->node->_private == (void *)xmlTextReaderIsEmpty) ||
2367 (reader->node->_private == (void *)xmlTextReaderIsEmptyPreserved));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002368}
2369
2370/**
2371 * xmlTextReaderLocalName:
2372 * @reader: the xmlTextReaderPtr used
2373 *
2374 * The local name of the node.
2375 *
2376 * Returns the local name or NULL if not available
2377 */
2378xmlChar *
2379xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002380 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002381 if ((reader == NULL) || (reader->node == NULL))
2382 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002383 if (reader->curnode != NULL)
2384 node = reader->curnode;
2385 else
2386 node = reader->node;
2387 if (node->type == XML_NAMESPACE_DECL) {
2388 xmlNsPtr ns = (xmlNsPtr) node;
2389 if (ns->prefix == NULL)
2390 return(xmlStrdup(BAD_CAST "xmlns"));
2391 else
2392 return(xmlStrdup(ns->prefix));
2393 }
2394 if ((node->type != XML_ELEMENT_NODE) &&
2395 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002396 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002397 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002398}
2399
2400/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002401 * xmlTextReaderConstLocalName:
2402 * @reader: the xmlTextReaderPtr used
2403 *
2404 * The local name of the node.
2405 *
2406 * Returns the local name or NULL if not available, the
2407 * string will be deallocated with the reader.
2408 */
2409const xmlChar *
2410xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2411 xmlNodePtr node;
2412 if ((reader == NULL) || (reader->node == NULL))
2413 return(NULL);
2414 if (reader->curnode != NULL)
2415 node = reader->curnode;
2416 else
2417 node = reader->node;
2418 if (node->type == XML_NAMESPACE_DECL) {
2419 xmlNsPtr ns = (xmlNsPtr) node;
2420 if (ns->prefix == NULL)
2421 return(CONSTSTR(BAD_CAST "xmlns"));
2422 else
2423 return(ns->prefix);
2424 }
2425 if ((node->type != XML_ELEMENT_NODE) &&
2426 (node->type != XML_ATTRIBUTE_NODE))
2427 return(xmlTextReaderConstName(reader));
2428 return(node->name);
2429}
2430
2431/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002432 * xmlTextReaderName:
2433 * @reader: the xmlTextReaderPtr used
2434 *
2435 * The qualified name of the node, equal to Prefix :LocalName.
2436 *
2437 * Returns the local name or NULL if not available
2438 */
2439xmlChar *
2440xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002441 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002442 xmlChar *ret;
2443
2444 if ((reader == NULL) || (reader->node == NULL))
2445 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002446 if (reader->curnode != NULL)
2447 node = reader->curnode;
2448 else
2449 node = reader->node;
2450 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002451 case XML_ELEMENT_NODE:
2452 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002453 if ((node->ns == NULL) ||
2454 (node->ns->prefix == NULL))
2455 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002456
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002457 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002458 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002459 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002460 return(ret);
2461 case XML_TEXT_NODE:
2462 return(xmlStrdup(BAD_CAST "#text"));
2463 case XML_CDATA_SECTION_NODE:
2464 return(xmlStrdup(BAD_CAST "#cdata-section"));
2465 case XML_ENTITY_NODE:
2466 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002467 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002468 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002469 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002470 case XML_COMMENT_NODE:
2471 return(xmlStrdup(BAD_CAST "#comment"));
2472 case XML_DOCUMENT_NODE:
2473 case XML_HTML_DOCUMENT_NODE:
2474#ifdef LIBXML_DOCB_ENABLED
2475 case XML_DOCB_DOCUMENT_NODE:
2476#endif
2477 return(xmlStrdup(BAD_CAST "#document"));
2478 case XML_DOCUMENT_FRAG_NODE:
2479 return(xmlStrdup(BAD_CAST "#document-fragment"));
2480 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002481 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002482 case XML_DOCUMENT_TYPE_NODE:
2483 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002484 return(xmlStrdup(node->name));
2485 case XML_NAMESPACE_DECL: {
2486 xmlNsPtr ns = (xmlNsPtr) node;
2487
2488 ret = xmlStrdup(BAD_CAST "xmlns");
2489 if (ns->prefix == NULL)
2490 return(ret);
2491 ret = xmlStrcat(ret, BAD_CAST ":");
2492 ret = xmlStrcat(ret, ns->prefix);
2493 return(ret);
2494 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002495
2496 case XML_ELEMENT_DECL:
2497 case XML_ATTRIBUTE_DECL:
2498 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002499 case XML_XINCLUDE_START:
2500 case XML_XINCLUDE_END:
2501 return(NULL);
2502 }
2503 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002504}
2505
2506/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002507 * xmlTextReaderConstName:
2508 * @reader: the xmlTextReaderPtr used
2509 *
2510 * The qualified name of the node, equal to Prefix :LocalName.
2511 *
2512 * Returns the local name or NULL if not available, the string is
2513 * deallocated with the reader.
2514 */
2515const xmlChar *
2516xmlTextReaderConstName(xmlTextReaderPtr reader) {
2517 xmlNodePtr node;
2518
2519 if ((reader == NULL) || (reader->node == NULL))
2520 return(NULL);
2521 if (reader->curnode != NULL)
2522 node = reader->curnode;
2523 else
2524 node = reader->node;
2525 switch (node->type) {
2526 case XML_ELEMENT_NODE:
2527 case XML_ATTRIBUTE_NODE:
2528 if ((node->ns == NULL) ||
2529 (node->ns->prefix == NULL))
2530 return(node->name);
2531 return(CONSTQSTR(node->ns->prefix, node->name));
2532 case XML_TEXT_NODE:
2533 return(CONSTSTR(BAD_CAST "#text"));
2534 case XML_CDATA_SECTION_NODE:
2535 return(CONSTSTR(BAD_CAST "#cdata-section"));
2536 case XML_ENTITY_NODE:
2537 case XML_ENTITY_REF_NODE:
2538 return(CONSTSTR(node->name));
2539 case XML_PI_NODE:
2540 return(CONSTSTR(node->name));
2541 case XML_COMMENT_NODE:
2542 return(CONSTSTR(BAD_CAST "#comment"));
2543 case XML_DOCUMENT_NODE:
2544 case XML_HTML_DOCUMENT_NODE:
2545#ifdef LIBXML_DOCB_ENABLED
2546 case XML_DOCB_DOCUMENT_NODE:
2547#endif
2548 return(CONSTSTR(BAD_CAST "#document"));
2549 case XML_DOCUMENT_FRAG_NODE:
2550 return(CONSTSTR(BAD_CAST "#document-fragment"));
2551 case XML_NOTATION_NODE:
2552 return(CONSTSTR(node->name));
2553 case XML_DOCUMENT_TYPE_NODE:
2554 case XML_DTD_NODE:
2555 return(CONSTSTR(node->name));
2556 case XML_NAMESPACE_DECL: {
2557 xmlNsPtr ns = (xmlNsPtr) node;
2558
2559 if (ns->prefix == NULL)
2560 return(CONSTSTR(BAD_CAST "xmlns"));
2561 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2562 }
2563
2564 case XML_ELEMENT_DECL:
2565 case XML_ATTRIBUTE_DECL:
2566 case XML_ENTITY_DECL:
2567 case XML_XINCLUDE_START:
2568 case XML_XINCLUDE_END:
2569 return(NULL);
2570 }
2571 return(NULL);
2572}
2573
2574/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002575 * xmlTextReaderPrefix:
2576 * @reader: the xmlTextReaderPtr used
2577 *
2578 * A shorthand reference to the namespace associated with the node.
2579 *
2580 * Returns the prefix or NULL if not available
2581 */
2582xmlChar *
2583xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002584 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002585 if ((reader == NULL) || (reader->node == NULL))
2586 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002587 if (reader->curnode != NULL)
2588 node = reader->curnode;
2589 else
2590 node = reader->node;
2591 if (node->type == XML_NAMESPACE_DECL) {
2592 xmlNsPtr ns = (xmlNsPtr) node;
2593 if (ns->prefix == NULL)
2594 return(NULL);
2595 return(xmlStrdup(BAD_CAST "xmlns"));
2596 }
2597 if ((node->type != XML_ELEMENT_NODE) &&
2598 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002599 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002600 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002601 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002602 return(NULL);
2603}
2604
2605/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002606 * xmlTextReaderConstPrefix:
2607 * @reader: the xmlTextReaderPtr used
2608 *
2609 * A shorthand reference to the namespace associated with the node.
2610 *
2611 * Returns the prefix or NULL if not available, the string is deallocated
2612 * with the reader.
2613 */
2614const xmlChar *
2615xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2616 xmlNodePtr node;
2617 if ((reader == NULL) || (reader->node == NULL))
2618 return(NULL);
2619 if (reader->curnode != NULL)
2620 node = reader->curnode;
2621 else
2622 node = reader->node;
2623 if (node->type == XML_NAMESPACE_DECL) {
2624 xmlNsPtr ns = (xmlNsPtr) node;
2625 if (ns->prefix == NULL)
2626 return(NULL);
2627 return(CONSTSTR(BAD_CAST "xmlns"));
2628 }
2629 if ((node->type != XML_ELEMENT_NODE) &&
2630 (node->type != XML_ATTRIBUTE_NODE))
2631 return(NULL);
2632 if ((node->ns != NULL) && (node->ns->prefix != NULL))
2633 return(CONSTSTR(node->ns->prefix));
2634 return(NULL);
2635}
2636
2637/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002638 * xmlTextReaderNamespaceUri:
2639 * @reader: the xmlTextReaderPtr used
2640 *
2641 * The URI defining the namespace associated with the node.
2642 *
2643 * Returns the namespace URI or NULL if not available
2644 */
2645xmlChar *
2646xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002647 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002648 if ((reader == NULL) || (reader->node == NULL))
2649 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002650 if (reader->curnode != NULL)
2651 node = reader->curnode;
2652 else
2653 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00002654 if (node->type == XML_NAMESPACE_DECL)
2655 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002656 if ((node->type != XML_ELEMENT_NODE) &&
2657 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002658 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002659 if (node->ns != NULL)
2660 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002661 return(NULL);
2662}
2663
2664/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002665 * xmlTextReaderConstNamespaceUri:
2666 * @reader: the xmlTextReaderPtr used
2667 *
2668 * The URI defining the namespace associated with the node.
2669 *
2670 * Returns the namespace URI or NULL if not available, the string
2671 * will be deallocated with the reader
2672 */
2673const xmlChar *
2674xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
2675 xmlNodePtr node;
2676 if ((reader == NULL) || (reader->node == NULL))
2677 return(NULL);
2678 if (reader->curnode != NULL)
2679 node = reader->curnode;
2680 else
2681 node = reader->node;
2682 if (node->type == XML_NAMESPACE_DECL)
2683 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
2684 if ((node->type != XML_ELEMENT_NODE) &&
2685 (node->type != XML_ATTRIBUTE_NODE))
2686 return(NULL);
2687 if (node->ns != NULL)
2688 return(CONSTSTR(node->ns->href));
2689 return(NULL);
2690}
2691
2692/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002693 * xmlTextReaderBaseUri:
2694 * @reader: the xmlTextReaderPtr used
2695 *
2696 * The base URI of the node.
2697 *
2698 * Returns the base URI or NULL if not available
2699 */
2700xmlChar *
2701xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
2702 if ((reader == NULL) || (reader->node == NULL))
2703 return(NULL);
2704 return(xmlNodeGetBase(NULL, reader->node));
2705}
2706
2707/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002708 * xmlTextReaderConstBaseUri:
2709 * @reader: the xmlTextReaderPtr used
2710 *
2711 * The base URI of the node.
2712 *
2713 * Returns the base URI or NULL if not available, the string
2714 * will be deallocated with the reader
2715 */
2716const xmlChar *
2717xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
2718 xmlChar *tmp;
2719 const xmlChar *ret;
2720
2721 if ((reader == NULL) || (reader->node == NULL))
2722 return(NULL);
2723 tmp = xmlNodeGetBase(NULL, reader->node);
2724 if (tmp == NULL)
2725 return(NULL);
2726 ret = CONSTSTR(tmp);
2727 xmlFree(tmp);
2728 return(ret);
2729}
2730
2731/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002732 * xmlTextReaderDepth:
2733 * @reader: the xmlTextReaderPtr used
2734 *
2735 * The depth of the node in the tree.
2736 *
2737 * Returns the depth or -1 in case of error
2738 */
2739int
2740xmlTextReaderDepth(xmlTextReaderPtr reader) {
2741 if (reader == NULL)
2742 return(-1);
2743 if (reader->node == NULL)
2744 return(0);
2745
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002746 if (reader->curnode != NULL) {
2747 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
2748 (reader->curnode->type == XML_NAMESPACE_DECL))
2749 return(reader->depth + 1);
2750 return(reader->depth + 2);
2751 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002752 return(reader->depth);
2753}
2754
2755/**
2756 * xmlTextReaderHasAttributes:
2757 * @reader: the xmlTextReaderPtr used
2758 *
2759 * Whether the node has attributes.
2760 *
2761 * Returns 1 if true, 0 if false, and -1 in case or error
2762 */
2763int
2764xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002765 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002766 if (reader == NULL)
2767 return(-1);
2768 if (reader->node == NULL)
2769 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002770 if (reader->curnode != NULL)
2771 node = reader->curnode;
2772 else
2773 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002774
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002775 if ((node->type == XML_ELEMENT_NODE) &&
2776 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002777 return(1);
2778 /* TODO: handle the xmlDecl */
2779 return(0);
2780}
2781
2782/**
2783 * xmlTextReaderHasValue:
2784 * @reader: the xmlTextReaderPtr used
2785 *
2786 * Whether the node can have a text value.
2787 *
2788 * Returns 1 if true, 0 if false, and -1 in case or error
2789 */
2790int
2791xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002792 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002793 if (reader == NULL)
2794 return(-1);
2795 if (reader->node == NULL)
2796 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002797 if (reader->curnode != NULL)
2798 node = reader->curnode;
2799 else
2800 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002801
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002802 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002803 case XML_ATTRIBUTE_NODE:
2804 case XML_TEXT_NODE:
2805 case XML_CDATA_SECTION_NODE:
2806 case XML_PI_NODE:
2807 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00002808 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002809 return(1);
2810 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002811 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002812 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002813 return(0);
2814}
2815
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002816/**
2817 * xmlTextReaderValue:
2818 * @reader: the xmlTextReaderPtr used
2819 *
2820 * Provides the text value of the node if present
2821 *
2822 * Returns the string or NULL if not available. The retsult must be deallocated
2823 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002824 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002825xmlChar *
2826xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002827 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002828 if (reader == NULL)
2829 return(NULL);
2830 if (reader->node == NULL)
2831 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002832 if (reader->curnode != NULL)
2833 node = reader->curnode;
2834 else
2835 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002836
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002837 switch (node->type) {
2838 case XML_NAMESPACE_DECL:
2839 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002840 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002841 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002842
2843 if (attr->parent != NULL)
2844 return (xmlNodeListGetString
2845 (attr->parent->doc, attr->children, 1));
2846 else
2847 return (xmlNodeListGetString(NULL, attr->children, 1));
2848 break;
2849 }
2850 case XML_TEXT_NODE:
2851 case XML_CDATA_SECTION_NODE:
2852 case XML_PI_NODE:
2853 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002854 if (node->content != NULL)
2855 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002856 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002857 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002858 }
2859 return(NULL);
2860}
2861
2862/**
2863 * xmlTextReaderIsDefault:
2864 * @reader: the xmlTextReaderPtr used
2865 *
2866 * Whether an Attribute node was generated from the default value
2867 * defined in the DTD or schema.
2868 *
2869 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
2870 */
2871int
2872xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
2873 if (reader == NULL)
2874 return(-1);
2875 return(0);
2876}
2877
2878/**
2879 * xmlTextReaderQuoteChar:
2880 * @reader: the xmlTextReaderPtr used
2881 *
2882 * The quotation mark character used to enclose the value of an attribute.
2883 *
2884 * Returns " or ' and -1 in case of error
2885 */
2886int
2887xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
2888 if (reader == NULL)
2889 return(-1);
2890 /* TODO maybe lookup the attribute value for " first */
2891 return((int) '"');
2892}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002893
2894/**
2895 * xmlTextReaderXmlLang:
2896 * @reader: the xmlTextReaderPtr used
2897 *
2898 * The xml:lang scope within which the node resides.
2899 *
2900 * Returns the xml:lang value or NULL if none exists.
2901 */
2902xmlChar *
2903xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
2904 if (reader == NULL)
2905 return(NULL);
2906 if (reader->node == NULL)
2907 return(NULL);
2908 return(xmlNodeGetLang(reader->node));
2909}
2910
Daniel Veillard67df8092002-12-16 22:04:11 +00002911/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002912 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00002913 * @reader: the xmlTextReaderPtr used
2914 *
2915 * The xml:lang scope within which the node resides.
2916 *
2917 * Returns the xml:lang value or NULL if none exists.
2918 */
2919const xmlChar *
2920xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
2921 xmlChar *tmp;
2922 const xmlChar *ret;
2923
2924 if (reader == NULL)
2925 return(NULL);
2926 if (reader->node == NULL)
2927 return(NULL);
2928 tmp = xmlNodeGetLang(reader->node);
2929 if (tmp == NULL)
2930 return(NULL);
2931 ret = CONSTSTR(tmp);
2932 xmlFree(tmp);
2933 return(ret);
2934}
2935
2936/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00002937 * xmlTextReaderConstString:
2938 * @reader: the xmlTextReaderPtr used
2939 * @str: the string to intern.
2940 *
2941 * Get an interned string from the reader, allows for example to
2942 * speedup string name comparisons
2943 *
2944 * Returns an interned copy of the string or NULL in case of error. The
2945 * string will be deallocated with the reader.
2946 */
2947const xmlChar *
2948xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
2949 if (reader == NULL)
2950 return(NULL);
2951 return(CONSTSTR(str));
2952}
2953
2954/**
Daniel Veillard67df8092002-12-16 22:04:11 +00002955 * xmlTextReaderNormalization:
2956 * @reader: the xmlTextReaderPtr used
2957 *
2958 * The value indicating whether to normalize white space and attribute values.
2959 * Since attribute value and end of line normalizations are a MUST in the XML
2960 * specification only the value true is accepted. The broken bahaviour of
2961 * accepting out of range character entities like &#0; is of course not
2962 * supported either.
2963 *
2964 * Returns 1 or -1 in case of error.
2965 */
2966int
2967xmlTextReaderNormalization(xmlTextReaderPtr reader) {
2968 if (reader == NULL)
2969 return(-1);
2970 return(1);
2971}
2972
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002973/************************************************************************
2974 * *
2975 * Extensions to the base APIs *
2976 * *
2977 ************************************************************************/
2978
2979/**
2980 * xmlTextReaderSetParserProp:
2981 * @reader: the xmlTextReaderPtr used
2982 * @prop: the xmlParserProperties to set
2983 * @value: usually 0 or 1 to (de)activate it
2984 *
2985 * Change the parser processing behaviour by changing some of its internal
2986 * properties. Note that some properties can only be changed before any
2987 * read has been done.
2988 *
2989 * Returns 0 if the call was successful, or -1 in case of error
2990 */
2991int
2992xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
2993 xmlParserProperties p = (xmlParserProperties) prop;
2994 xmlParserCtxtPtr ctxt;
2995
2996 if ((reader == NULL) || (reader->ctxt == NULL))
2997 return(-1);
2998 ctxt = reader->ctxt;
2999
3000 switch (p) {
3001 case XML_PARSER_LOADDTD:
3002 if (value != 0) {
3003 if (ctxt->loadsubset == 0) {
3004 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3005 return(-1);
3006 ctxt->loadsubset = XML_DETECT_IDS;
3007 }
3008 } else {
3009 ctxt->loadsubset = 0;
3010 }
3011 return(0);
3012 case XML_PARSER_DEFAULTATTRS:
3013 if (value != 0) {
3014 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3015 } else {
3016 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3017 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3018 }
3019 return(0);
3020 case XML_PARSER_VALIDATE:
3021 if (value != 0) {
3022 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003023 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003024 } else {
3025 ctxt->validate = 0;
3026 }
3027 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003028 case XML_PARSER_SUBST_ENTITIES:
3029 if (value != 0) {
3030 ctxt->replaceEntities = 1;
3031 } else {
3032 ctxt->replaceEntities = 0;
3033 }
3034 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003035 }
3036 return(-1);
3037}
3038
3039/**
3040 * xmlTextReaderGetParserProp:
3041 * @reader: the xmlTextReaderPtr used
3042 * @prop: the xmlParserProperties to get
3043 *
3044 * Read the parser internal property.
3045 *
3046 * Returns the value, usually 0 or 1, or -1 in case of error.
3047 */
3048int
3049xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3050 xmlParserProperties p = (xmlParserProperties) prop;
3051 xmlParserCtxtPtr ctxt;
3052
3053 if ((reader == NULL) || (reader->ctxt == NULL))
3054 return(-1);
3055 ctxt = reader->ctxt;
3056
3057 switch (p) {
3058 case XML_PARSER_LOADDTD:
3059 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3060 return(1);
3061 return(0);
3062 case XML_PARSER_DEFAULTATTRS:
3063 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3064 return(1);
3065 return(0);
3066 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003067 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003068 case XML_PARSER_SUBST_ENTITIES:
3069 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003070 }
3071 return(-1);
3072}
3073
Daniel Veillarde18fc182002-12-28 22:56:33 +00003074/**
3075 * xmlTextReaderCurrentNode:
3076 * @reader: the xmlTextReaderPtr used
3077 *
3078 * Hacking interface allowing to get the xmlNodePtr correponding to the
3079 * current node being accessed by the xmlTextReader. This is dangerous
3080 * because the underlying node may be destroyed on the next Reads.
3081 *
3082 * Returns the xmlNodePtr or NULL in case of error.
3083 */
3084xmlNodePtr
3085xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3086 if (reader == NULL)
3087 return(NULL);
3088
3089 if (reader->curnode != NULL)
3090 return(reader->curnode);
3091 return(reader->node);
3092}
3093
3094/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003095 * xmlTextReaderPreserve:
3096 * @reader: the xmlTextReaderPtr used
3097 *
3098 *
3099 * current node being accessed by the xmlTextReader. This is dangerous
3100 * because the underlying node may be destroyed on the next Reads.
3101 *
3102 * Returns the xmlNodePtr or NULL in case of error.
3103 */
3104xmlNodePtr
3105xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3106 xmlNodePtr cur, parent;
3107
3108 if (reader == NULL)
3109 return(NULL);
3110
3111 if (reader->curnode != NULL)
3112 cur = reader->curnode;
3113 else
3114 cur = reader->node;
3115 if (cur == NULL)
3116 return(NULL);
3117 if (cur->_private == (void *)xmlTextReaderIsEmpty)
3118 cur->_private = (void *)xmlTextReaderIsEmptyPreserved;
3119 else
3120 cur->_private = (void *)xmlTextReaderIsPreserved;
3121
3122 parent = cur->parent;;
3123 while (parent != NULL) {
3124 parent->_private = (void *)xmlTextReaderIsPreserved;
3125 parent = parent->parent;
3126 }
3127 return(cur);
3128}
3129
3130/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003131 * xmlTextReaderCurrentDoc:
3132 * @reader: the xmlTextReaderPtr used
3133 *
3134 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003135 * current document being accessed by the xmlTextReader.
3136 * NOTE: as a result of this call, the reader will not destroy the
3137 * associated XML document and calling xmlFreeDoc() on the result
3138 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003139 *
3140 * Returns the xmlDocPtr or NULL in case of error.
3141 */
3142xmlDocPtr
3143xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003144 if ((reader == NULL) || (reader->ctxt == NULL) ||
3145 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003146 return(NULL);
3147
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003148 reader->preserve = 1;
3149 if ((reader->ctxt->myDoc->dict != NULL) &&
3150 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3151 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003152 return(reader->ctxt->myDoc);
3153}
3154
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003155#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003156/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003157 * xmlTextReaderRelaxNGSetSchema:
3158 * @reader: the xmlTextReaderPtr used
3159 * @schema: a precompiled RelaxNG schema
3160 *
3161 * Use RelaxNG to validate the document as it is processed.
3162 * Activation is only possible before the first Read().
3163 * if @schema is NULL, then RelaxNG validation is desactivated.
3164 @ The @schema should not be freed until the reader is deallocated
3165 * or its use has been deactivated.
3166 *
3167 * Returns 0 in case the RelaxNG validation could be (des)activated and
3168 * -1 in case of error.
3169 */
3170int
3171xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3172 if (schema == NULL) {
3173 if (reader->rngSchemas != NULL) {
3174 xmlRelaxNGFree(reader->rngSchemas);
3175 reader->rngSchemas = NULL;
3176 }
3177 if (reader->rngValidCtxt != NULL) {
3178 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3179 reader->rngValidCtxt = NULL;
3180 }
3181 return(0);
3182 }
3183 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3184 return(-1);
3185 if (reader->rngSchemas != NULL) {
3186 xmlRelaxNGFree(reader->rngSchemas);
3187 reader->rngSchemas = NULL;
3188 }
3189 if (reader->rngValidCtxt != NULL) {
3190 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3191 reader->rngValidCtxt = NULL;
3192 }
3193 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3194 if (reader->rngValidCtxt == NULL)
3195 return(-1);
3196 if (reader->errorFunc != NULL) {
3197 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3198 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3199 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3200 reader->errorFuncArg);
3201 }
3202 reader->rngValidErrors = 0;
3203 reader->rngFullNode = NULL;
3204 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3205 return(0);
3206}
3207
3208/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003209 * xmlTextReaderRelaxNGValidate:
3210 * @reader: the xmlTextReaderPtr used
3211 * @rng: the path to a RelaxNG schema or NULL
3212 *
3213 * Use RelaxNG to validate the document as it is processed.
3214 * Activation is only possible before the first Read().
3215 * if @rng is NULL, then RelaxNG validation is desactivated.
3216 *
3217 * Returns 0 in case the RelaxNG validation could be (des)activated and
3218 * -1 in case of error.
3219 */
3220int
3221xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3222 xmlRelaxNGParserCtxtPtr ctxt;
3223
3224 if (reader == NULL)
3225 return(-1);
3226
3227 if (rng == NULL) {
3228 if (reader->rngSchemas != NULL) {
3229 xmlRelaxNGFree(reader->rngSchemas);
3230 reader->rngSchemas = NULL;
3231 }
3232 if (reader->rngValidCtxt != NULL) {
3233 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3234 reader->rngValidCtxt = NULL;
3235 }
3236 return(0);
3237 }
3238 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3239 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003240 if (reader->rngSchemas != NULL) {
3241 xmlRelaxNGFree(reader->rngSchemas);
3242 reader->rngSchemas = NULL;
3243 }
3244 if (reader->rngValidCtxt != NULL) {
3245 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3246 reader->rngValidCtxt = NULL;
3247 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003248 ctxt = xmlRelaxNGNewParserCtxt(rng);
3249 if (reader->errorFunc != NULL) {
3250 xmlRelaxNGSetParserErrors(ctxt,
3251 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3252 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3253 reader->errorFuncArg);
3254 }
3255 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3256 xmlRelaxNGFreeParserCtxt(ctxt);
3257 if (reader->rngSchemas == NULL)
3258 return(-1);
3259 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3260 if (reader->rngValidCtxt == NULL)
3261 return(-1);
3262 if (reader->errorFunc != NULL) {
3263 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3264 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3265 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3266 reader->errorFuncArg);
3267 }
3268 reader->rngValidErrors = 0;
3269 reader->rngFullNode = NULL;
3270 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3271 return(0);
3272}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003273#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003274
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003275/************************************************************************
3276 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003277 * Error Handling Extensions *
3278 * *
3279 ************************************************************************/
3280
3281/* helper to build a xmlMalloc'ed string from a format and va_list */
3282static char *
3283xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3284 int size;
3285 int chars;
3286 char *larger;
3287 char *str;
3288
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003289 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003290 if (str == NULL) {
3291 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3292 return NULL;
3293 }
3294
3295 size = 150;
3296
3297 while (1) {
3298 chars = vsnprintf(str, size, msg, ap);
3299 if ((chars > -1) && (chars < size))
3300 break;
3301 if (chars > -1)
3302 size += chars + 1;
3303 else
3304 size += 100;
3305 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3306 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3307 xmlFree(str);
3308 return NULL;
3309 }
3310 str = larger;
3311 }
3312
3313 return str;
3314}
3315
Daniel Veillard417be3a2003-01-20 21:26:34 +00003316/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003317 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003318 * @locator: the xmlTextReaderLocatorPtr used
3319 *
3320 * Obtain the line number for the given locator.
3321 *
3322 * Returns the line number or -1 in case of error.
3323 */
3324int
3325xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3326 /* we know that locator is a xmlParserCtxtPtr */
3327 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3328 int ret = -1;
3329
3330 if (ctx->node != NULL) {
3331 ret = xmlGetLineNo(ctx->node);
3332 }
3333 else {
3334 /* inspired from error.c */
3335 xmlParserInputPtr input;
3336 input = ctx->input;
3337 if ((input->filename == NULL) && (ctx->inputNr > 1))
3338 input = ctx->inputTab[ctx->inputNr - 2];
3339 if (input != NULL) {
3340 ret = input->line;
3341 }
3342 else {
3343 ret = -1;
3344 }
3345 }
3346
3347 return ret;
3348}
3349
3350/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003351 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003352 * @locator: the xmlTextReaderLocatorPtr used
3353 *
3354 * Obtain the base URI for the given locator.
3355 *
3356 * Returns the base URI or NULL in case of error.
3357 */
3358xmlChar *
3359xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3360 /* we know that locator is a xmlParserCtxtPtr */
3361 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3362 xmlChar *ret = NULL;
3363
3364 if (ctx->node != NULL) {
3365 ret = xmlNodeGetBase(NULL,ctx->node);
3366 }
3367 else {
3368 /* inspired from error.c */
3369 xmlParserInputPtr input;
3370 input = ctx->input;
3371 if ((input->filename == NULL) && (ctx->inputNr > 1))
3372 input = ctx->inputTab[ctx->inputNr - 2];
3373 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003374 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003375 }
3376 else {
3377 ret = NULL;
3378 }
3379 }
3380
3381 return ret;
3382}
3383
Daniel Veillard26f70262003-01-16 22:45:08 +00003384static void
William M. Brack899e64a2003-09-26 18:03:42 +00003385xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003386 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3387 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3388
3389 if (str != NULL) {
3390 reader->errorFunc(reader->errorFuncArg,
3391 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003392 severity,
3393 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003394 xmlFree(str);
3395 }
3396}
3397
3398static void
3399xmlTextReaderError(void *ctxt, const char *msg, ...) {
3400 va_list ap;
3401
3402 va_start(ap,msg);
3403 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003404 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003405 xmlTextReaderBuildMessage(msg,ap));
3406 va_end(ap);
3407
3408}
3409
3410static void
3411xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3412 va_list ap;
3413
3414 va_start(ap,msg);
3415 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003416 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003417 xmlTextReaderBuildMessage(msg,ap));
3418 va_end(ap);
3419}
3420
3421static void
3422xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3423 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003424 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003425
Daniel Veillard417be3a2003-01-20 21:26:34 +00003426 if ((len > 1) && (msg[len - 2] != ':')) {
3427 /*
3428 * some callbacks only report locator information:
3429 * skip them (mimicking behaviour in error.c)
3430 */
3431 va_start(ap,msg);
3432 xmlTextReaderGenericError(ctxt,
3433 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3434 xmlTextReaderBuildMessage(msg,ap));
3435 va_end(ap);
3436 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003437}
3438
3439static void
3440xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3441 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003442 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003443
Daniel Veillard417be3a2003-01-20 21:26:34 +00003444 if ((len != 0) && (msg[len - 1] != ':')) {
3445 /*
3446 * some callbacks only report locator information:
3447 * skip them (mimicking behaviour in error.c)
3448 */
3449 va_start(ap,msg);
3450 xmlTextReaderGenericError(ctxt,
3451 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3452 xmlTextReaderBuildMessage(msg,ap));
3453 va_end(ap);
3454 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003455}
3456
3457/**
3458 * xmlTextReaderSetErrorHandler:
3459 * @reader: the xmlTextReaderPtr used
3460 * @f: the callback function to call on error and warnings
3461 * @arg: a user argument to pass to the callback function
3462 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003463 * Register a callback function that will be called on error and warnings.
3464 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003465 * If @f is NULL, the default error and warning handlers are restored.
3466 */
3467void
3468xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3469 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003470 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003471 if (f != NULL) {
3472 reader->ctxt->sax->error = xmlTextReaderError;
3473 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3474 reader->ctxt->sax->warning = xmlTextReaderWarning;
3475 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3476 reader->errorFunc = f;
3477 reader->errorFuncArg = arg;
3478 }
3479 else {
3480 /* restore defaults */
3481 reader->ctxt->sax->error = xmlParserError;
3482 reader->ctxt->vctxt.error = xmlParserValidityError;
3483 reader->ctxt->sax->warning = xmlParserWarning;
3484 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3485 reader->errorFunc = NULL;
3486 reader->errorFuncArg = NULL;
3487 }
3488}
3489
Daniel Veillard417be3a2003-01-20 21:26:34 +00003490/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003491 * xmlTextReaderIsValid:
3492 * @reader: the xmlTextReaderPtr used
3493 *
3494 * Retrieve the validity status from the parser context
3495 *
3496 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3497 */
3498int
3499xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003500 if (reader == NULL) return(-1);
3501#ifdef LIBXML_SCHEMAS_ENABLED
3502 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3503 return(reader->rngValidErrors == 0);
3504#endif
3505 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3506 (reader->ctxt != NULL))
3507 return(reader->ctxt->valid);
3508 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003509}
3510
3511/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003512 * xmlTextReaderGetErrorHandler:
3513 * @reader: the xmlTextReaderPtr used
3514 * @f: the callback function or NULL is no callback has been registered
3515 * @arg: a user argument
3516 *
3517 * Retrieve the error callback function and user argument.
3518 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003519void
3520xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3521 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003522 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003523 *f = reader->errorFunc;
3524 *arg = reader->errorFuncArg;
3525}
3526
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003527
3528/************************************************************************
3529 * *
3530 * New set (2.6.0) of simpler and more flexible APIs *
3531 * *
3532 ************************************************************************/
3533
3534/**
3535 * xmlTextReaderSetup:
3536 * @reader: an XML reader
3537 * @URL: the base URL to use for the document
3538 * @encoding: the document encoding, or NULL
3539 * @options: a combination of xmlParserOption(s)
3540 * @reuse: keep the context for reuse
3541 *
3542 * Setup an XML reader with new options
3543 *
3544 * Returns 0 in case of success and -1 in case of error.
3545 */
3546static int
3547xmlTextReaderSetup(xmlTextReaderPtr reader, const char *URL,
3548 const char *encoding, int options)
3549{
3550 if ((reader == NULL) || (reader->ctxt == NULL))
3551 return (-1);
3552
3553 xmlCtxtUseOptions(reader->ctxt, options);
3554 if (encoding != NULL) {
3555 xmlCharEncodingHandlerPtr hdlr;
3556
3557 hdlr = xmlFindCharEncodingHandler(encoding);
3558 if (hdlr != NULL)
3559 xmlSwitchToEncoding(reader->ctxt, hdlr);
3560 }
3561 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
3562 (reader->ctxt->input->filename == NULL))
3563 reader->ctxt->input->filename = (char *)
3564 xmlStrdup((const xmlChar *) URL);
3565 return (0);
3566}
3567
3568/**
3569 * xmlReaderForDoc:
3570 * @cur: a pointer to a zero terminated string
3571 * @URL: the base URL to use for the document
3572 * @encoding: the document encoding, or NULL
3573 * @options: a combination of xmlParserOption(s)
3574 *
3575 * Create an xmltextReader for an XML in-memory document.
3576 *
3577 * Returns the new reader or NULL in case of error.
3578 */
3579xmlTextReaderPtr
3580xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
3581 int options)
3582{
3583 int len;
3584
3585 if (cur == NULL)
3586 return (NULL);
3587 len = xmlStrlen(cur);
3588
3589 return (xmlReaderForMemory
3590 ((const char *) cur, len, URL, encoding, options));
3591}
3592
3593/**
3594 * xmlReaderForFile:
3595 * @filename: a file or URL
3596 * @encoding: the document encoding, or NULL
3597 * @options: a combination of xmlParserOption(s)
3598 *
3599 * parse an XML file from the filesystem or the network.
3600 *
3601 * Returns the new reader or NULL in case of error.
3602 */
3603xmlTextReaderPtr
3604xmlReaderForFile(const char *filename, const char *encoding, int options)
3605{
3606 xmlTextReaderPtr reader;
3607
3608 reader = xmlNewTextReaderFilename(filename);
3609 if (reader == NULL)
3610 return (NULL);
3611 xmlTextReaderSetup(reader, NULL, encoding, options);
3612 return (reader);
3613}
3614
3615/**
3616 * xmlReaderForMemory:
3617 * @buffer: a pointer to a char array
3618 * @size: the size of the array
3619 * @URL: the base URL to use for the document
3620 * @encoding: the document encoding, or NULL
3621 * @options: a combination of xmlParserOption(s)
3622 *
3623 * Create an xmltextReader for an XML in-memory document.
3624 *
3625 * Returns the new reader or NULL in case of error.
3626 */
3627xmlTextReaderPtr
3628xmlReaderForMemory(const char *buffer, int size, const char *URL,
3629 const char *encoding, int options)
3630{
3631 xmlTextReaderPtr reader;
3632 xmlParserInputBufferPtr buf;
3633
3634 buf =
3635 xmlParserInputBufferCreateMem(buffer, size,
3636 XML_CHAR_ENCODING_NONE);
3637 if (buf == NULL) {
3638 return (NULL);
3639 }
3640 reader = xmlNewTextReader(buf, URL);
3641 if (reader == NULL) {
3642 xmlFreeParserInputBuffer(buf);
3643 return (NULL);
3644 }
3645 xmlTextReaderSetup(reader, URL, encoding, options);
3646 return (reader);
3647}
3648
3649/**
3650 * xmlReaderForFd:
3651 * @fd: an open file descriptor
3652 * @URL: the base URL to use for the document
3653 * @encoding: the document encoding, or NULL
3654 * @options: a combination of xmlParserOption(s)
3655 *
3656 * Create an xmltextReader for an XML from a file descriptor.
3657 *
3658 * Returns the new reader or NULL in case of error.
3659 */
3660xmlTextReaderPtr
3661xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
3662{
3663 xmlTextReaderPtr reader;
3664 xmlParserInputBufferPtr input;
3665
3666 if (fd < 0)
3667 return (NULL);
3668
3669 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
3670 if (input == NULL)
3671 return (NULL);
3672 reader = xmlNewTextReader(input, URL);
3673 if (reader == NULL) {
3674 xmlFreeParserInputBuffer(input);
3675 return (NULL);
3676 }
3677 xmlTextReaderSetup(reader, URL, encoding, options);
3678 return (reader);
3679}
3680
3681/**
3682 * xmlReaderForIO:
3683 * @ioread: an I/O read function
3684 * @ioclose: an I/O close function
3685 * @ioctx: an I/O handler
3686 * @URL: the base URL to use for the document
3687 * @encoding: the document encoding, or NULL
3688 * @options: a combination of xmlParserOption(s)
3689 *
3690 * Create an xmltextReader for an XML document from I/O functions and source.
3691 *
3692 * Returns the new reader or NULL in case of error.
3693 */
3694xmlTextReaderPtr
3695xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
3696 void *ioctx, const char *URL, const char *encoding,
3697 int options)
3698{
3699 xmlTextReaderPtr reader;
3700 xmlParserInputBufferPtr input;
3701
3702 if (ioread == NULL)
3703 return (NULL);
3704
3705 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
3706 XML_CHAR_ENCODING_NONE);
3707 if (input == NULL)
3708 return (NULL);
3709 reader = xmlNewTextReader(input, URL);
3710 if (reader == NULL) {
3711 xmlFreeParserInputBuffer(input);
3712 return (NULL);
3713 }
3714 xmlTextReaderSetup(reader, URL, encoding, options);
3715 return (reader);
3716}
3717
3718/**
3719 * xmlReaderNewDoc:
3720 * @reader: an XML reader
3721 * @cur: a pointer to a zero terminated string
3722 * @URL: the base URL to use for the document
3723 * @encoding: the document encoding, or NULL
3724 * @options: a combination of xmlParserOption(s)
3725 *
3726 * Setup an xmltextReader to parse an XML in-memory document.
3727 * This reuses the existing @reader xmlTextReader.
3728 *
3729 * Returns 0 in case of success and -1 in case of error
3730 */
3731int
3732xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
3733 const char *URL, const char *encoding, int options)
3734{
3735 xmlParserInputPtr stream;
3736
3737 if (cur == NULL)
3738 return (-1);
3739 if ((reader == NULL) || (reader->ctxt == NULL))
3740 return (-1);
3741
3742 xmlCtxtReset(reader->ctxt);
3743
3744 stream = xmlNewStringInputStream(reader->ctxt, cur);
3745 if (stream == NULL) {
3746 return (-1);
3747 }
3748 inputPush(reader->ctxt, stream);
3749 return (xmlTextReaderSetup(reader, URL, encoding, options));
3750}
3751
3752/**
3753 * xmlReaderNewFile:
3754 * @reader: an XML reader
3755 * @filename: a file or URL
3756 * @encoding: the document encoding, or NULL
3757 * @options: a combination of xmlParserOption(s)
3758 *
3759 * parse an XML file from the filesystem or the network.
3760 * This reuses the existing @reader xmlTextReader.
3761 *
3762 * Returns 0 in case of success and -1 in case of error
3763 */
3764int
3765xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
3766 const char *encoding, int options)
3767{
3768 xmlParserInputPtr stream;
3769
3770 if (filename == NULL)
3771 return (-1);
3772 if ((reader == NULL) || (reader->ctxt == NULL))
3773 return (-1);
3774
3775 xmlCtxtReset(reader->ctxt);
3776
3777 stream = xmlNewInputFromFile(reader->ctxt, filename);
3778 if (stream == NULL) {
3779 return (-1);
3780 }
3781 inputPush(reader->ctxt, stream);
3782 return (xmlTextReaderSetup(reader, NULL, encoding, options));
3783}
3784
3785/**
3786 * xmlReaderNewMemory:
3787 * @reader: an XML reader
3788 * @buffer: a pointer to a char array
3789 * @size: the size of the array
3790 * @URL: the base URL to use for the document
3791 * @encoding: the document encoding, or NULL
3792 * @options: a combination of xmlParserOption(s)
3793 *
3794 * Setup an xmltextReader to parse an XML in-memory document.
3795 * This reuses the existing @reader xmlTextReader.
3796 *
3797 * Returns 0 in case of success and -1 in case of error
3798 */
3799int
3800xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
3801 const char *URL, const char *encoding, int options)
3802{
3803 xmlParserInputBufferPtr input;
3804 xmlParserInputPtr stream;
3805
3806 if ((reader == NULL) || (reader->ctxt == NULL))
3807 return (-1);
3808 if (buffer == NULL)
3809 return (-1);
3810
3811 xmlCtxtReset(reader->ctxt);
3812
3813 input =
3814 xmlParserInputBufferCreateMem(buffer, size,
3815 XML_CHAR_ENCODING_NONE);
3816 if (input == NULL) {
3817 return (-1);
3818 }
3819
3820 stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE);
3821 if (stream == NULL) {
3822 xmlFreeParserInputBuffer(input);
3823 return (-1);
3824 }
3825
3826 inputPush(reader->ctxt, stream);
3827 return (xmlTextReaderSetup(reader, URL, encoding, options));
3828}
3829
3830/**
3831 * xmlReaderNewFd:
3832 * @reader: an XML reader
3833 * @fd: an open file descriptor
3834 * @URL: the base URL to use for the document
3835 * @encoding: the document encoding, or NULL
3836 * @options: a combination of xmlParserOption(s)
3837 *
3838 * Setup an xmltextReader to parse an XML from a file descriptor.
3839 * This reuses the existing @reader xmlTextReader.
3840 *
3841 * Returns 0 in case of success and -1 in case of error
3842 */
3843int
3844xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
3845 const char *URL, const char *encoding, int options)
3846{
3847 xmlParserInputBufferPtr input;
3848 xmlParserInputPtr stream;
3849
3850 if (fd < 0)
3851 return (-1);
3852 if ((reader == NULL) || (reader->ctxt == NULL))
3853 return (-1);
3854
3855 xmlCtxtReset(reader->ctxt);
3856
3857
3858 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
3859 if (input == NULL)
3860 return (-1);
3861 stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE);
3862 if (stream == NULL) {
3863 xmlFreeParserInputBuffer(input);
3864 return (-1);
3865 }
3866 inputPush(reader->ctxt, stream);
3867 return (xmlTextReaderSetup(reader, URL, encoding, options));
3868}
3869
3870/**
3871 * xmlReaderNewIO:
3872 * @reader: an XML reader
3873 * @ioread: an I/O read function
3874 * @ioclose: an I/O close function
3875 * @ioctx: an I/O handler
3876 * @URL: the base URL to use for the document
3877 * @encoding: the document encoding, or NULL
3878 * @options: a combination of xmlParserOption(s)
3879 *
3880 * Setup an xmltextReader to parse an XML document from I/O functions
3881 * and source.
3882 * This reuses the existing @reader xmlTextReader.
3883 *
3884 * Returns 0 in case of success and -1 in case of error
3885 */
3886int
3887xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
3888 xmlInputCloseCallback ioclose, void *ioctx,
3889 const char *URL, const char *encoding, int options)
3890{
3891 xmlParserInputBufferPtr input;
3892 xmlParserInputPtr stream;
3893
3894 if (ioread == NULL)
3895 return (-1);
3896 if ((reader == NULL) || (reader->ctxt == NULL))
3897 return (-1);
3898
3899 xmlCtxtReset(reader->ctxt);
3900
3901 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
3902 XML_CHAR_ENCODING_NONE);
3903 if (input == NULL)
3904 return (-1);
3905 stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE);
3906 if (stream == NULL) {
3907 xmlFreeParserInputBuffer(input);
3908 return (-1);
3909 }
3910 inputPush(reader->ctxt, stream);
3911 return (xmlTextReaderSetup(reader, URL, encoding, options));
3912}
Daniel Veillard26f70262003-01-16 22:45:08 +00003913/************************************************************************
3914 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003915 * Utilities *
3916 * *
3917 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00003918#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003919/**
3920 * xmlBase64Decode:
3921 * @in: the input buffer
3922 * @inlen: the size of the input (in), the size read from it (out)
3923 * @to: the output buffer
3924 * @tolen: the size of the output (in), the size written to (out)
3925 *
3926 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00003927 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003928 *
3929 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
3930 * 2 if there wasn't enough space on the output or -1 in case of error.
3931 */
3932static int
3933xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
3934 unsigned char *to, unsigned long *tolen) {
3935 unsigned long incur; /* current index in in[] */
3936 unsigned long inblk; /* last block index in in[] */
3937 unsigned long outcur; /* current index in out[] */
3938 unsigned long inmax; /* size of in[] */
3939 unsigned long outmax; /* size of out[] */
3940 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00003941 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003942 int nbintmp; /* number of byte in intmp[] */
3943 int is_ignore; /* cur should be ignored */
3944 int is_end = 0; /* the end of the base64 was found */
3945 int retval = 1;
3946 int i;
3947
3948 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
3949 return(-1);
3950
3951 incur = 0;
3952 inblk = 0;
3953 outcur = 0;
3954 inmax = *inlen;
3955 outmax = *tolen;
3956 nbintmp = 0;
3957
3958 while (1) {
3959 if (incur >= inmax)
3960 break;
3961 cur = in[incur++];
3962 is_ignore = 0;
3963 if ((cur >= 'A') && (cur <= 'Z'))
3964 cur = cur - 'A';
3965 else if ((cur >= 'a') && (cur <= 'z'))
3966 cur = cur - 'a' + 26;
3967 else if ((cur >= '0') && (cur <= '9'))
3968 cur = cur - '0' + 52;
3969 else if (cur == '+')
3970 cur = 62;
3971 else if (cur == '/')
3972 cur = 63;
3973 else if (cur == '.')
3974 cur = 0;
3975 else if (cur == '=') /*no op , end of the base64 stream */
3976 is_end = 1;
3977 else {
3978 is_ignore = 1;
3979 if (nbintmp == 0)
3980 inblk = incur;
3981 }
3982
3983 if (!is_ignore) {
3984 int nbouttmp = 3;
3985 int is_break = 0;
3986
3987 if (is_end) {
3988 if (nbintmp == 0)
3989 break;
3990 if ((nbintmp == 1) || (nbintmp == 2))
3991 nbouttmp = 1;
3992 else
3993 nbouttmp = 2;
3994 nbintmp = 3;
3995 is_break = 1;
3996 }
3997 intmp[nbintmp++] = cur;
3998 /*
3999 * if intmp is full, push the 4byte sequence as a 3 byte
4000 * sequence out
4001 */
4002 if (nbintmp == 4) {
4003 nbintmp = 0;
4004 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4005 outtmp[1] =
4006 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4007 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4008 if (outcur + 3 >= outmax) {
4009 retval = 2;
4010 break;
4011 }
4012
4013 for (i = 0; i < nbouttmp; i++)
4014 to[outcur++] = outtmp[i];
4015 inblk = incur;
4016 }
4017
4018 if (is_break) {
4019 retval = 0;
4020 break;
4021 }
4022 }
4023 }
4024
4025 *tolen = outcur;
4026 *inlen = inblk;
4027 return (retval);
4028}
4029
4030/*
4031 * Test routine for the xmlBase64Decode function
4032 */
4033#if 0
4034int main(int argc, char **argv) {
4035 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4036 char output[100];
4037 char output2[100];
4038 char output3[100];
4039 unsigned long inlen = strlen(input);
4040 unsigned long outlen = 100;
4041 int ret;
4042 unsigned long cons, tmp, tmp2, prod;
4043
4044 /*
4045 * Direct
4046 */
4047 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4048
4049 output[outlen] = 0;
4050 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4051
4052 /*
4053 * output chunking
4054 */
4055 cons = 0;
4056 prod = 0;
4057 while (cons < inlen) {
4058 tmp = 5;
4059 tmp2 = inlen - cons;
4060
4061 printf("%ld %ld\n", cons, prod);
4062 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4063 cons += tmp2;
4064 prod += tmp;
4065 printf("%ld %ld\n", cons, prod);
4066 }
4067 output2[outlen] = 0;
4068 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4069
4070 /*
4071 * input chunking
4072 */
4073 cons = 0;
4074 prod = 0;
4075 while (cons < inlen) {
4076 tmp = 100 - prod;
4077 tmp2 = inlen - cons;
4078 if (tmp2 > 5)
4079 tmp2 = 5;
4080
4081 printf("%ld %ld\n", cons, prod);
4082 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4083 cons += tmp2;
4084 prod += tmp;
4085 printf("%ld %ld\n", cons, prod);
4086 }
4087 output3[outlen] = 0;
4088 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4089 return(0);
4090
4091}
4092#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004093#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004094#endif /* LIBXML_READER_ENABLED */