blob: c46433571fd28993a44a612b074a4b6e5a577e8a [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard7704fb12003-01-03 16:19:51 +000015 * - provide an API to preserve part of the tree
16 * - Streaming XInclude support
Daniel Veillard067bae52003-01-05 01:27:54 +000017 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000018 * - setting(s) for NoBlanks
19 * - performances and tuning ...
20 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#define IN_LIBXML
22#include "libxml.h"
23
Daniel Veillard81273902003-09-30 00:43:48 +000024#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000026#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000027
28#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#include <libxml/xmlmemory.h>
36#include <libxml/xmlIO.h>
37#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000038#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000039#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000040#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000041#ifdef LIBXML_XINCLUDE_ENABLED
42#include <libxml/xinclude.h>
43#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000044
45/* #define DEBUG_CALLBACKS */
46/* #define DEBUG_READER */
47
48/**
49 * TODO:
50 *
51 * macro to flag unimplemented blocks
52 */
53#define TODO \
54 xmlGenericError(xmlGenericErrorContext, \
55 "Unimplemented block at %s:%d\n", \
56 __FILE__, __LINE__);
57
58#ifdef DEBUG_READER
59#define DUMP_READER xmlTextReaderDebug(reader);
60#else
61#define DUMP_READER
62#endif
63
Daniel Veillarda880b122003-04-21 21:36:41 +000064#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000065/************************************************************************
66 * *
67 * The parser: maps the Text Reader API on top of the existing *
68 * parsing routines building a tree *
69 * *
70 ************************************************************************/
71
72#define XML_TEXTREADER_INPUT 1
73#define XML_TEXTREADER_CTXT 2
74
75typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000076 XML_TEXTREADER_MODE_INITIAL = 0,
77 XML_TEXTREADER_MODE_INTERACTIVE = 1,
78 XML_TEXTREADER_MODE_ERROR = 2,
79 XML_TEXTREADER_MODE_EOF =3,
80 XML_TEXTREADER_MODE_CLOSED = 4,
81 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000082} xmlTextReaderMode;
83
84typedef enum {
85 XML_TEXTREADER_NONE = -1,
86 XML_TEXTREADER_START= 0,
87 XML_TEXTREADER_ELEMENT= 1,
88 XML_TEXTREADER_END= 2,
89 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000090 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000091 XML_TEXTREADER_DONE= 5,
92 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000093} xmlTextReaderState;
94
Daniel Veillardf4e55762003-04-15 23:32:22 +000095typedef enum {
96 XML_TEXTREADER_NOT_VALIDATE = 0,
97 XML_TEXTREADER_VALIDATE_DTD = 1,
98 XML_TEXTREADER_VALIDATE_RNG = 2
99} xmlTextReaderValidate;
100
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000101struct _xmlTextReader {
102 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000103 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000104 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000105 int allocs; /* what structure were deallocated */
106 xmlTextReaderState state;
107 xmlParserCtxtPtr ctxt; /* the parser context */
108 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
109 xmlParserInputBufferPtr input; /* the input */
110 startElementSAXFunc startElement;/* initial SAX callbacks */
111 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000112 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000113 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000114 charactersSAXFunc characters;
115 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000116 unsigned int base; /* base of the segment in the input */
117 unsigned int cur; /* current position in the input */
118 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000119 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000120 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000121 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000122 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000123 xmlBufferPtr buffer; /* used to return const xmlChar * */
124 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000125
126 /* entity stack when traversing entities content */
127 xmlNodePtr ent; /* Current Entity Ref Node */
128 int entNr; /* Depth of the entities stack */
129 int entMax; /* Max depth of the entities stack */
130 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000131
132 /* error handling */
133 xmlTextReaderErrorFunc errorFunc; /* callback function */
134 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000135
136#ifdef LIBXML_SCHEMAS_ENABLED
137 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000138 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
139 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
140 int rngValidErrors;/* The number of errors detected */
141 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
142#endif
143#ifdef LIBXML_XINCLUDE_ENABLED
144 /* Handling of XInclude processing */
145 int xinclude; /* is xinclude asked for */
146 const xmlChar * xinclude_name; /* the xinclude name from dict */
147 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
148 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000149#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000150};
151
Daniel Veillarde8039df2003-10-27 11:25:13 +0000152#define NODE_IS_EMPTY 0x1
153#define NODE_IS_PRESERVED 0x2
Daniel Veillard067bae52003-01-05 01:27:54 +0000154
Daniel Veillarde72c5082003-09-19 12:44:05 +0000155/**
156 * CONSTSTR:
157 *
158 * Macro used to return an interned string
159 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000160#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
161#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
162
163static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
164static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000165
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000166/************************************************************************
167 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000168 * Our own version of the freeing routines as we recycle nodes *
169 * *
170 ************************************************************************/
171/**
172 * DICT_FREE:
173 * @str: a string
174 *
175 * Free a string if it is not owned by the "dict" dictionnary in the
176 * current scope
177 */
178#define DICT_FREE(str) \
179 if ((str) && ((!dict) || \
180 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
181 xmlFree((char *)(str));
182
183static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
184static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
185
186/**
187 * xmlTextReaderFreeProp:
188 * @reader: the xmlTextReaderPtr used
189 * @cur: the node
190 *
191 * Free a node.
192 */
193static void
194xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
195 xmlDictPtr dict;
196
197 dict = reader->ctxt->dict;
198 if (cur == NULL) return;
199
200 /* Check for ID removal -> leading to invalid references ! */
201 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
202 ((cur->parent->doc->intSubset != NULL) ||
203 (cur->parent->doc->extSubset != NULL))) {
204 if (xmlIsID(cur->parent->doc, cur->parent, cur))
205 xmlRemoveID(cur->parent->doc, cur);
206 }
207 if (cur->children != NULL)
208 xmlTextReaderFreeNodeList(reader, cur->children);
209
210 DICT_FREE(cur->name);
211 if ((reader != NULL) && (reader->ctxt != NULL) &&
212 (reader->ctxt->freeAttrsNr < 100)) {
213 cur->next = reader->ctxt->freeAttrs;
214 reader->ctxt->freeAttrs = cur;
215 reader->ctxt->freeAttrsNr++;
216 } else {
217 xmlFree(cur);
218 }
219}
220
221/**
222 * xmlTextReaderFreePropList:
223 * @reader: the xmlTextReaderPtr used
224 * @cur: the first property in the list
225 *
226 * Free a property and all its siblings, all the children are freed too.
227 */
228static void
229xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
230 xmlAttrPtr next;
231 if (cur == NULL) return;
232 while (cur != NULL) {
233 next = cur->next;
234 xmlTextReaderFreeProp(reader, cur);
235 cur = next;
236 }
237}
238
239/**
240 * xmlTextReaderFreeNodeList:
241 * @reader: the xmlTextReaderPtr used
242 * @cur: the first node in the list
243 *
244 * Free a node and all its siblings, this is a recursive behaviour, all
245 * the children are freed too.
246 */
247static void
248xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
249 xmlNodePtr next;
250 xmlDictPtr dict;
251
252 dict = reader->ctxt->dict;
253 if (cur == NULL) return;
254 if (cur->type == XML_NAMESPACE_DECL) {
255 xmlFreeNsList((xmlNsPtr) cur);
256 return;
257 }
258 if ((cur->type == XML_DOCUMENT_NODE) ||
259 (cur->type == XML_HTML_DOCUMENT_NODE)) {
260 xmlFreeDoc((xmlDocPtr) cur);
261 return;
262 }
263 while (cur != NULL) {
264 next = cur->next;
265 /* unroll to speed up freeing the document */
266 if (cur->type != XML_DTD_NODE) {
267
268 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000269 (cur->type != XML_ENTITY_REF_NODE)) {
270 if (cur->children->parent == cur)
271 xmlTextReaderFreeNodeList(reader, cur->children);
272 cur->children = NULL;
273 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000274 if (((cur->type == XML_ELEMENT_NODE) ||
275 (cur->type == XML_XINCLUDE_START) ||
276 (cur->type == XML_XINCLUDE_END)) &&
277 (cur->properties != NULL))
278 xmlTextReaderFreePropList(reader, cur->properties);
279 if ((cur->type != XML_ELEMENT_NODE) &&
280 (cur->type != XML_XINCLUDE_START) &&
281 (cur->type != XML_XINCLUDE_END) &&
282 (cur->type != XML_ENTITY_REF_NODE)) {
283 DICT_FREE(cur->content);
284 }
285 if (((cur->type == XML_ELEMENT_NODE) ||
286 (cur->type == XML_XINCLUDE_START) ||
287 (cur->type == XML_XINCLUDE_END)) &&
288 (cur->nsDef != NULL))
289 xmlFreeNsList(cur->nsDef);
290
291 /*
292 * we don't free element names here they are interned now
293 */
294 if ((cur->type != XML_TEXT_NODE) &&
295 (cur->type != XML_COMMENT_NODE))
296 DICT_FREE(cur->name);
297 if (((cur->type == XML_ELEMENT_NODE) ||
298 (cur->type == XML_TEXT_NODE)) &&
299 (reader != NULL) && (reader->ctxt != NULL) &&
300 (reader->ctxt->freeElemsNr < 100)) {
301 cur->next = reader->ctxt->freeElems;
302 reader->ctxt->freeElems = cur;
303 reader->ctxt->freeElemsNr++;
304 } else {
305 xmlFree(cur);
306 }
307 }
308 cur = next;
309 }
310}
311
312/**
313 * xmlTextReaderFreeNode:
314 * @reader: the xmlTextReaderPtr used
315 * @cur: the node
316 *
317 * Free a node, this is a recursive behaviour, all the children are freed too.
318 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
319 */
320static void
321xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
322 xmlDictPtr dict;
323
324 dict = reader->ctxt->dict;
325 if (cur->type == XML_DTD_NODE) {
326 xmlFreeDtd((xmlDtdPtr) cur);
327 return;
328 }
329 if (cur->type == XML_NAMESPACE_DECL) {
330 xmlFreeNs((xmlNsPtr) cur);
331 return;
332 }
333 if (cur->type == XML_ATTRIBUTE_NODE) {
334 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
335 return;
336 }
337
338 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000339 (cur->type != XML_ENTITY_REF_NODE)) {
340 if (cur->children->parent == cur)
341 xmlTextReaderFreeNodeList(reader, cur->children);
342 cur->children = NULL;
343 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000344 if (((cur->type == XML_ELEMENT_NODE) ||
345 (cur->type == XML_XINCLUDE_START) ||
346 (cur->type == XML_XINCLUDE_END)) &&
347 (cur->properties != NULL))
348 xmlTextReaderFreePropList(reader, cur->properties);
349 if ((cur->type != XML_ELEMENT_NODE) &&
350 (cur->type != XML_XINCLUDE_START) &&
351 (cur->type != XML_XINCLUDE_END) &&
352 (cur->type != XML_ENTITY_REF_NODE)) {
353 DICT_FREE(cur->content);
354 }
355 if (((cur->type == XML_ELEMENT_NODE) ||
356 (cur->type == XML_XINCLUDE_START) ||
357 (cur->type == XML_XINCLUDE_END)) &&
358 (cur->nsDef != NULL))
359 xmlFreeNsList(cur->nsDef);
360
361 /*
362 * we don't free names here they are interned now
363 */
364 if ((cur->type != XML_TEXT_NODE) &&
365 (cur->type != XML_COMMENT_NODE))
366 DICT_FREE(cur->name);
367 if (((cur->type == XML_ELEMENT_NODE) ||
368 (cur->type == XML_TEXT_NODE)) &&
369 (reader != NULL) && (reader->ctxt != NULL) &&
370 (reader->ctxt->freeElemsNr < 100)) {
371 cur->next = reader->ctxt->freeElems;
372 reader->ctxt->freeElems = cur;
373 reader->ctxt->freeElemsNr++;
374 } else {
375 xmlFree(cur);
376 }
377}
378
379/**
380 * xmlTextReaderFreeDoc:
381 * @reader: the xmlTextReaderPtr used
382 * @cur: pointer to the document
383 *
384 * Free up all the structures used by a document, tree included.
385 */
386static void
387xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
388 xmlDtdPtr extSubset, intSubset;
389
390 if (cur == NULL) return;
391
392 /*
393 * Do this before freeing the children list to avoid ID lookups
394 */
395 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
396 cur->ids = NULL;
397 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
398 cur->refs = NULL;
399 extSubset = cur->extSubset;
400 intSubset = cur->intSubset;
401 if (intSubset == extSubset)
402 extSubset = NULL;
403 if (extSubset != NULL) {
404 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
405 cur->extSubset = NULL;
406 xmlFreeDtd(extSubset);
407 }
408 if (intSubset != NULL) {
409 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
410 cur->intSubset = NULL;
411 xmlFreeDtd(intSubset);
412 }
413
414 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
415
416 if (cur->version != NULL) xmlFree((char *) cur->version);
417 if (cur->name != NULL) xmlFree((char *) cur->name);
418 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
419 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
420 if (cur->URL != NULL) xmlFree((char *) cur->URL);
421 xmlFree(cur);
422}
423
424/************************************************************************
425 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000426 * The reader core parser *
427 * *
428 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000429#ifdef DEBUG_READER
430static void
431xmlTextReaderDebug(xmlTextReaderPtr reader) {
432 if ((reader == NULL) || (reader->ctxt == NULL)) {
433 fprintf(stderr, "xmlTextReader NULL\n");
434 return;
435 }
436 fprintf(stderr, "xmlTextReader: state %d depth %d ",
437 reader->state, reader->depth);
438 if (reader->node == NULL) {
439 fprintf(stderr, "node = NULL\n");
440 } else {
441 fprintf(stderr, "node %s\n", reader->node->name);
442 }
443 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
444 reader->base, reader->cur, reader->ctxt->nodeNr);
445 if (reader->input->buffer == NULL) {
446 fprintf(stderr, "buffer is NULL\n");
447 } else {
448#ifdef LIBXML_DEBUG_ENABLED
449 xmlDebugDumpString(stderr,
450 &reader->input->buffer->content[reader->cur]);
451#endif
452 fprintf(stderr, "\n");
453 }
454}
455#endif
456
457/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000458 * xmlTextReaderEntPush:
459 * @reader: the xmlTextReaderPtr used
460 * @value: the entity reference node
461 *
462 * Pushes a new entity reference node on top of the entities stack
463 *
464 * Returns 0 in case of error, the index in the stack otherwise
465 */
466static int
467xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
468{
469 if (reader->entMax <= 0) {
470 reader->entMax = 10;
471 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
472 sizeof(reader->entTab[0]));
473 if (reader->entTab == NULL) {
474 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
475 return (0);
476 }
477 }
478 if (reader->entNr >= reader->entMax) {
479 reader->entMax *= 2;
480 reader->entTab =
481 (xmlNodePtr *) xmlRealloc(reader->entTab,
482 reader->entMax *
483 sizeof(reader->entTab[0]));
484 if (reader->entTab == NULL) {
485 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
486 return (0);
487 }
488 }
489 reader->entTab[reader->entNr] = value;
490 reader->ent = value;
491 return (reader->entNr++);
492}
493
494/**
495 * xmlTextReaderEntPop:
496 * @reader: the xmlTextReaderPtr used
497 *
498 * Pops the top element entity from the entities stack
499 *
500 * Returns the entity just removed
501 */
502static xmlNodePtr
503xmlTextReaderEntPop(xmlTextReaderPtr reader)
504{
505 xmlNodePtr ret;
506
507 if (reader->entNr <= 0)
508 return (0);
509 reader->entNr--;
510 if (reader->entNr > 0)
511 reader->ent = reader->entTab[reader->entNr - 1];
512 else
513 reader->ent = NULL;
514 ret = reader->entTab[reader->entNr];
515 reader->entTab[reader->entNr] = 0;
516 return (ret);
517}
518
519/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000520 * xmlTextReaderStartElement:
521 * @ctx: the user data (XML parser context)
522 * @fullname: The element name, including namespace prefix
523 * @atts: An array of name/value attributes pairs, NULL terminated
524 *
525 * called when an opening tag has been processed.
526 */
527static void
528xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
529 const xmlChar **atts) {
530 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
531 xmlTextReaderPtr reader = ctxt->_private;
532
533#ifdef DEBUG_CALLBACKS
534 printf("xmlTextReaderStartElement(%s)\n", fullname);
535#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000536 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000537 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000538 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
539 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
540 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000541 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000542 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000543 if (reader != NULL)
544 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000545}
546
547/**
548 * xmlTextReaderEndElement:
549 * @ctx: the user data (XML parser context)
550 * @fullname: The element name, including namespace prefix
551 *
552 * called when an ending tag has been processed.
553 */
554static void
555xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
556 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
557 xmlTextReaderPtr reader = ctxt->_private;
558
559#ifdef DEBUG_CALLBACKS
560 printf("xmlTextReaderEndElement(%s)\n", fullname);
561#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000562 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000563 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000564 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000565}
566
567/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000568 * xmlTextReaderStartElementNs:
569 * @ctx: the user data (XML parser context)
570 * @localname: the local name of the element
571 * @prefix: the element namespace prefix if available
572 * @URI: the element namespace name if available
573 * @nb_namespaces: number of namespace definitions on that node
574 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
575 * @nb_attributes: the number of attributes on that node
576 * nb_defaulted: the number of defaulted attributes.
577 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
578 * attribute values.
579 *
580 * called when an opening tag has been processed.
581 */
582static void
583xmlTextReaderStartElementNs(void *ctx,
584 const xmlChar *localname,
585 const xmlChar *prefix,
586 const xmlChar *URI,
587 int nb_namespaces,
588 const xmlChar **namespaces,
589 int nb_attributes,
590 int nb_defaulted,
591 const xmlChar **attributes)
592{
593 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
594 xmlTextReaderPtr reader = ctxt->_private;
595
596#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000597 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000598#endif
599 if ((reader != NULL) && (reader->startElementNs != NULL)) {
600 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
601 namespaces, nb_attributes, nb_defaulted,
602 attributes);
603 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
604 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
605 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000606 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000607 }
608 if (reader != NULL)
609 reader->state = XML_TEXTREADER_ELEMENT;
610}
611
612/**
613 * xmlTextReaderEndElementNs:
614 * @ctx: the user data (XML parser context)
615 * @localname: the local name of the element
616 * @prefix: the element namespace prefix if available
617 * @URI: the element namespace name if available
618 *
619 * called when an ending tag has been processed.
620 */
621static void
622xmlTextReaderEndElementNs(void *ctx,
623 const xmlChar * localname,
624 const xmlChar * prefix,
625 const xmlChar * URI)
626{
627 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
628 xmlTextReaderPtr reader = ctxt->_private;
629
630#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000631 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000632#endif
633 if ((reader != NULL) && (reader->endElementNs != NULL)) {
634 reader->endElementNs(ctx, localname, prefix, URI);
635 }
636}
637
638
639/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000640 * xmlTextReaderCharacters:
641 * @ctx: the user data (XML parser context)
642 * @ch: a xmlChar string
643 * @len: the number of xmlChar
644 *
645 * receiving some chars from the parser.
646 */
647static void
648xmlTextReaderCharacters(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("xmlTextReaderCharacters()\n");
655#endif
656 if ((reader != NULL) && (reader->characters != NULL)) {
657 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 }
659}
660
661/**
662 * xmlTextReaderCDataBlock:
663 * @ctx: the user data (XML parser context)
664 * @value: The pcdata content
665 * @len: the block length
666 *
667 * called when a pcdata block has been parsed
668 */
669static void
670xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
671{
672 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
673 xmlTextReaderPtr reader = ctxt->_private;
674
675#ifdef DEBUG_CALLBACKS
676 printf("xmlTextReaderCDataBlock()\n");
677#endif
678 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
679 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000680 }
681}
682
683/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000684 * xmlTextReaderPushData:
685 * @reader: the xmlTextReaderPtr used
686 *
687 * Push data down the progressive parser until a significant callback
688 * got raised.
689 *
690 * Returns -1 in case of failure, 0 otherwise
691 */
692static int
693xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000694 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000695 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000696 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000697
698 if ((reader->input == NULL) || (reader->input->buffer == NULL))
699 return(-1);
700
Daniel Veillardea7751d2002-12-20 00:16:24 +0000701 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000702 reader->state = XML_TEXTREADER_NONE;
703 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000704
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000705 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000706 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000707 /*
708 * Refill the buffer unless we are at the end of the stream
709 */
710 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
711 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000712 if ((val == 0) &&
713 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
714 if (inbuf->use == reader->cur) {
715 reader->mode = XML_TEXTREADER_MODE_EOF;
716 reader->state = oldstate;
717 if ((oldstate != XML_TEXTREADER_START) ||
718 (reader->ctxt->myDoc != NULL))
719 return(val);
720 }
721 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000722 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000723 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000724 if ((oldstate != XML_TEXTREADER_START) ||
725 (reader->ctxt->myDoc != NULL))
726 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000727 } else if (val == 0) {
728 /* mark the end of the stream and process the remains */
729 reader->mode = XML_TEXTREADER_MODE_EOF;
730 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000731 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000732
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000733 } else
734 break;
735 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000736 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000737 * parse by block of CHUNK_SIZE bytes, various tests show that
738 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000739 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000740 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000741 val = xmlParseChunk(reader->ctxt,
742 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000743 CHUNK_SIZE, 0);
744 reader->cur += CHUNK_SIZE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000745 if (val != 0)
746 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000747 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000748 s = inbuf->use - reader->cur;
749 val = xmlParseChunk(reader->ctxt,
750 (const char *) &inbuf->content[reader->cur],
751 s, 0);
752 reader->cur += s;
753 if (val != 0)
754 return(-1);
755 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000756 }
757 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000758
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000759 /*
760 * Discard the consumed input when needed and possible
761 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000762 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000763 if ((reader->cur >= 4096) &&
764 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000765 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000766 if (val >= 0) {
767 reader->cur -= val;
768 }
769 }
770 }
771
772 /*
773 * At the end of the stream signal that the work is done to the Push
774 * parser.
775 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000776 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000777 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000778 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000779 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000780 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000781 s, 1);
782 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000783 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000784 if (val != 0) return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000785 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000786 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000787 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000788 return(0);
789}
790
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000791#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000792/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000793 * xmlTextReaderValidatePush:
794 * @reader: the xmlTextReaderPtr used
795 *
796 * Push the current node for validation
797 */
798static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000799xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000800 xmlNodePtr node = reader->node;
801
Daniel Veillardf4e55762003-04-15 23:32:22 +0000802 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
803 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
804 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
805 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
806 reader->ctxt->myDoc, node, node->name);
807 } else {
808 /* TODO use the BuildQName interface */
809 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000810
Daniel Veillardf4e55762003-04-15 23:32:22 +0000811 qname = xmlStrdup(node->ns->prefix);
812 qname = xmlStrcat(qname, BAD_CAST ":");
813 qname = xmlStrcat(qname, node->name);
814 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
815 reader->ctxt->myDoc, node, qname);
816 if (qname != NULL)
817 xmlFree(qname);
818 }
819#ifdef LIBXML_SCHEMAS_ENABLED
820 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
821 (reader->rngValidCtxt != NULL)) {
822 int ret;
823
824 if (reader->rngFullNode != NULL) return;
825 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
826 reader->ctxt->myDoc,
827 node);
828 if (ret == 0) {
829 /*
830 * this element requires a full tree
831 */
832 node = xmlTextReaderExpand(reader);
833 if (node == NULL) {
834printf("Expand failed !\n");
835 ret = -1;
836 } else {
837 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
838 reader->ctxt->myDoc,
839 node);
840 reader->rngFullNode = node;
841 }
842 }
843 if (ret != 1)
844 reader->rngValidErrors++;
845#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000846 }
847}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000848
849/**
850 * xmlTextReaderValidateCData:
851 * @reader: the xmlTextReaderPtr used
852 * @data: pointer to the CData
853 * @len: lenght of the CData block in bytes.
854 *
855 * Push some CData for validation
856 */
857static void
858xmlTextReaderValidateCData(xmlTextReaderPtr reader,
859 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000860 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
861 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
862 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
863 data, len);
864#ifdef LIBXML_SCHEMAS_ENABLED
865 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
866 (reader->rngValidCtxt != NULL)) {
867 int ret;
868
869 if (reader->rngFullNode != NULL) return;
870 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
871 if (ret != 1)
872 reader->rngValidErrors++;
873#endif
874 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000875}
876
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000877/**
878 * xmlTextReaderValidatePop:
879 * @reader: the xmlTextReaderPtr used
880 *
881 * Pop the current node from validation
882 */
883static void
884xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
885 xmlNodePtr node = reader->node;
886
Daniel Veillardf4e55762003-04-15 23:32:22 +0000887 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
888 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
889 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
890 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
891 reader->ctxt->myDoc, node, node->name);
892 } else {
893 /* TODO use the BuildQName interface */
894 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000895
Daniel Veillardf4e55762003-04-15 23:32:22 +0000896 qname = xmlStrdup(node->ns->prefix);
897 qname = xmlStrcat(qname, BAD_CAST ":");
898 qname = xmlStrcat(qname, node->name);
899 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
900 reader->ctxt->myDoc, node, qname);
901 if (qname != NULL)
902 xmlFree(qname);
903 }
904#ifdef LIBXML_SCHEMAS_ENABLED
905 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
906 (reader->rngValidCtxt != NULL)) {
907 int ret;
908
909 if (reader->rngFullNode != NULL) {
910 if (node == reader->rngFullNode)
911 reader->rngFullNode = NULL;
912 return;
913 }
914 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
915 reader->ctxt->myDoc,
916 node);
917 if (ret != 1)
918 reader->rngValidErrors++;
919#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000920 }
921}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000922
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000923/**
924 * xmlTextReaderValidateEntity:
925 * @reader: the xmlTextReaderPtr used
926 *
927 * Handle the validation when an entity reference is encountered and
928 * entity substitution is not activated. As a result the parser interface
929 * must walk through the entity and do the validation calls
930 */
931static void
932xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
933 xmlNodePtr oldnode = reader->node;
934 xmlNodePtr node = reader->node;
935 xmlParserCtxtPtr ctxt = reader->ctxt;
936
937 do {
938 if (node->type == XML_ENTITY_REF_NODE) {
939 /*
940 * Case where the underlying tree is not availble, lookup the entity
941 * and walk it.
942 */
943 if ((node->children == NULL) && (ctxt->sax != NULL) &&
944 (ctxt->sax->getEntity != NULL)) {
945 node->children = (xmlNodePtr)
946 ctxt->sax->getEntity(ctxt, node->name);
947 }
948
949 if ((node->children != NULL) &&
950 (node->children->type == XML_ENTITY_DECL) &&
951 (node->children->children != NULL)) {
952 xmlTextReaderEntPush(reader, node);
953 node = node->children->children;
954 continue;
955 } else {
956 /*
957 * The error has probably be raised already.
958 */
959 if (node == oldnode)
960 break;
961 node = node->next;
962 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000963#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000964 } else if (node->type == XML_ELEMENT_NODE) {
965 reader->node = node;
966 xmlTextReaderValidatePush(reader);
967 } else if ((node->type == XML_TEXT_NODE) ||
968 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000969 xmlTextReaderValidateCData(reader, node->content,
970 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000971#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000972 }
973
974 /*
975 * go to next node
976 */
977 if (node->children != NULL) {
978 node = node->children;
979 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +0000980 } else if (node->type == XML_ELEMENT_NODE) {
981 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000982 }
983 if (node->next != NULL) {
984 node = node->next;
985 continue;
986 }
987 do {
988 node = node->parent;
989 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000990 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000991 if (reader->entNr == 0) {
992 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +0000993 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +0000994 xmlUnlinkNode(tmp);
995 xmlTextReaderFreeNode(reader, tmp);
996 } else
997 break;
998 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000999 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001000 reader->node = node;
1001 xmlTextReaderValidatePop(reader);
1002 }
1003 if ((node->type == XML_ENTITY_DECL) &&
1004 (reader->ent != NULL) && (reader->ent->children == node)) {
1005 node = xmlTextReaderEntPop(reader);
1006 }
1007 if (node == oldnode)
1008 break;
1009 if (node->next != NULL) {
1010 node = node->next;
1011 break;
1012 }
1013 } while ((node != NULL) && (node != oldnode));
1014 } while ((node != NULL) && (node != oldnode));
1015 reader->node = oldnode;
1016}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001017#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001018
1019
1020/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001021 * xmlTextReaderGetSuccessor:
1022 * @cur: the current node
1023 *
1024 * Get the successor of a node if available.
1025 *
1026 * Returns the successor node or NULL
1027 */
1028static xmlNodePtr
1029xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1030 if (cur == NULL) return(NULL) ; /* ERROR */
1031 if (cur->next != NULL) return(cur->next) ;
1032 do {
1033 cur = cur->parent;
1034 if (cur == NULL) return(NULL);
1035 if (cur->next != NULL) return(cur->next);
1036 } while (cur != NULL);
1037 return(cur);
1038}
1039
1040/**
1041 * xmlTextReaderDoExpand:
1042 * @reader: the xmlTextReaderPtr used
1043 *
1044 * Makes sure that the current node is fully read as well as all its
1045 * descendant. It means the full DOM subtree must be available at the
1046 * end of the call.
1047 *
1048 * Returns 1 if the node was expanded successfully, 0 if there is no more
1049 * nodes to read, or -1 in case of error
1050 */
1051static int
1052xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1053 int val;
1054
1055 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1056 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001057 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001058 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1059
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001060 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1061 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001062 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001063 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001064 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1065 return(1);
1066 val = xmlTextReaderPushData(reader);
1067 if (val < 0)
1068 return(-1);
1069 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1070 return(1);
1071}
1072
1073/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001074 * xmlTextReaderRead:
1075 * @reader: the xmlTextReaderPtr used
1076 *
1077 * Moves the position of the current instance to the next node in
1078 * the stream, exposing its properties.
1079 *
1080 * Returns 1 if the node was read successfully, 0 if there is no more
1081 * nodes to read, or -1 in case of error
1082 */
1083int
1084xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001085 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001086 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001087 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001088
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001089
1090 if (reader == NULL)
1091 return(-1);
1092 if (reader->doc != NULL)
1093 return(xmlTextReaderReadTree(reader));
1094 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001095 return(-1);
1096 if (reader->ctxt->wellFormed != 1)
1097 return(-1);
1098
1099#ifdef DEBUG_READER
1100 fprintf(stderr, "\nREAD ");
1101 DUMP_READER
1102#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001103 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001104 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1105 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001106 /*
1107 * Initial state
1108 */
1109 do {
1110 val = xmlTextReaderPushData(reader);
1111 if (val < 0)
1112 return(-1);
1113 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001114 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1115 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001116 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001117 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001118 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001119 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001120 if (reader->node == NULL)
1121 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001122 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001123 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001124 if (reader->ctxt->myDoc != NULL) {
1125 reader->node = reader->ctxt->myDoc->children;
1126 }
1127 if (reader->node == NULL)
1128 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001129 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001130 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001131 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001132 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001133 }
1134 oldstate = reader->state;
1135 olddepth = reader->ctxt->nodeNr;
1136 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001137
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001138get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001139 /*
1140 * If we are not backtracking on ancestors or examined nodes,
1141 * that the parser didn't finished or that we arent at the end
1142 * of stream, continue processing.
1143 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001144 while ((reader->node->next == NULL) &&
1145 (reader->ctxt->nodeNr == olddepth) &&
1146 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001147 (reader->node->children == NULL) ||
1148 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001149 ((reader->node->children != NULL) &&
1150 (reader->node->children->type == XML_TEXT_NODE) &&
1151 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001152 (reader->node->type == XML_DTD_NODE) ||
1153 (reader->node->type == XML_DOCUMENT_NODE) ||
1154 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001155 ((reader->ctxt->node == NULL) ||
1156 (reader->ctxt->node == reader->node) ||
1157 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001158 (reader->ctxt->instate != XML_PARSER_EOF)) {
1159 val = xmlTextReaderPushData(reader);
1160 if (val < 0)
1161 return(-1);
1162 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001163 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001164 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001165 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001166 if ((reader->node->children != NULL) &&
1167 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001168 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001169 (reader->node->type != XML_DTD_NODE)) {
1170 reader->node = reader->node->children;
1171 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001172 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001173 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001174 }
1175 }
1176 if (reader->node->next != NULL) {
1177 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001178 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001179 (reader->node->children == NULL) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001180 ((reader->node->extra & NODE_IS_EMPTY) == 0) &&
1181 (reader->in_xinclude <= 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001182 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001183 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001184 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001185#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001186 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001187 (reader->node->type == XML_ELEMENT_NODE))
1188 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001189#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001190 reader->node = reader->node->next;
1191 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001192
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001193 /*
1194 * Cleanup of the old node
1195 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001196 if ((reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001197 (reader->node->prev->type != XML_DTD_NODE) &&
1198 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001199 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001200 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001201 xmlUnlinkNode(tmp);
1202 xmlTextReaderFreeNode(reader, tmp);
1203 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001204 }
1205
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001206 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001207 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001208 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001209 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001210 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001211 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001212 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001213 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001214 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001215#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001216 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001217 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001218#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001219 reader->node = reader->node->parent;
1220 if ((reader->node == NULL) ||
1221 (reader->node->type == XML_DOCUMENT_NODE) ||
1222#ifdef LIBXML_DOCB_ENABLED
1223 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1224#endif
1225 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001226 if (reader->mode != XML_TEXTREADER_DONE) {
1227 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1228 reader->mode = XML_TEXTREADER_DONE;
1229 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001230 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001231 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001232
1233 /*
1234 * Cleanup of the old node
1235 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001236 if ((oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001237 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001238 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001239 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001240 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001241 }
1242
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001243 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001244 }
1245 reader->depth--;
1246 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001247
1248node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001249 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001250
1251 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001252 * If we are in the middle of a piece of CDATA make sure it's finished
1253 */
1254 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001255 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001256 ((reader->node->type == XML_TEXT_NODE) ||
1257 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1258 xmlTextReaderExpand(reader);
1259 }
1260
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001261#ifdef LIBXML_XINCLUDE_ENABLED
1262 /*
1263 * Handle XInclude if asked for
1264 */
1265 if ((reader->xinclude) && (reader->node != NULL) &&
1266 (reader->node->type == XML_ELEMENT_NODE) &&
1267 (reader->node->ns != NULL) &&
1268 (xmlStrEqual(reader->node->ns->href, XINCLUDE_NS))) {
1269 if (reader->xincctxt == NULL) {
1270 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1271 }
1272 /*
1273 * expand that node and process it
1274 */
1275 xmlTextReaderExpand(reader);
1276 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1277 }
1278 if (reader->node->type == XML_XINCLUDE_START) {
1279 reader->in_xinclude++;
1280 goto get_next_node;
1281 }
1282 if (reader->node->type == XML_XINCLUDE_END) {
1283 reader->in_xinclude--;
1284 goto get_next_node;
1285 }
1286#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001287 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001288 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001289 */
1290 if ((reader->node != NULL) &&
1291 (reader->node->type == XML_ENTITY_REF_NODE) &&
1292 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1293 /*
1294 * Case where the underlying tree is not availble, lookup the entity
1295 * and walk it.
1296 */
1297 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1298 (reader->ctxt->sax->getEntity != NULL)) {
1299 reader->node->children = (xmlNodePtr)
1300 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1301 }
1302
1303 if ((reader->node->children != NULL) &&
1304 (reader->node->children->type == XML_ENTITY_DECL) &&
1305 (reader->node->children->children != NULL)) {
1306 xmlTextReaderEntPush(reader, reader->node);
1307 reader->node = reader->node->children->children;
1308 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001309#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001310 } else if ((reader->node != NULL) &&
1311 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001312 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001313 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001314#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001315 }
1316 if ((reader->node != NULL) &&
1317 (reader->node->type == XML_ENTITY_DECL) &&
1318 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1319 reader->node = xmlTextReaderEntPop(reader);
1320 reader->depth++;
1321 goto get_next_node;
1322 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001323#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001324 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001325 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001326
1327 if ((node->type == XML_ELEMENT_NODE) &&
1328 ((reader->state != XML_TEXTREADER_END) &&
1329 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1330 xmlTextReaderValidatePush(reader);
1331 } else if ((node->type == XML_TEXT_NODE) ||
1332 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001333 xmlTextReaderValidateCData(reader, node->content,
1334 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001335 }
1336 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001337#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001338 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001339node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001340 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001341 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001342}
1343
Daniel Veillard67df8092002-12-16 22:04:11 +00001344/**
1345 * xmlTextReaderReadState:
1346 * @reader: the xmlTextReaderPtr used
1347 *
1348 * Gets the read state of the reader.
1349 *
1350 * Returns the state value, or -1 in case of error
1351 */
1352int
1353xmlTextReaderReadState(xmlTextReaderPtr reader) {
1354 if (reader == NULL)
1355 return(-1);
1356 return(reader->mode);
1357}
1358
1359/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001360 * xmlTextReaderExpand:
1361 * @reader: the xmlTextReaderPtr used
1362 *
1363 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001364 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001365 *
1366 * Returns a node pointer valid until the next xmlTextReaderRead() call
1367 * or NULL in case of error.
1368 */
1369xmlNodePtr
1370xmlTextReaderExpand(xmlTextReaderPtr reader) {
1371 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1372 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001373 if (reader->doc != NULL)
1374 return(reader->node);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001375 if (xmlTextReaderDoExpand(reader) < 0)
1376 return(NULL);
1377 return(reader->node);
1378}
1379
1380/**
1381 * xmlTextReaderNext:
1382 * @reader: the xmlTextReaderPtr used
1383 *
1384 * Skip to the node following the current one in document order while
1385 * avoiding the subtree if any.
1386 *
1387 * Returns 1 if the node was read successfully, 0 if there is no more
1388 * nodes to read, or -1 in case of error
1389 */
1390int
1391xmlTextReaderNext(xmlTextReaderPtr reader) {
1392 int ret;
1393 xmlNodePtr cur;
1394
1395 if (reader == NULL)
1396 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001397 if (reader->doc != NULL)
1398 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001399 cur = reader->node;
1400 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1401 return(xmlTextReaderRead(reader));
1402 if (reader->state == XML_TEXTREADER_END)
1403 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001404 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001405 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001406 do {
1407 ret = xmlTextReaderRead(reader);
1408 if (ret != 1)
1409 return(ret);
1410 } while (reader->node != cur);
1411 return(xmlTextReaderRead(reader));
1412}
1413
1414/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001415 * xmlTextReaderReadInnerXml:
1416 * @reader: the xmlTextReaderPtr used
1417 *
1418 * Reads the contents of the current node, including child nodes and markup.
1419 *
1420 * Returns a string containing the XML content, or NULL if the current node
1421 * is neither an element nor attribute, or has no child nodes. The
1422 * string must be deallocated by the caller.
1423 */
1424xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001425xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001426 TODO
1427 return(NULL);
1428}
1429
1430/**
1431 * xmlTextReaderReadOuterXml:
1432 * @reader: the xmlTextReaderPtr used
1433 *
1434 * Reads the contents of the current node, including child nodes and markup.
1435 *
1436 * Returns a string containing the XML content, or NULL if the current node
1437 * is neither an element nor attribute, or has no child nodes. The
1438 * string must be deallocated by the caller.
1439 */
1440xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001441xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001442 TODO
1443 return(NULL);
1444}
1445
1446/**
1447 * xmlTextReaderReadString:
1448 * @reader: the xmlTextReaderPtr used
1449 *
1450 * Reads the contents of an element or a text node as a string.
1451 *
1452 * Returns a string containing the contents of the Element or Text node,
1453 * or NULL if the reader is positioned on any other type of node.
1454 * The string must be deallocated by the caller.
1455 */
1456xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001457xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001458 TODO
1459 return(NULL);
1460}
1461
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001462#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001463/**
1464 * xmlTextReaderReadBase64:
1465 * @reader: the xmlTextReaderPtr used
1466 * @array: a byte array to store the content.
1467 * @offset: the zero-based index into array where the method should
1468 * begin to write.
1469 * @len: the number of bytes to write.
1470 *
1471 * Reads and decodes the Base64 encoded contents of an element and
1472 * stores the result in a byte buffer.
1473 *
1474 * Returns the number of bytes written to array, or zero if the current
1475 * instance is not positioned on an element or -1 in case of error.
1476 */
1477int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001478xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1479 unsigned char *array ATTRIBUTE_UNUSED,
1480 int offset ATTRIBUTE_UNUSED,
1481 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001482 if ((reader == NULL) || (reader->ctxt == NULL))
1483 return(-1);
1484 if (reader->ctxt->wellFormed != 1)
1485 return(-1);
1486
1487 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1488 return(0);
1489 TODO
1490 return(0);
1491}
1492
1493/**
1494 * xmlTextReaderReadBinHex:
1495 * @reader: the xmlTextReaderPtr used
1496 * @array: a byte array to store the content.
1497 * @offset: the zero-based index into array where the method should
1498 * begin to write.
1499 * @len: the number of bytes to write.
1500 *
1501 * Reads and decodes the BinHex encoded contents of an element and
1502 * stores the result in a byte buffer.
1503 *
1504 * Returns the number of bytes written to array, or zero if the current
1505 * instance is not positioned on an element or -1 in case of error.
1506 */
1507int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001508xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1509 unsigned char *array ATTRIBUTE_UNUSED,
1510 int offset ATTRIBUTE_UNUSED,
1511 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001512 if ((reader == NULL) || (reader->ctxt == NULL))
1513 return(-1);
1514 if (reader->ctxt->wellFormed != 1)
1515 return(-1);
1516
1517 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1518 return(0);
1519 TODO
1520 return(0);
1521}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001522#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001523
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001524/************************************************************************
1525 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001526 * Operating on a preparsed tree *
1527 * *
1528 ************************************************************************/
1529static int
1530xmlTextReaderNextTree(xmlTextReaderPtr reader)
1531{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001532 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001533 return(-1);
1534
1535 if (reader->state == XML_TEXTREADER_END)
1536 return(0);
1537
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001538 if (reader->node == NULL) {
1539 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001540 reader->state = XML_TEXTREADER_END;
1541 return(0);
1542 }
1543
1544 reader->node = reader->doc->children;
1545 reader->state = XML_TEXTREADER_START;
1546 return(1);
1547 }
1548
1549 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1550 if (reader->node->children != 0) {
1551 reader->node = reader->node->children;
1552 reader->depth++;
1553 reader->state = XML_TEXTREADER_START;
1554 return(1);
1555 }
1556
1557 if ((reader->node->type == XML_ELEMENT_NODE) ||
1558 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1559 reader->state = XML_TEXTREADER_BACKTRACK;
1560 return(1);
1561 }
1562 }
1563
1564 if (reader->node->next != 0) {
1565 reader->node = reader->node->next;
1566 reader->state = XML_TEXTREADER_START;
1567 return(1);
1568 }
1569
1570 if (reader->node->parent != 0) {
1571 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1572 reader->state = XML_TEXTREADER_END;
1573 return(0);
1574 }
1575
1576 reader->node = reader->node->parent;
1577 reader->depth--;
1578 reader->state = XML_TEXTREADER_BACKTRACK;
1579 return(1);
1580 }
1581
1582 reader->state = XML_TEXTREADER_END;
1583
1584 return(1);
1585}
1586
1587/**
1588 * xmlTextReaderReadTree:
1589 * @reader: the xmlTextReaderPtr used
1590 *
1591 * Moves the position of the current instance to the next node in
1592 * the stream, exposing its properties.
1593 *
1594 * Returns 1 if the node was read successfully, 0 if there is no more
1595 * nodes to read, or -1 in case of error
1596 */
1597static int
1598xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1599 if (reader->state == XML_TEXTREADER_END)
1600 return(0);
1601
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001602next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001603 if (reader->node == NULL) {
1604 if (reader->doc->children == NULL) {
1605 reader->state = XML_TEXTREADER_END;
1606 return(0);
1607 }
1608
1609 reader->node = reader->doc->children;
1610 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001611 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001612 }
1613
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001614 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1615 (reader->node->type != XML_DTD_NODE) &&
1616 (reader->node->type != XML_XINCLUDE_START) &&
1617 (reader->node->type != XML_ENTITY_REF_NODE)) {
1618 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001619 reader->node = reader->node->children;
1620 reader->depth++;
1621 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001622 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001623 }
1624
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001625 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001626 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001627 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001628 }
1629 }
1630
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001631 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001632 reader->node = reader->node->next;
1633 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001634 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001635 }
1636
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001637 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001638 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1639 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1640 reader->state = XML_TEXTREADER_END;
1641 return(0);
1642 }
1643
1644 reader->node = reader->node->parent;
1645 reader->depth--;
1646 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001647 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001648 }
1649
1650 reader->state = XML_TEXTREADER_END;
1651
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001652found_node:
1653 if ((reader->node->type == XML_XINCLUDE_START) ||
1654 (reader->node->type == XML_XINCLUDE_END))
1655 goto next_node;
1656
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001657 return(1);
1658}
1659
1660/**
1661 * xmlTextReaderNextTree:
1662 * @reader: the xmlTextReaderPtr used
1663 *
1664 * Skip to the node following the current one in document order while
1665 * avoiding the subtree if any.
1666 * Currently implemented only for Readers built on a document
1667 *
1668 * Returns 1 if the node was read successfully, 0 if there is no more
1669 * nodes to read, or -1 in case of error
1670 */
1671int
1672xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1673 if (reader == NULL)
1674 return(-1);
1675 if (reader->doc == NULL) {
1676 TODO
1677 return(-1);
1678 }
1679
1680 if (reader->state == XML_TEXTREADER_END)
1681 return(0);
1682
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001683 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001684 return(xmlTextReaderNextTree(reader));
1685
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001686 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001687 reader->node = reader->node->next;
1688 reader->state = XML_TEXTREADER_START;
1689 return(1);
1690 }
1691
1692 return(0);
1693}
1694
1695/************************************************************************
1696 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001697 * Constructor and destructors *
1698 * *
1699 ************************************************************************/
1700/**
1701 * xmlNewTextReader:
1702 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001703 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001704 *
1705 * Create an xmlTextReader structure fed with @input
1706 *
1707 * Returns the new xmlTextReaderPtr or NULL in case of error
1708 */
1709xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001710xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001711 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001712
1713 if (input == NULL)
1714 return(NULL);
1715 ret = xmlMalloc(sizeof(xmlTextReader));
1716 if (ret == NULL) {
1717 xmlGenericError(xmlGenericErrorContext,
1718 "xmlNewTextReader : malloc failed\n");
1719 return(NULL);
1720 }
1721 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001722 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001723 ret->entTab = NULL;
1724 ret->entMax = 0;
1725 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001726 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001727 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001728 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1729 if (ret->sax == NULL) {
1730 xmlFree(ret);
1731 xmlGenericError(xmlGenericErrorContext,
1732 "xmlNewTextReader : malloc failed\n");
1733 return(NULL);
1734 }
Daniel Veillard81273902003-09-30 00:43:48 +00001735 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001736 ret->startElement = ret->sax->startElement;
1737 ret->sax->startElement = xmlTextReaderStartElement;
1738 ret->endElement = ret->sax->endElement;
1739 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001740#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001741 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001742#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001743 ret->startElementNs = ret->sax->startElementNs;
1744 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1745 ret->endElementNs = ret->sax->endElementNs;
1746 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001747#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001748 } else {
1749 ret->startElementNs = NULL;
1750 ret->endElementNs = NULL;
1751 }
Daniel Veillard81273902003-09-30 00:43:48 +00001752#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001753 ret->characters = ret->sax->characters;
1754 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001755 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001756 ret->cdataBlock = ret->sax->cdataBlock;
1757 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001758
Daniel Veillard67df8092002-12-16 22:04:11 +00001759 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001760 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001761 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001762 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001763 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001764 }
1765 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001766 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001767 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001768 ret->base = 0;
1769 ret->cur = 4;
1770 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001771 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001772 ret->base = 0;
1773 ret->cur = 0;
1774 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001775 if (ret->ctxt == NULL) {
1776 xmlGenericError(xmlGenericErrorContext,
1777 "xmlNewTextReader : malloc failed\n");
1778 xmlFree(ret->sax);
1779 xmlFree(ret);
1780 return(NULL);
1781 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001782 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001783 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001784 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001785 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001786 /*
1787 * use the parser dictionnary to allocate all elements and attributes names
1788 */
1789 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001790 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001791#ifdef LIBXML_XINCLUDE_ENABLED
1792 ret->xinclude = 0;
1793#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001794 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001795}
1796
1797/**
1798 * xmlNewTextReaderFilename:
1799 * @URI: the URI of the resource to process
1800 *
1801 * Create an xmlTextReader structure fed with the resource at @URI
1802 *
1803 * Returns the new xmlTextReaderPtr or NULL in case of error
1804 */
1805xmlTextReaderPtr
1806xmlNewTextReaderFilename(const char *URI) {
1807 xmlParserInputBufferPtr input;
1808 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001809 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001810
1811 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1812 if (input == NULL)
1813 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001814 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001815 if (ret == NULL) {
1816 xmlFreeParserInputBuffer(input);
1817 return(NULL);
1818 }
1819 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001820 if (ret->ctxt->directory == NULL)
1821 directory = xmlParserGetDirectory(URI);
1822 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1823 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1824 if (directory != NULL)
1825 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001826 return(ret);
1827}
1828
1829/**
1830 * xmlFreeTextReader:
1831 * @reader: the xmlTextReaderPtr
1832 *
1833 * Deallocate all the resources associated to the reader
1834 */
1835void
1836xmlFreeTextReader(xmlTextReaderPtr reader) {
1837 if (reader == NULL)
1838 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001839#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001840 if (reader->rngSchemas != NULL) {
1841 xmlRelaxNGFree(reader->rngSchemas);
1842 reader->rngSchemas = NULL;
1843 }
1844 if (reader->rngValidCtxt != NULL) {
1845 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1846 reader->rngValidCtxt = NULL;
1847 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001848#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001849#ifdef LIBXML_XINCLUDE_ENABLED
1850 if (reader->xincctxt != NULL)
1851 xmlXIncludeFreeContext(reader->xincctxt);
1852#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001853 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001854 if (reader->dict == reader->ctxt->dict)
1855 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001856 if (reader->ctxt->myDoc != NULL) {
1857 if (reader->preserve == 0)
1858 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1859 reader->ctxt->myDoc = NULL;
1860 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001861 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1862 (reader->ctxt->vctxt.vstateMax > 0)){
1863 xmlFree(reader->ctxt->vctxt.vstateTab);
1864 reader->ctxt->vctxt.vstateTab = 0;
1865 reader->ctxt->vctxt.vstateMax = 0;
1866 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001867 if (reader->allocs & XML_TEXTREADER_CTXT)
1868 xmlFreeParserCtxt(reader->ctxt);
1869 }
1870 if (reader->sax != NULL)
1871 xmlFree(reader->sax);
1872 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1873 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001874 if (reader->faketext != NULL) {
1875 xmlFreeNode(reader->faketext);
1876 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001877 if (reader->buffer != NULL)
1878 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001879 if (reader->entTab != NULL)
1880 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001881 if (reader->dict != NULL)
1882 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001883 xmlFree(reader);
1884}
1885
1886/************************************************************************
1887 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001888 * Methods for XmlTextReader *
1889 * *
1890 ************************************************************************/
1891/**
1892 * xmlTextReaderClose:
1893 * @reader: the xmlTextReaderPtr used
1894 *
1895 * This method releases any resources allocated by the current instance
1896 * changes the state to Closed and close any underlying input.
1897 *
1898 * Returns 0 or -1 in case of error
1899 */
1900int
1901xmlTextReaderClose(xmlTextReaderPtr reader) {
1902 if (reader == NULL)
1903 return(-1);
1904 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001905 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001906 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1907 if (reader->ctxt != NULL) {
1908 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001909 if (reader->preserve == 0)
1910 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001911 reader->ctxt->myDoc = NULL;
1912 }
1913 if (reader->allocs & XML_TEXTREADER_CTXT) {
1914 xmlFreeParserCtxt(reader->ctxt);
1915 reader->allocs -= XML_TEXTREADER_CTXT;
1916 }
1917 }
1918 if (reader->sax != NULL) {
1919 xmlFree(reader->sax);
1920 reader->sax = NULL;
1921 }
1922 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1923 xmlFreeParserInputBuffer(reader->input);
1924 reader->allocs -= XML_TEXTREADER_INPUT;
1925 }
1926 return(0);
1927}
1928
1929/**
1930 * xmlTextReaderGetAttributeNo:
1931 * @reader: the xmlTextReaderPtr used
1932 * @no: the zero-based index of the attribute relative to the containing element
1933 *
1934 * Provides the value of the attribute with the specified index relative
1935 * to the containing element.
1936 *
1937 * Returns a string containing the value of the specified attribute, or NULL
1938 * in case of error. The string must be deallocated by the caller.
1939 */
1940xmlChar *
1941xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1942 xmlChar *ret;
1943 int i;
1944 xmlAttrPtr cur;
1945 xmlNsPtr ns;
1946
1947 if (reader == NULL)
1948 return(NULL);
1949 if (reader->node == NULL)
1950 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001951 if (reader->curnode != NULL)
1952 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001953 /* TODO: handle the xmlDecl */
1954 if (reader->node->type != XML_ELEMENT_NODE)
1955 return(NULL);
1956
1957 ns = reader->node->nsDef;
1958 for (i = 0;(i < no) && (ns != NULL);i++) {
1959 ns = ns->next;
1960 }
1961 if (ns != NULL)
1962 return(xmlStrdup(ns->href));
1963
1964 cur = reader->node->properties;
1965 if (cur == NULL)
1966 return(NULL);
1967 for (;i < no;i++) {
1968 cur = cur->next;
1969 if (cur == NULL)
1970 return(NULL);
1971 }
1972 /* TODO walk the DTD if present */
1973
1974 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1975 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1976 return(ret);
1977}
1978
1979/**
1980 * xmlTextReaderGetAttribute:
1981 * @reader: the xmlTextReaderPtr used
1982 * @name: the qualified name of the attribute.
1983 *
1984 * Provides the value of the attribute with the specified qualified name.
1985 *
1986 * Returns a string containing the value of the specified attribute, or NULL
1987 * in case of error. The string must be deallocated by the caller.
1988 */
1989xmlChar *
1990xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1991 xmlChar *prefix = NULL;
1992 xmlChar *localname;
1993 xmlNsPtr ns;
1994 xmlChar *ret = NULL;
1995
1996 if ((reader == NULL) || (name == NULL))
1997 return(NULL);
1998 if (reader->node == NULL)
1999 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002000 if (reader->curnode != NULL)
2001 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002002
2003 /* TODO: handle the xmlDecl */
2004 if (reader->node->type != XML_ELEMENT_NODE)
2005 return(NULL);
2006
2007 localname = xmlSplitQName2(name, &prefix);
2008 if (localname == NULL)
2009 return(xmlGetProp(reader->node, name));
2010
2011 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2012 if (ns != NULL)
2013 ret = xmlGetNsProp(reader->node, localname, ns->href);
2014
2015 if (localname != NULL)
2016 xmlFree(localname);
2017 if (prefix != NULL)
2018 xmlFree(prefix);
2019 return(ret);
2020}
2021
2022
2023/**
2024 * xmlTextReaderGetAttributeNs:
2025 * @reader: the xmlTextReaderPtr used
2026 * @localName: the local name of the attribute.
2027 * @namespaceURI: the namespace URI of the attribute.
2028 *
2029 * Provides the value of the specified attribute
2030 *
2031 * Returns a string containing the value of the specified attribute, or NULL
2032 * in case of error. The string must be deallocated by the caller.
2033 */
2034xmlChar *
2035xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2036 const xmlChar *namespaceURI) {
2037 if ((reader == NULL) || (localName == NULL))
2038 return(NULL);
2039 if (reader->node == NULL)
2040 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002041 if (reader->curnode != NULL)
2042 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002043
2044 /* TODO: handle the xmlDecl */
2045 if (reader->node->type != XML_ELEMENT_NODE)
2046 return(NULL);
2047
2048 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2049}
2050
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002051/**
2052 * xmlTextReaderGetRemainder:
2053 * @reader: the xmlTextReaderPtr used
2054 *
2055 * Method to get the remainder of the buffered XML. this method stops the
2056 * parser, set its state to End Of File and return the input stream with
2057 * what is left that the parser did not use.
2058 *
2059 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2060 * in case of error.
2061 */
2062xmlParserInputBufferPtr
2063xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2064 xmlParserInputBufferPtr ret = NULL;
2065
2066 if (reader == NULL)
2067 return(NULL);
2068 if (reader->node == NULL)
2069 return(NULL);
2070
2071 reader->node = NULL;
2072 reader->curnode = NULL;
2073 reader->mode = XML_TEXTREADER_MODE_EOF;
2074 if (reader->ctxt != NULL) {
2075 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002076 if (reader->preserve == 0)
2077 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002078 reader->ctxt->myDoc = NULL;
2079 }
2080 if (reader->allocs & XML_TEXTREADER_CTXT) {
2081 xmlFreeParserCtxt(reader->ctxt);
2082 reader->allocs -= XML_TEXTREADER_CTXT;
2083 }
2084 }
2085 if (reader->sax != NULL) {
2086 xmlFree(reader->sax);
2087 reader->sax = NULL;
2088 }
2089 if (reader->allocs & XML_TEXTREADER_INPUT) {
2090 ret = reader->input;
2091 reader->allocs -= XML_TEXTREADER_INPUT;
2092 } else {
2093 /*
2094 * Hum, one may need to duplicate the data structure because
2095 * without reference counting the input may be freed twice:
2096 * - by the layer which allocated it.
2097 * - by the layer to which would have been returned to.
2098 */
2099 TODO
2100 return(NULL);
2101 }
2102 return(ret);
2103}
2104
2105/**
2106 * xmlTextReaderLookupNamespace:
2107 * @reader: the xmlTextReaderPtr used
2108 * @prefix: the prefix whose namespace URI is to be resolved. To return
2109 * the default namespace, specify NULL
2110 *
2111 * Resolves a namespace prefix in the scope of the current element.
2112 *
2113 * Returns a string containing the namespace URI to which the prefix maps
2114 * or NULL in case of error. The string must be deallocated by the caller.
2115 */
2116xmlChar *
2117xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2118 xmlNsPtr ns;
2119
2120 if (reader == NULL)
2121 return(NULL);
2122 if (reader->node == NULL)
2123 return(NULL);
2124
2125 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2126 if (ns == NULL)
2127 return(NULL);
2128 return(xmlStrdup(ns->href));
2129}
2130
2131/**
2132 * xmlTextReaderMoveToAttributeNo:
2133 * @reader: the xmlTextReaderPtr used
2134 * @no: the zero-based index of the attribute relative to the containing
2135 * element.
2136 *
2137 * Moves the position of the current instance to the attribute with
2138 * the specified index relative to the containing element.
2139 *
2140 * Returns 1 in case of success, -1 in case of error, 0 if not found
2141 */
2142int
2143xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2144 int i;
2145 xmlAttrPtr cur;
2146 xmlNsPtr ns;
2147
2148 if (reader == NULL)
2149 return(-1);
2150 if (reader->node == NULL)
2151 return(-1);
2152 /* TODO: handle the xmlDecl */
2153 if (reader->node->type != XML_ELEMENT_NODE)
2154 return(-1);
2155
2156 reader->curnode = NULL;
2157
2158 ns = reader->node->nsDef;
2159 for (i = 0;(i < no) && (ns != NULL);i++) {
2160 ns = ns->next;
2161 }
2162 if (ns != NULL) {
2163 reader->curnode = (xmlNodePtr) ns;
2164 return(1);
2165 }
2166
2167 cur = reader->node->properties;
2168 if (cur == NULL)
2169 return(0);
2170 for (;i < no;i++) {
2171 cur = cur->next;
2172 if (cur == NULL)
2173 return(0);
2174 }
2175 /* TODO walk the DTD if present */
2176
2177 reader->curnode = (xmlNodePtr) cur;
2178 return(1);
2179}
2180
2181/**
2182 * xmlTextReaderMoveToAttribute:
2183 * @reader: the xmlTextReaderPtr used
2184 * @name: the qualified name of the attribute.
2185 *
2186 * Moves the position of the current instance to the attribute with
2187 * the specified qualified name.
2188 *
2189 * Returns 1 in case of success, -1 in case of error, 0 if not found
2190 */
2191int
2192xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2193 xmlChar *prefix = NULL;
2194 xmlChar *localname;
2195 xmlNsPtr ns;
2196 xmlAttrPtr prop;
2197
2198 if ((reader == NULL) || (name == NULL))
2199 return(-1);
2200 if (reader->node == NULL)
2201 return(-1);
2202
2203 /* TODO: handle the xmlDecl */
2204 if (reader->node->type != XML_ELEMENT_NODE)
2205 return(0);
2206
2207 localname = xmlSplitQName2(name, &prefix);
2208 if (localname == NULL) {
2209 /*
2210 * Namespace default decl
2211 */
2212 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2213 ns = reader->node->nsDef;
2214 while (ns != NULL) {
2215 if (ns->prefix == NULL) {
2216 reader->curnode = (xmlNodePtr) ns;
2217 return(1);
2218 }
2219 ns = ns->next;
2220 }
2221 return(0);
2222 }
2223
2224 prop = reader->node->properties;
2225 while (prop != NULL) {
2226 /*
2227 * One need to have
2228 * - same attribute names
2229 * - and the attribute carrying that namespace
2230 */
2231 if ((xmlStrEqual(prop->name, name)) &&
2232 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2233 reader->curnode = (xmlNodePtr) prop;
2234 return(1);
2235 }
2236 prop = prop->next;
2237 }
2238 return(0);
2239 }
2240
2241 /*
2242 * Namespace default decl
2243 */
2244 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2245 ns = reader->node->nsDef;
2246 while (ns != NULL) {
2247 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2248 reader->curnode = (xmlNodePtr) ns;
2249 goto found;
2250 }
2251 ns = ns->next;
2252 }
2253 goto not_found;
2254 }
2255 prop = reader->node->properties;
2256 while (prop != NULL) {
2257 /*
2258 * One need to have
2259 * - same attribute names
2260 * - and the attribute carrying that namespace
2261 */
2262 if ((xmlStrEqual(prop->name, localname)) &&
2263 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2264 reader->curnode = (xmlNodePtr) prop;
2265 goto found;
2266 }
2267 prop = prop->next;
2268 }
2269not_found:
2270 if (localname != NULL)
2271 xmlFree(localname);
2272 if (prefix != NULL)
2273 xmlFree(prefix);
2274 return(0);
2275
2276found:
2277 if (localname != NULL)
2278 xmlFree(localname);
2279 if (prefix != NULL)
2280 xmlFree(prefix);
2281 return(1);
2282}
2283
2284/**
2285 * xmlTextReaderMoveToAttributeNs:
2286 * @reader: the xmlTextReaderPtr used
2287 * @localName: the local name of the attribute.
2288 * @namespaceURI: the namespace URI of the attribute.
2289 *
2290 * Moves the position of the current instance to the attribute with the
2291 * specified local name and namespace URI.
2292 *
2293 * Returns 1 in case of success, -1 in case of error, 0 if not found
2294 */
2295int
2296xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2297 const xmlChar *localName, const xmlChar *namespaceURI) {
2298 xmlAttrPtr prop;
2299 xmlNodePtr node;
2300
2301 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2302 return(-1);
2303 if (reader->node == NULL)
2304 return(-1);
2305 if (reader->node->type != XML_ELEMENT_NODE)
2306 return(0);
2307 node = reader->node;
2308
2309 /*
2310 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2311 * namespace name associated to "xmlns"
2312 */
2313 prop = node->properties;
2314 while (prop != NULL) {
2315 /*
2316 * One need to have
2317 * - same attribute names
2318 * - and the attribute carrying that namespace
2319 */
2320 if (xmlStrEqual(prop->name, localName) &&
2321 ((prop->ns != NULL) &&
2322 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2323 reader->curnode = (xmlNodePtr) prop;
2324 return(1);
2325 }
2326 prop = prop->next;
2327 }
2328 return(0);
2329}
2330
2331/**
2332 * xmlTextReaderMoveToFirstAttribute:
2333 * @reader: the xmlTextReaderPtr used
2334 *
2335 * Moves the position of the current instance to the first attribute
2336 * associated with the current node.
2337 *
2338 * Returns 1 in case of success, -1 in case of error, 0 if not found
2339 */
2340int
2341xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2342 if (reader == NULL)
2343 return(-1);
2344 if (reader->node == NULL)
2345 return(-1);
2346 if (reader->node->type != XML_ELEMENT_NODE)
2347 return(0);
2348
2349 if (reader->node->nsDef != NULL) {
2350 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2351 return(1);
2352 }
2353 if (reader->node->properties != NULL) {
2354 reader->curnode = (xmlNodePtr) reader->node->properties;
2355 return(1);
2356 }
2357 return(0);
2358}
2359
2360/**
2361 * xmlTextReaderMoveToNextAttribute:
2362 * @reader: the xmlTextReaderPtr used
2363 *
2364 * Moves the position of the current instance to the next attribute
2365 * associated with the current node.
2366 *
2367 * Returns 1 in case of success, -1 in case of error, 0 if not found
2368 */
2369int
2370xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2371 if (reader == NULL)
2372 return(-1);
2373 if (reader->node == NULL)
2374 return(-1);
2375 if (reader->node->type != XML_ELEMENT_NODE)
2376 return(0);
2377 if (reader->curnode == NULL)
2378 return(xmlTextReaderMoveToFirstAttribute(reader));
2379
2380 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2381 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2382 if (ns->next != NULL) {
2383 reader->curnode = (xmlNodePtr) ns->next;
2384 return(1);
2385 }
2386 if (reader->node->properties != NULL) {
2387 reader->curnode = (xmlNodePtr) reader->node->properties;
2388 return(1);
2389 }
2390 return(0);
2391 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2392 (reader->curnode->next != NULL)) {
2393 reader->curnode = reader->curnode->next;
2394 return(1);
2395 }
2396 return(0);
2397}
2398
2399/**
2400 * xmlTextReaderMoveToElement:
2401 * @reader: the xmlTextReaderPtr used
2402 *
2403 * Moves the position of the current instance to the node that
2404 * contains the current Attribute node.
2405 *
2406 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2407 */
2408int
2409xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2410 if (reader == NULL)
2411 return(-1);
2412 if (reader->node == NULL)
2413 return(-1);
2414 if (reader->node->type != XML_ELEMENT_NODE)
2415 return(0);
2416 if (reader->curnode != NULL) {
2417 reader->curnode = NULL;
2418 return(1);
2419 }
2420 return(0);
2421}
2422
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002423/**
2424 * xmlTextReaderReadAttributeValue:
2425 * @reader: the xmlTextReaderPtr used
2426 *
2427 * Parses an attribute value into one or more Text and EntityReference nodes.
2428 *
2429 * Returns 1 in case of success, 0 if the reader was not positionned on an
2430 * ttribute node or all the attribute values have been read, or -1
2431 * in case of error.
2432 */
2433int
2434xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2435 if (reader == NULL)
2436 return(-1);
2437 if (reader->node == NULL)
2438 return(-1);
2439 if (reader->curnode == NULL)
2440 return(0);
2441 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2442 if (reader->curnode->children == NULL)
2443 return(0);
2444 reader->curnode = reader->curnode->children;
2445 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2446 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2447
2448 if (reader->faketext == NULL) {
2449 reader->faketext = xmlNewDocText(reader->node->doc,
2450 ns->href);
2451 } else {
2452 if (reader->faketext->content != NULL)
2453 xmlFree(reader->faketext->content);
2454 reader->faketext->content = xmlStrdup(ns->href);
2455 }
2456 reader->curnode = reader->faketext;
2457 } else {
2458 if (reader->curnode->next == NULL)
2459 return(0);
2460 reader->curnode = reader->curnode->next;
2461 }
2462 return(1);
2463}
2464
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002465/************************************************************************
2466 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002467 * Acces API to the current node *
2468 * *
2469 ************************************************************************/
2470/**
2471 * xmlTextReaderAttributeCount:
2472 * @reader: the xmlTextReaderPtr used
2473 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002474 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002475 *
2476 * Returns 0 i no attributes, -1 in case of error or the attribute count
2477 */
2478int
2479xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2480 int ret;
2481 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002482 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002483 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002484
2485 if (reader == NULL)
2486 return(-1);
2487 if (reader->node == NULL)
2488 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002489
2490 if (reader->curnode != NULL)
2491 node = reader->curnode;
2492 else
2493 node = reader->node;
2494
2495 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002496 return(0);
2497 if ((reader->state == XML_TEXTREADER_END) ||
2498 (reader->state == XML_TEXTREADER_BACKTRACK))
2499 return(0);
2500 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002501 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002502 while (attr != NULL) {
2503 ret++;
2504 attr = attr->next;
2505 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002506 ns = node->nsDef;
2507 while (ns != NULL) {
2508 ret++;
2509 ns = ns->next;
2510 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002511 return(ret);
2512}
2513
2514/**
2515 * xmlTextReaderNodeType:
2516 * @reader: the xmlTextReaderPtr used
2517 *
2518 * Get the node type of the current node
2519 * Reference:
2520 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2521 *
2522 * Returns the xmlNodeType of the current node or -1 in case of error
2523 */
2524int
2525xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002526 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002527
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002528 if (reader == NULL)
2529 return(-1);
2530 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002531 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002532 if (reader->curnode != NULL)
2533 node = reader->curnode;
2534 else
2535 node = reader->node;
2536 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002537 case XML_ELEMENT_NODE:
2538 if ((reader->state == XML_TEXTREADER_END) ||
2539 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002540 return(XML_READER_TYPE_END_ELEMENT);
2541 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002542 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002543 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002544 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002545 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002546 if (xmlIsBlankNode(reader->node)) {
2547 if (xmlNodeGetSpacePreserve(reader->node))
2548 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2549 else
2550 return(XML_READER_TYPE_WHITESPACE);
2551 } else {
2552 return(XML_READER_TYPE_TEXT);
2553 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002554 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002555 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002556 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002557 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002558 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002559 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002560 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002561 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002562 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002563 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002564 case XML_DOCUMENT_NODE:
2565 case XML_HTML_DOCUMENT_NODE:
2566#ifdef LIBXML_DOCB_ENABLED
2567 case XML_DOCB_DOCUMENT_NODE:
2568#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002569 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002570 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002571 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002572 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002573 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002574 case XML_DOCUMENT_TYPE_NODE:
2575 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002576 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002577
2578 case XML_ELEMENT_DECL:
2579 case XML_ATTRIBUTE_DECL:
2580 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002581 case XML_XINCLUDE_START:
2582 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002583 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002584 }
2585 return(-1);
2586}
2587
2588/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002589 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002590 * @reader: the xmlTextReaderPtr used
2591 *
2592 * Check if the current node is empty
2593 *
2594 * Returns 1 if empty, 0 if not and -1 in case of error
2595 */
2596int
2597xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2598 if ((reader == NULL) || (reader->node == NULL))
2599 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002600 if (reader->node->type != XML_ELEMENT_NODE)
2601 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002602 if (reader->curnode != NULL)
2603 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002604 if (reader->node->children != NULL)
2605 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002606 if (reader->state == XML_TEXTREADER_END)
2607 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002608 if (reader->doc != NULL)
2609 return(1);
2610 if (reader->in_xinclude > 0)
2611 return(1);
Daniel Veillarde8039df2003-10-27 11:25:13 +00002612 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002613}
2614
2615/**
2616 * xmlTextReaderLocalName:
2617 * @reader: the xmlTextReaderPtr used
2618 *
2619 * The local name of the node.
2620 *
2621 * Returns the local name or NULL if not available
2622 */
2623xmlChar *
2624xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002625 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002626 if ((reader == NULL) || (reader->node == NULL))
2627 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002628 if (reader->curnode != NULL)
2629 node = reader->curnode;
2630 else
2631 node = reader->node;
2632 if (node->type == XML_NAMESPACE_DECL) {
2633 xmlNsPtr ns = (xmlNsPtr) node;
2634 if (ns->prefix == NULL)
2635 return(xmlStrdup(BAD_CAST "xmlns"));
2636 else
2637 return(xmlStrdup(ns->prefix));
2638 }
2639 if ((node->type != XML_ELEMENT_NODE) &&
2640 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002641 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002642 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002643}
2644
2645/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002646 * xmlTextReaderConstLocalName:
2647 * @reader: the xmlTextReaderPtr used
2648 *
2649 * The local name of the node.
2650 *
2651 * Returns the local name or NULL if not available, the
2652 * string will be deallocated with the reader.
2653 */
2654const xmlChar *
2655xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2656 xmlNodePtr node;
2657 if ((reader == NULL) || (reader->node == NULL))
2658 return(NULL);
2659 if (reader->curnode != NULL)
2660 node = reader->curnode;
2661 else
2662 node = reader->node;
2663 if (node->type == XML_NAMESPACE_DECL) {
2664 xmlNsPtr ns = (xmlNsPtr) node;
2665 if (ns->prefix == NULL)
2666 return(CONSTSTR(BAD_CAST "xmlns"));
2667 else
2668 return(ns->prefix);
2669 }
2670 if ((node->type != XML_ELEMENT_NODE) &&
2671 (node->type != XML_ATTRIBUTE_NODE))
2672 return(xmlTextReaderConstName(reader));
2673 return(node->name);
2674}
2675
2676/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002677 * xmlTextReaderName:
2678 * @reader: the xmlTextReaderPtr used
2679 *
2680 * The qualified name of the node, equal to Prefix :LocalName.
2681 *
2682 * Returns the local name or NULL if not available
2683 */
2684xmlChar *
2685xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002686 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002687 xmlChar *ret;
2688
2689 if ((reader == NULL) || (reader->node == NULL))
2690 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002691 if (reader->curnode != NULL)
2692 node = reader->curnode;
2693 else
2694 node = reader->node;
2695 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002696 case XML_ELEMENT_NODE:
2697 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002698 if ((node->ns == NULL) ||
2699 (node->ns->prefix == NULL))
2700 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002701
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002702 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002703 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002704 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002705 return(ret);
2706 case XML_TEXT_NODE:
2707 return(xmlStrdup(BAD_CAST "#text"));
2708 case XML_CDATA_SECTION_NODE:
2709 return(xmlStrdup(BAD_CAST "#cdata-section"));
2710 case XML_ENTITY_NODE:
2711 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002712 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002713 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002714 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002715 case XML_COMMENT_NODE:
2716 return(xmlStrdup(BAD_CAST "#comment"));
2717 case XML_DOCUMENT_NODE:
2718 case XML_HTML_DOCUMENT_NODE:
2719#ifdef LIBXML_DOCB_ENABLED
2720 case XML_DOCB_DOCUMENT_NODE:
2721#endif
2722 return(xmlStrdup(BAD_CAST "#document"));
2723 case XML_DOCUMENT_FRAG_NODE:
2724 return(xmlStrdup(BAD_CAST "#document-fragment"));
2725 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002726 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002727 case XML_DOCUMENT_TYPE_NODE:
2728 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002729 return(xmlStrdup(node->name));
2730 case XML_NAMESPACE_DECL: {
2731 xmlNsPtr ns = (xmlNsPtr) node;
2732
2733 ret = xmlStrdup(BAD_CAST "xmlns");
2734 if (ns->prefix == NULL)
2735 return(ret);
2736 ret = xmlStrcat(ret, BAD_CAST ":");
2737 ret = xmlStrcat(ret, ns->prefix);
2738 return(ret);
2739 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002740
2741 case XML_ELEMENT_DECL:
2742 case XML_ATTRIBUTE_DECL:
2743 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002744 case XML_XINCLUDE_START:
2745 case XML_XINCLUDE_END:
2746 return(NULL);
2747 }
2748 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002749}
2750
2751/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002752 * xmlTextReaderConstName:
2753 * @reader: the xmlTextReaderPtr used
2754 *
2755 * The qualified name of the node, equal to Prefix :LocalName.
2756 *
2757 * Returns the local name or NULL if not available, the string is
2758 * deallocated with the reader.
2759 */
2760const xmlChar *
2761xmlTextReaderConstName(xmlTextReaderPtr reader) {
2762 xmlNodePtr node;
2763
2764 if ((reader == NULL) || (reader->node == NULL))
2765 return(NULL);
2766 if (reader->curnode != NULL)
2767 node = reader->curnode;
2768 else
2769 node = reader->node;
2770 switch (node->type) {
2771 case XML_ELEMENT_NODE:
2772 case XML_ATTRIBUTE_NODE:
2773 if ((node->ns == NULL) ||
2774 (node->ns->prefix == NULL))
2775 return(node->name);
2776 return(CONSTQSTR(node->ns->prefix, node->name));
2777 case XML_TEXT_NODE:
2778 return(CONSTSTR(BAD_CAST "#text"));
2779 case XML_CDATA_SECTION_NODE:
2780 return(CONSTSTR(BAD_CAST "#cdata-section"));
2781 case XML_ENTITY_NODE:
2782 case XML_ENTITY_REF_NODE:
2783 return(CONSTSTR(node->name));
2784 case XML_PI_NODE:
2785 return(CONSTSTR(node->name));
2786 case XML_COMMENT_NODE:
2787 return(CONSTSTR(BAD_CAST "#comment"));
2788 case XML_DOCUMENT_NODE:
2789 case XML_HTML_DOCUMENT_NODE:
2790#ifdef LIBXML_DOCB_ENABLED
2791 case XML_DOCB_DOCUMENT_NODE:
2792#endif
2793 return(CONSTSTR(BAD_CAST "#document"));
2794 case XML_DOCUMENT_FRAG_NODE:
2795 return(CONSTSTR(BAD_CAST "#document-fragment"));
2796 case XML_NOTATION_NODE:
2797 return(CONSTSTR(node->name));
2798 case XML_DOCUMENT_TYPE_NODE:
2799 case XML_DTD_NODE:
2800 return(CONSTSTR(node->name));
2801 case XML_NAMESPACE_DECL: {
2802 xmlNsPtr ns = (xmlNsPtr) node;
2803
2804 if (ns->prefix == NULL)
2805 return(CONSTSTR(BAD_CAST "xmlns"));
2806 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2807 }
2808
2809 case XML_ELEMENT_DECL:
2810 case XML_ATTRIBUTE_DECL:
2811 case XML_ENTITY_DECL:
2812 case XML_XINCLUDE_START:
2813 case XML_XINCLUDE_END:
2814 return(NULL);
2815 }
2816 return(NULL);
2817}
2818
2819/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002820 * xmlTextReaderPrefix:
2821 * @reader: the xmlTextReaderPtr used
2822 *
2823 * A shorthand reference to the namespace associated with the node.
2824 *
2825 * Returns the prefix or NULL if not available
2826 */
2827xmlChar *
2828xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002829 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002830 if ((reader == NULL) || (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;
2836 if (node->type == XML_NAMESPACE_DECL) {
2837 xmlNsPtr ns = (xmlNsPtr) node;
2838 if (ns->prefix == NULL)
2839 return(NULL);
2840 return(xmlStrdup(BAD_CAST "xmlns"));
2841 }
2842 if ((node->type != XML_ELEMENT_NODE) &&
2843 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002844 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002845 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002846 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002847 return(NULL);
2848}
2849
2850/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002851 * xmlTextReaderConstPrefix:
2852 * @reader: the xmlTextReaderPtr used
2853 *
2854 * A shorthand reference to the namespace associated with the node.
2855 *
2856 * Returns the prefix or NULL if not available, the string is deallocated
2857 * with the reader.
2858 */
2859const xmlChar *
2860xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2861 xmlNodePtr node;
2862 if ((reader == NULL) || (reader->node == NULL))
2863 return(NULL);
2864 if (reader->curnode != NULL)
2865 node = reader->curnode;
2866 else
2867 node = reader->node;
2868 if (node->type == XML_NAMESPACE_DECL) {
2869 xmlNsPtr ns = (xmlNsPtr) node;
2870 if (ns->prefix == NULL)
2871 return(NULL);
2872 return(CONSTSTR(BAD_CAST "xmlns"));
2873 }
2874 if ((node->type != XML_ELEMENT_NODE) &&
2875 (node->type != XML_ATTRIBUTE_NODE))
2876 return(NULL);
2877 if ((node->ns != NULL) && (node->ns->prefix != NULL))
2878 return(CONSTSTR(node->ns->prefix));
2879 return(NULL);
2880}
2881
2882/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002883 * xmlTextReaderNamespaceUri:
2884 * @reader: the xmlTextReaderPtr used
2885 *
2886 * The URI defining the namespace associated with the node.
2887 *
2888 * Returns the namespace URI or NULL if not available
2889 */
2890xmlChar *
2891xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002892 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002893 if ((reader == NULL) || (reader->node == NULL))
2894 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002895 if (reader->curnode != NULL)
2896 node = reader->curnode;
2897 else
2898 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00002899 if (node->type == XML_NAMESPACE_DECL)
2900 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002901 if ((node->type != XML_ELEMENT_NODE) &&
2902 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002903 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002904 if (node->ns != NULL)
2905 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002906 return(NULL);
2907}
2908
2909/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002910 * xmlTextReaderConstNamespaceUri:
2911 * @reader: the xmlTextReaderPtr used
2912 *
2913 * The URI defining the namespace associated with the node.
2914 *
2915 * Returns the namespace URI or NULL if not available, the string
2916 * will be deallocated with the reader
2917 */
2918const xmlChar *
2919xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
2920 xmlNodePtr node;
2921 if ((reader == NULL) || (reader->node == NULL))
2922 return(NULL);
2923 if (reader->curnode != NULL)
2924 node = reader->curnode;
2925 else
2926 node = reader->node;
2927 if (node->type == XML_NAMESPACE_DECL)
2928 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
2929 if ((node->type != XML_ELEMENT_NODE) &&
2930 (node->type != XML_ATTRIBUTE_NODE))
2931 return(NULL);
2932 if (node->ns != NULL)
2933 return(CONSTSTR(node->ns->href));
2934 return(NULL);
2935}
2936
2937/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002938 * xmlTextReaderBaseUri:
2939 * @reader: the xmlTextReaderPtr used
2940 *
2941 * The base URI of the node.
2942 *
2943 * Returns the base URI or NULL if not available
2944 */
2945xmlChar *
2946xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
2947 if ((reader == NULL) || (reader->node == NULL))
2948 return(NULL);
2949 return(xmlNodeGetBase(NULL, reader->node));
2950}
2951
2952/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002953 * xmlTextReaderConstBaseUri:
2954 * @reader: the xmlTextReaderPtr used
2955 *
2956 * The base URI of the node.
2957 *
2958 * Returns the base URI or NULL if not available, the string
2959 * will be deallocated with the reader
2960 */
2961const xmlChar *
2962xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
2963 xmlChar *tmp;
2964 const xmlChar *ret;
2965
2966 if ((reader == NULL) || (reader->node == NULL))
2967 return(NULL);
2968 tmp = xmlNodeGetBase(NULL, reader->node);
2969 if (tmp == NULL)
2970 return(NULL);
2971 ret = CONSTSTR(tmp);
2972 xmlFree(tmp);
2973 return(ret);
2974}
2975
2976/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002977 * xmlTextReaderDepth:
2978 * @reader: the xmlTextReaderPtr used
2979 *
2980 * The depth of the node in the tree.
2981 *
2982 * Returns the depth or -1 in case of error
2983 */
2984int
2985xmlTextReaderDepth(xmlTextReaderPtr reader) {
2986 if (reader == NULL)
2987 return(-1);
2988 if (reader->node == NULL)
2989 return(0);
2990
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002991 if (reader->curnode != NULL) {
2992 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
2993 (reader->curnode->type == XML_NAMESPACE_DECL))
2994 return(reader->depth + 1);
2995 return(reader->depth + 2);
2996 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002997 return(reader->depth);
2998}
2999
3000/**
3001 * xmlTextReaderHasAttributes:
3002 * @reader: the xmlTextReaderPtr used
3003 *
3004 * Whether the node has attributes.
3005 *
3006 * Returns 1 if true, 0 if false, and -1 in case or error
3007 */
3008int
3009xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003010 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003011 if (reader == NULL)
3012 return(-1);
3013 if (reader->node == NULL)
3014 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003015 if (reader->curnode != NULL)
3016 node = reader->curnode;
3017 else
3018 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003019
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003020 if ((node->type == XML_ELEMENT_NODE) &&
3021 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003022 return(1);
3023 /* TODO: handle the xmlDecl */
3024 return(0);
3025}
3026
3027/**
3028 * xmlTextReaderHasValue:
3029 * @reader: the xmlTextReaderPtr used
3030 *
3031 * Whether the node can have a text value.
3032 *
3033 * Returns 1 if true, 0 if false, and -1 in case or error
3034 */
3035int
3036xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003037 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003038 if (reader == NULL)
3039 return(-1);
3040 if (reader->node == NULL)
3041 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003042 if (reader->curnode != NULL)
3043 node = reader->curnode;
3044 else
3045 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003047 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003048 case XML_ATTRIBUTE_NODE:
3049 case XML_TEXT_NODE:
3050 case XML_CDATA_SECTION_NODE:
3051 case XML_PI_NODE:
3052 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003053 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003054 return(1);
3055 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003056 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003057 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003058 return(0);
3059}
3060
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003061/**
3062 * xmlTextReaderValue:
3063 * @reader: the xmlTextReaderPtr used
3064 *
3065 * Provides the text value of the node if present
3066 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003067 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003068 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003069 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003070xmlChar *
3071xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003072 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003073 if (reader == NULL)
3074 return(NULL);
3075 if (reader->node == NULL)
3076 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003077 if (reader->curnode != NULL)
3078 node = reader->curnode;
3079 else
3080 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003081
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003082 switch (node->type) {
3083 case XML_NAMESPACE_DECL:
3084 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003085 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003086 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003087
3088 if (attr->parent != NULL)
3089 return (xmlNodeListGetString
3090 (attr->parent->doc, attr->children, 1));
3091 else
3092 return (xmlNodeListGetString(NULL, attr->children, 1));
3093 break;
3094 }
3095 case XML_TEXT_NODE:
3096 case XML_CDATA_SECTION_NODE:
3097 case XML_PI_NODE:
3098 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003099 if (node->content != NULL)
3100 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003101 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003102 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003103 }
3104 return(NULL);
3105}
3106
3107/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003108 * xmlTextReaderConstValue:
3109 * @reader: the xmlTextReaderPtr used
3110 *
3111 * Provides the text value of the node if present
3112 *
3113 * Returns the string or NULL if not available. The result will be
3114 * deallocated on the next Read() operation.
3115 */
3116const xmlChar *
3117xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3118 xmlNodePtr node;
3119 if (reader == NULL)
3120 return(NULL);
3121 if (reader->node == NULL)
3122 return(NULL);
3123 if (reader->curnode != NULL)
3124 node = reader->curnode;
3125 else
3126 node = reader->node;
3127
3128 switch (node->type) {
3129 case XML_NAMESPACE_DECL:
3130 return(((xmlNsPtr) node)->href);
3131 case XML_ATTRIBUTE_NODE:{
3132 xmlAttrPtr attr = (xmlAttrPtr) node;
3133
3134 if ((attr->children != NULL) &&
3135 (attr->children->type == XML_TEXT_NODE) &&
3136 (attr->children->next == NULL))
3137 return(attr->children->content);
3138 else {
3139 reader->buffer->use = 0;
3140 xmlNodeBufGetContent(reader->buffer, node);
3141 return(reader->buffer->content);
3142 }
3143 break;
3144 }
3145 case XML_TEXT_NODE:
3146 case XML_CDATA_SECTION_NODE:
3147 case XML_PI_NODE:
3148 case XML_COMMENT_NODE:
3149 return(node->content);
3150 default:
3151 break;
3152 }
3153 return(NULL);
3154}
3155
3156/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003157 * xmlTextReaderIsDefault:
3158 * @reader: the xmlTextReaderPtr used
3159 *
3160 * Whether an Attribute node was generated from the default value
3161 * defined in the DTD or schema.
3162 *
3163 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3164 */
3165int
3166xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3167 if (reader == NULL)
3168 return(-1);
3169 return(0);
3170}
3171
3172/**
3173 * xmlTextReaderQuoteChar:
3174 * @reader: the xmlTextReaderPtr used
3175 *
3176 * The quotation mark character used to enclose the value of an attribute.
3177 *
3178 * Returns " or ' and -1 in case of error
3179 */
3180int
3181xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3182 if (reader == NULL)
3183 return(-1);
3184 /* TODO maybe lookup the attribute value for " first */
3185 return((int) '"');
3186}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003187
3188/**
3189 * xmlTextReaderXmlLang:
3190 * @reader: the xmlTextReaderPtr used
3191 *
3192 * The xml:lang scope within which the node resides.
3193 *
3194 * Returns the xml:lang value or NULL if none exists.
3195 */
3196xmlChar *
3197xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3198 if (reader == NULL)
3199 return(NULL);
3200 if (reader->node == NULL)
3201 return(NULL);
3202 return(xmlNodeGetLang(reader->node));
3203}
3204
Daniel Veillard67df8092002-12-16 22:04:11 +00003205/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003206 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003207 * @reader: the xmlTextReaderPtr used
3208 *
3209 * The xml:lang scope within which the node resides.
3210 *
3211 * Returns the xml:lang value or NULL if none exists.
3212 */
3213const xmlChar *
3214xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3215 xmlChar *tmp;
3216 const xmlChar *ret;
3217
3218 if (reader == NULL)
3219 return(NULL);
3220 if (reader->node == NULL)
3221 return(NULL);
3222 tmp = xmlNodeGetLang(reader->node);
3223 if (tmp == NULL)
3224 return(NULL);
3225 ret = CONSTSTR(tmp);
3226 xmlFree(tmp);
3227 return(ret);
3228}
3229
3230/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003231 * xmlTextReaderConstString:
3232 * @reader: the xmlTextReaderPtr used
3233 * @str: the string to intern.
3234 *
3235 * Get an interned string from the reader, allows for example to
3236 * speedup string name comparisons
3237 *
3238 * Returns an interned copy of the string or NULL in case of error. The
3239 * string will be deallocated with the reader.
3240 */
3241const xmlChar *
3242xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3243 if (reader == NULL)
3244 return(NULL);
3245 return(CONSTSTR(str));
3246}
3247
3248/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003249 * xmlTextReaderNormalization:
3250 * @reader: the xmlTextReaderPtr used
3251 *
3252 * The value indicating whether to normalize white space and attribute values.
3253 * Since attribute value and end of line normalizations are a MUST in the XML
3254 * specification only the value true is accepted. The broken bahaviour of
3255 * accepting out of range character entities like &#0; is of course not
3256 * supported either.
3257 *
3258 * Returns 1 or -1 in case of error.
3259 */
3260int
3261xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3262 if (reader == NULL)
3263 return(-1);
3264 return(1);
3265}
3266
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003267/************************************************************************
3268 * *
3269 * Extensions to the base APIs *
3270 * *
3271 ************************************************************************/
3272
3273/**
3274 * xmlTextReaderSetParserProp:
3275 * @reader: the xmlTextReaderPtr used
3276 * @prop: the xmlParserProperties to set
3277 * @value: usually 0 or 1 to (de)activate it
3278 *
3279 * Change the parser processing behaviour by changing some of its internal
3280 * properties. Note that some properties can only be changed before any
3281 * read has been done.
3282 *
3283 * Returns 0 if the call was successful, or -1 in case of error
3284 */
3285int
3286xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3287 xmlParserProperties p = (xmlParserProperties) prop;
3288 xmlParserCtxtPtr ctxt;
3289
3290 if ((reader == NULL) || (reader->ctxt == NULL))
3291 return(-1);
3292 ctxt = reader->ctxt;
3293
3294 switch (p) {
3295 case XML_PARSER_LOADDTD:
3296 if (value != 0) {
3297 if (ctxt->loadsubset == 0) {
3298 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3299 return(-1);
3300 ctxt->loadsubset = XML_DETECT_IDS;
3301 }
3302 } else {
3303 ctxt->loadsubset = 0;
3304 }
3305 return(0);
3306 case XML_PARSER_DEFAULTATTRS:
3307 if (value != 0) {
3308 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3309 } else {
3310 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3311 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3312 }
3313 return(0);
3314 case XML_PARSER_VALIDATE:
3315 if (value != 0) {
3316 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003317 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003318 } else {
3319 ctxt->validate = 0;
3320 }
3321 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003322 case XML_PARSER_SUBST_ENTITIES:
3323 if (value != 0) {
3324 ctxt->replaceEntities = 1;
3325 } else {
3326 ctxt->replaceEntities = 0;
3327 }
3328 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003329 }
3330 return(-1);
3331}
3332
3333/**
3334 * xmlTextReaderGetParserProp:
3335 * @reader: the xmlTextReaderPtr used
3336 * @prop: the xmlParserProperties to get
3337 *
3338 * Read the parser internal property.
3339 *
3340 * Returns the value, usually 0 or 1, or -1 in case of error.
3341 */
3342int
3343xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3344 xmlParserProperties p = (xmlParserProperties) prop;
3345 xmlParserCtxtPtr ctxt;
3346
3347 if ((reader == NULL) || (reader->ctxt == NULL))
3348 return(-1);
3349 ctxt = reader->ctxt;
3350
3351 switch (p) {
3352 case XML_PARSER_LOADDTD:
3353 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3354 return(1);
3355 return(0);
3356 case XML_PARSER_DEFAULTATTRS:
3357 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3358 return(1);
3359 return(0);
3360 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003361 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003362 case XML_PARSER_SUBST_ENTITIES:
3363 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003364 }
3365 return(-1);
3366}
3367
Daniel Veillarde18fc182002-12-28 22:56:33 +00003368/**
3369 * xmlTextReaderCurrentNode:
3370 * @reader: the xmlTextReaderPtr used
3371 *
3372 * Hacking interface allowing to get the xmlNodePtr correponding to the
3373 * current node being accessed by the xmlTextReader. This is dangerous
3374 * because the underlying node may be destroyed on the next Reads.
3375 *
3376 * Returns the xmlNodePtr or NULL in case of error.
3377 */
3378xmlNodePtr
3379xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3380 if (reader == NULL)
3381 return(NULL);
3382
3383 if (reader->curnode != NULL)
3384 return(reader->curnode);
3385 return(reader->node);
3386}
3387
3388/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003389 * xmlTextReaderPreserve:
3390 * @reader: the xmlTextReaderPtr used
3391 *
3392 *
3393 * current node being accessed by the xmlTextReader. This is dangerous
3394 * because the underlying node may be destroyed on the next Reads.
3395 *
3396 * Returns the xmlNodePtr or NULL in case of error.
3397 */
3398xmlNodePtr
3399xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3400 xmlNodePtr cur, parent;
3401
3402 if (reader == NULL)
3403 return(NULL);
3404
3405 if (reader->curnode != NULL)
3406 cur = reader->curnode;
3407 else
3408 cur = reader->node;
3409 if (cur == NULL)
3410 return(NULL);
Daniel Veillarde8039df2003-10-27 11:25:13 +00003411 cur->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003412
3413 parent = cur->parent;;
3414 while (parent != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00003415 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003416 parent = parent->parent;
3417 }
3418 return(cur);
3419}
3420
3421/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003422 * xmlTextReaderCurrentDoc:
3423 * @reader: the xmlTextReaderPtr used
3424 *
3425 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003426 * current document being accessed by the xmlTextReader.
3427 * NOTE: as a result of this call, the reader will not destroy the
3428 * associated XML document and calling xmlFreeDoc() on the result
3429 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003430 *
3431 * Returns the xmlDocPtr or NULL in case of error.
3432 */
3433xmlDocPtr
3434xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003435 if (reader == NULL)
3436 return(NULL);
3437 if (reader->doc != NULL)
3438 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003439 if ((reader == NULL) || (reader->ctxt == NULL) ||
3440 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003441 return(NULL);
3442
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003443 reader->preserve = 1;
3444 if ((reader->ctxt->myDoc->dict != NULL) &&
3445 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3446 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003447 return(reader->ctxt->myDoc);
3448}
3449
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003450#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003451/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003452 * xmlTextReaderRelaxNGSetSchema:
3453 * @reader: the xmlTextReaderPtr used
3454 * @schema: a precompiled RelaxNG schema
3455 *
3456 * Use RelaxNG to validate the document as it is processed.
3457 * Activation is only possible before the first Read().
3458 * if @schema is NULL, then RelaxNG validation is desactivated.
3459 @ The @schema should not be freed until the reader is deallocated
3460 * or its use has been deactivated.
3461 *
3462 * Returns 0 in case the RelaxNG validation could be (des)activated and
3463 * -1 in case of error.
3464 */
3465int
3466xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3467 if (schema == NULL) {
3468 if (reader->rngSchemas != NULL) {
3469 xmlRelaxNGFree(reader->rngSchemas);
3470 reader->rngSchemas = NULL;
3471 }
3472 if (reader->rngValidCtxt != NULL) {
3473 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3474 reader->rngValidCtxt = NULL;
3475 }
3476 return(0);
3477 }
3478 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3479 return(-1);
3480 if (reader->rngSchemas != NULL) {
3481 xmlRelaxNGFree(reader->rngSchemas);
3482 reader->rngSchemas = NULL;
3483 }
3484 if (reader->rngValidCtxt != NULL) {
3485 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3486 reader->rngValidCtxt = NULL;
3487 }
3488 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3489 if (reader->rngValidCtxt == NULL)
3490 return(-1);
3491 if (reader->errorFunc != NULL) {
3492 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3493 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3494 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3495 reader->errorFuncArg);
3496 }
3497 reader->rngValidErrors = 0;
3498 reader->rngFullNode = NULL;
3499 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3500 return(0);
3501}
3502
3503/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003504 * xmlTextReaderRelaxNGValidate:
3505 * @reader: the xmlTextReaderPtr used
3506 * @rng: the path to a RelaxNG schema or NULL
3507 *
3508 * Use RelaxNG to validate the document as it is processed.
3509 * Activation is only possible before the first Read().
3510 * if @rng is NULL, then RelaxNG validation is desactivated.
3511 *
3512 * Returns 0 in case the RelaxNG validation could be (des)activated and
3513 * -1 in case of error.
3514 */
3515int
3516xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3517 xmlRelaxNGParserCtxtPtr ctxt;
3518
3519 if (reader == NULL)
3520 return(-1);
3521
3522 if (rng == NULL) {
3523 if (reader->rngSchemas != NULL) {
3524 xmlRelaxNGFree(reader->rngSchemas);
3525 reader->rngSchemas = NULL;
3526 }
3527 if (reader->rngValidCtxt != NULL) {
3528 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3529 reader->rngValidCtxt = NULL;
3530 }
3531 return(0);
3532 }
3533 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3534 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003535 if (reader->rngSchemas != NULL) {
3536 xmlRelaxNGFree(reader->rngSchemas);
3537 reader->rngSchemas = NULL;
3538 }
3539 if (reader->rngValidCtxt != NULL) {
3540 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3541 reader->rngValidCtxt = NULL;
3542 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003543 ctxt = xmlRelaxNGNewParserCtxt(rng);
3544 if (reader->errorFunc != NULL) {
3545 xmlRelaxNGSetParserErrors(ctxt,
3546 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3547 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3548 reader->errorFuncArg);
3549 }
3550 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3551 xmlRelaxNGFreeParserCtxt(ctxt);
3552 if (reader->rngSchemas == NULL)
3553 return(-1);
3554 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3555 if (reader->rngValidCtxt == NULL)
3556 return(-1);
3557 if (reader->errorFunc != NULL) {
3558 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3559 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3560 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3561 reader->errorFuncArg);
3562 }
3563 reader->rngValidErrors = 0;
3564 reader->rngFullNode = NULL;
3565 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3566 return(0);
3567}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003568#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003569
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003570/************************************************************************
3571 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003572 * Error Handling Extensions *
3573 * *
3574 ************************************************************************/
3575
3576/* helper to build a xmlMalloc'ed string from a format and va_list */
3577static char *
3578xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3579 int size;
3580 int chars;
3581 char *larger;
3582 char *str;
3583
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003584 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003585 if (str == NULL) {
3586 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3587 return NULL;
3588 }
3589
3590 size = 150;
3591
3592 while (1) {
3593 chars = vsnprintf(str, size, msg, ap);
3594 if ((chars > -1) && (chars < size))
3595 break;
3596 if (chars > -1)
3597 size += chars + 1;
3598 else
3599 size += 100;
3600 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3601 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3602 xmlFree(str);
3603 return NULL;
3604 }
3605 str = larger;
3606 }
3607
3608 return str;
3609}
3610
Daniel Veillard417be3a2003-01-20 21:26:34 +00003611/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003612 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003613 * @locator: the xmlTextReaderLocatorPtr used
3614 *
3615 * Obtain the line number for the given locator.
3616 *
3617 * Returns the line number or -1 in case of error.
3618 */
3619int
3620xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3621 /* we know that locator is a xmlParserCtxtPtr */
3622 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3623 int ret = -1;
3624
3625 if (ctx->node != NULL) {
3626 ret = xmlGetLineNo(ctx->node);
3627 }
3628 else {
3629 /* inspired from error.c */
3630 xmlParserInputPtr input;
3631 input = ctx->input;
3632 if ((input->filename == NULL) && (ctx->inputNr > 1))
3633 input = ctx->inputTab[ctx->inputNr - 2];
3634 if (input != NULL) {
3635 ret = input->line;
3636 }
3637 else {
3638 ret = -1;
3639 }
3640 }
3641
3642 return ret;
3643}
3644
3645/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003646 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003647 * @locator: the xmlTextReaderLocatorPtr used
3648 *
3649 * Obtain the base URI for the given locator.
3650 *
3651 * Returns the base URI or NULL in case of error.
3652 */
3653xmlChar *
3654xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3655 /* we know that locator is a xmlParserCtxtPtr */
3656 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3657 xmlChar *ret = NULL;
3658
3659 if (ctx->node != NULL) {
3660 ret = xmlNodeGetBase(NULL,ctx->node);
3661 }
3662 else {
3663 /* inspired from error.c */
3664 xmlParserInputPtr input;
3665 input = ctx->input;
3666 if ((input->filename == NULL) && (ctx->inputNr > 1))
3667 input = ctx->inputTab[ctx->inputNr - 2];
3668 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003669 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003670 }
3671 else {
3672 ret = NULL;
3673 }
3674 }
3675
3676 return ret;
3677}
3678
Daniel Veillard26f70262003-01-16 22:45:08 +00003679static void
William M. Brack899e64a2003-09-26 18:03:42 +00003680xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003681 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3682 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3683
3684 if (str != NULL) {
3685 reader->errorFunc(reader->errorFuncArg,
3686 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003687 severity,
3688 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003689 xmlFree(str);
3690 }
3691}
3692
3693static void
3694xmlTextReaderError(void *ctxt, const char *msg, ...) {
3695 va_list ap;
3696
3697 va_start(ap,msg);
3698 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003699 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003700 xmlTextReaderBuildMessage(msg,ap));
3701 va_end(ap);
3702
3703}
3704
3705static void
3706xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3707 va_list ap;
3708
3709 va_start(ap,msg);
3710 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003711 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003712 xmlTextReaderBuildMessage(msg,ap));
3713 va_end(ap);
3714}
3715
3716static void
3717xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3718 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003719 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003720
Daniel Veillard417be3a2003-01-20 21:26:34 +00003721 if ((len > 1) && (msg[len - 2] != ':')) {
3722 /*
3723 * some callbacks only report locator information:
3724 * skip them (mimicking behaviour in error.c)
3725 */
3726 va_start(ap,msg);
3727 xmlTextReaderGenericError(ctxt,
3728 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3729 xmlTextReaderBuildMessage(msg,ap));
3730 va_end(ap);
3731 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003732}
3733
3734static void
3735xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3736 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003737 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003738
Daniel Veillard417be3a2003-01-20 21:26:34 +00003739 if ((len != 0) && (msg[len - 1] != ':')) {
3740 /*
3741 * some callbacks only report locator information:
3742 * skip them (mimicking behaviour in error.c)
3743 */
3744 va_start(ap,msg);
3745 xmlTextReaderGenericError(ctxt,
3746 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3747 xmlTextReaderBuildMessage(msg,ap));
3748 va_end(ap);
3749 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003750}
3751
3752/**
3753 * xmlTextReaderSetErrorHandler:
3754 * @reader: the xmlTextReaderPtr used
3755 * @f: the callback function to call on error and warnings
3756 * @arg: a user argument to pass to the callback function
3757 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003758 * Register a callback function that will be called on error and warnings.
3759 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003760 * If @f is NULL, the default error and warning handlers are restored.
3761 */
3762void
3763xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3764 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003765 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003766 if (f != NULL) {
3767 reader->ctxt->sax->error = xmlTextReaderError;
3768 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3769 reader->ctxt->sax->warning = xmlTextReaderWarning;
3770 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3771 reader->errorFunc = f;
3772 reader->errorFuncArg = arg;
3773 }
3774 else {
3775 /* restore defaults */
3776 reader->ctxt->sax->error = xmlParserError;
3777 reader->ctxt->vctxt.error = xmlParserValidityError;
3778 reader->ctxt->sax->warning = xmlParserWarning;
3779 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3780 reader->errorFunc = NULL;
3781 reader->errorFuncArg = NULL;
3782 }
3783}
3784
Daniel Veillard417be3a2003-01-20 21:26:34 +00003785/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003786 * xmlTextReaderIsValid:
3787 * @reader: the xmlTextReaderPtr used
3788 *
3789 * Retrieve the validity status from the parser context
3790 *
3791 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3792 */
3793int
3794xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003795 if (reader == NULL) return(-1);
3796#ifdef LIBXML_SCHEMAS_ENABLED
3797 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3798 return(reader->rngValidErrors == 0);
3799#endif
3800 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3801 (reader->ctxt != NULL))
3802 return(reader->ctxt->valid);
3803 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003804}
3805
3806/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003807 * xmlTextReaderGetErrorHandler:
3808 * @reader: the xmlTextReaderPtr used
3809 * @f: the callback function or NULL is no callback has been registered
3810 * @arg: a user argument
3811 *
3812 * Retrieve the error callback function and user argument.
3813 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003814void
3815xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3816 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003817 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003818 *f = reader->errorFunc;
3819 *arg = reader->errorFuncArg;
3820}
3821
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003822
3823/************************************************************************
3824 * *
3825 * New set (2.6.0) of simpler and more flexible APIs *
3826 * *
3827 ************************************************************************/
3828
3829/**
3830 * xmlTextReaderSetup:
3831 * @reader: an XML reader
3832 * @URL: the base URL to use for the document
3833 * @encoding: the document encoding, or NULL
3834 * @options: a combination of xmlParserOption(s)
3835 * @reuse: keep the context for reuse
3836 *
3837 * Setup an XML reader with new options
3838 *
3839 * Returns 0 in case of success and -1 in case of error.
3840 */
3841static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003842xmlTextReaderSetup(xmlTextReaderPtr reader,
3843 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003844 const char *encoding, int options)
3845{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003846 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003847 return (-1);
3848
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003849 reader->doc = NULL;
3850 reader->entNr = 0;
3851 if ((input != NULL) && (reader->input != NULL) &&
3852 (reader->allocs & XML_TEXTREADER_INPUT)) {
3853 xmlFreeParserInputBuffer(reader->input);
3854 reader->input = NULL;
3855 reader->allocs -= XML_TEXTREADER_INPUT;
3856 }
3857 if (input != NULL) {
3858 reader->input = input;
3859 reader->allocs |= XML_TEXTREADER_INPUT;
3860 }
3861 if (reader->buffer == NULL)
3862 reader->buffer = xmlBufferCreateSize(100);
3863 if (reader->buffer == NULL) {
3864 xmlGenericError(xmlGenericErrorContext,
3865 "xmlTextReaderSetup : malloc failed\n");
3866 return (-1);
3867 }
3868 if (reader->sax == NULL)
3869 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
3870 if (reader->sax == NULL) {
3871 xmlGenericError(xmlGenericErrorContext,
3872 "xmlTextReaderSetup : malloc failed\n");
3873 return (-1);
3874 }
3875 xmlSAXVersion(reader->sax, 2);
3876 reader->startElement = reader->sax->startElement;
3877 reader->sax->startElement = xmlTextReaderStartElement;
3878 reader->endElement = reader->sax->endElement;
3879 reader->sax->endElement = xmlTextReaderEndElement;
3880#ifdef LIBXML_SAX1_ENABLED
3881 if (reader->sax->initialized == XML_SAX2_MAGIC) {
3882#endif /* LIBXML_SAX1_ENABLED */
3883 reader->startElementNs = reader->sax->startElementNs;
3884 reader->sax->startElementNs = xmlTextReaderStartElementNs;
3885 reader->endElementNs = reader->sax->endElementNs;
3886 reader->sax->endElementNs = xmlTextReaderEndElementNs;
3887#ifdef LIBXML_SAX1_ENABLED
3888 } else {
3889 reader->startElementNs = NULL;
3890 reader->endElementNs = NULL;
3891 }
3892#endif /* LIBXML_SAX1_ENABLED */
3893 reader->characters = reader->sax->characters;
3894 reader->sax->characters = xmlTextReaderCharacters;
3895 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
3896 reader->cdataBlock = reader->sax->cdataBlock;
3897 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
3898
3899 reader->mode = XML_TEXTREADER_MODE_INITIAL;
3900 reader->node = NULL;
3901 reader->curnode = NULL;
3902 if (input != NULL) {
3903 if (reader->input->buffer->use < 4) {
3904 xmlParserInputBufferRead(input, 4);
3905 }
3906 if (reader->ctxt == NULL) {
3907 if (reader->input->buffer->use >= 4) {
3908 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
3909 (const char *) reader->input->buffer->content, 4, URL);
3910 reader->base = 0;
3911 reader->cur = 4;
3912 } else {
3913 reader->ctxt =
3914 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
3915 reader->base = 0;
3916 reader->cur = 0;
3917 }
3918 } else {
3919 xmlParserInputPtr inputStream;
3920 xmlParserInputBufferPtr buf;
3921 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
3922
3923 if (reader->ctxt->myDoc != NULL)
3924 xmlDictReference(reader->ctxt->myDoc->dict);
3925 xmlCtxtReset(reader->ctxt);
3926 buf = xmlAllocParserInputBuffer(enc);
3927 if (buf == NULL) return(-1);
3928 inputStream = xmlNewInputStream(reader->ctxt);
3929 if (inputStream == NULL) {
3930 xmlFreeParserInputBuffer(buf);
3931 return(-1);
3932 }
3933
3934 if (URL == NULL)
3935 inputStream->filename = NULL;
3936 else
3937 inputStream->filename = (char *)
3938 xmlCanonicPath((const xmlChar *) URL);
3939 inputStream->buf = buf;
3940 inputStream->base = inputStream->buf->buffer->content;
3941 inputStream->cur = inputStream->buf->buffer->content;
3942 inputStream->end =
3943 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
3944
3945 inputPush(reader->ctxt, inputStream);
3946 reader->cur = 0;
3947 }
3948 if (reader->ctxt == NULL) {
3949 xmlGenericError(xmlGenericErrorContext,
3950 "xmlTextReaderSetup : malloc failed\n");
3951 return (-1);
3952 }
3953 }
3954 if (reader->dict != NULL) {
3955 if (reader->ctxt->dict != NULL) {
3956 if (reader->dict != reader->ctxt->dict) {
3957 xmlDictFree(reader->dict);
3958 reader->dict = reader->ctxt->dict;
3959 }
3960 } else {
3961 reader->ctxt->dict = reader->dict;
3962 }
3963 } else {
3964 if (reader->ctxt->dict == NULL)
3965 reader->ctxt->dict = xmlDictCreate();
3966 reader->dict = reader->ctxt->dict;
3967 }
3968 reader->ctxt->_private = reader;
3969 reader->ctxt->linenumbers = 1;
3970 reader->ctxt->dictNames = 1;
3971 /*
3972 * use the parser dictionnary to allocate all elements and attributes names
3973 */
3974 reader->ctxt->docdict = 1;
3975
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003976#ifdef LIBXML_XINCLUDE_ENABLED
3977 if (reader->xincctxt != NULL) {
3978 xmlXIncludeFreeContext(reader->xincctxt);
3979 reader->xincctxt = NULL;
3980 }
3981 if (options & XML_PARSE_XINCLUDE) {
3982 reader->xinclude = 1;
3983 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
3984 options -= XML_PARSE_XINCLUDE;
3985 } else
3986 reader->xinclude = 0;
3987 reader->in_xinclude = 0;
3988#endif
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003989 xmlCtxtUseOptions(reader->ctxt, options);
3990 if (encoding != NULL) {
3991 xmlCharEncodingHandlerPtr hdlr;
3992
3993 hdlr = xmlFindCharEncodingHandler(encoding);
3994 if (hdlr != NULL)
3995 xmlSwitchToEncoding(reader->ctxt, hdlr);
3996 }
3997 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
3998 (reader->ctxt->input->filename == NULL))
3999 reader->ctxt->input->filename = (char *)
4000 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004001
4002 reader->doc = NULL;
4003
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004004 return (0);
4005}
4006
4007/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004008 * xmlReaderWalker:
4009 * @doc: a preparsed document
4010 *
4011 * Create an xmltextReader for a preparsed document.
4012 *
4013 * Returns the new reader or NULL in case of error.
4014 */
4015xmlTextReaderPtr
4016xmlReaderWalker(xmlDocPtr doc)
4017{
4018 xmlTextReaderPtr ret;
4019
4020 if (doc == NULL)
4021 return(NULL);
4022
4023 ret = xmlMalloc(sizeof(xmlTextReader));
4024 if (ret == NULL) {
4025 xmlGenericError(xmlGenericErrorContext,
4026 "xmlNewTextReader : malloc failed\n");
4027 return(NULL);
4028 }
4029 memset(ret, 0, sizeof(xmlTextReader));
4030 ret->entNr = 0;
4031 ret->input = NULL;
4032 ret->mode = XML_TEXTREADER_MODE_INITIAL;
4033 ret->node = NULL;
4034 ret->curnode = NULL;
4035 ret->base = 0;
4036 ret->cur = 0;
4037 ret->allocs = XML_TEXTREADER_CTXT;
4038 ret->doc = doc;
4039 ret->state = XML_TEXTREADER_START;
4040 ret->dict = xmlDictCreate();
4041 return(ret);
4042}
4043
4044/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004045 * xmlReaderForDoc:
4046 * @cur: a pointer to a zero terminated string
4047 * @URL: the base URL to use for the document
4048 * @encoding: the document encoding, or NULL
4049 * @options: a combination of xmlParserOption(s)
4050 *
4051 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004052 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004053 *
4054 * Returns the new reader or NULL in case of error.
4055 */
4056xmlTextReaderPtr
4057xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
4058 int options)
4059{
4060 int len;
4061
4062 if (cur == NULL)
4063 return (NULL);
4064 len = xmlStrlen(cur);
4065
4066 return (xmlReaderForMemory
4067 ((const char *) cur, len, URL, encoding, options));
4068}
4069
4070/**
4071 * xmlReaderForFile:
4072 * @filename: a file or URL
4073 * @encoding: the document encoding, or NULL
4074 * @options: a combination of xmlParserOption(s)
4075 *
4076 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004077 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004078 *
4079 * Returns the new reader or NULL in case of error.
4080 */
4081xmlTextReaderPtr
4082xmlReaderForFile(const char *filename, const char *encoding, int options)
4083{
4084 xmlTextReaderPtr reader;
4085
4086 reader = xmlNewTextReaderFilename(filename);
4087 if (reader == NULL)
4088 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004089 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004090 return (reader);
4091}
4092
4093/**
4094 * xmlReaderForMemory:
4095 * @buffer: a pointer to a char array
4096 * @size: the size of the array
4097 * @URL: the base URL to use for the document
4098 * @encoding: the document encoding, or NULL
4099 * @options: a combination of xmlParserOption(s)
4100 *
4101 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004102 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004103 *
4104 * Returns the new reader or NULL in case of error.
4105 */
4106xmlTextReaderPtr
4107xmlReaderForMemory(const char *buffer, int size, const char *URL,
4108 const char *encoding, int options)
4109{
4110 xmlTextReaderPtr reader;
4111 xmlParserInputBufferPtr buf;
4112
4113 buf =
4114 xmlParserInputBufferCreateMem(buffer, size,
4115 XML_CHAR_ENCODING_NONE);
4116 if (buf == NULL) {
4117 return (NULL);
4118 }
4119 reader = xmlNewTextReader(buf, URL);
4120 if (reader == NULL) {
4121 xmlFreeParserInputBuffer(buf);
4122 return (NULL);
4123 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004124 reader->allocs |= XML_TEXTREADER_INPUT;
4125 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004126 return (reader);
4127}
4128
4129/**
4130 * xmlReaderForFd:
4131 * @fd: an open file descriptor
4132 * @URL: the base URL to use for the document
4133 * @encoding: the document encoding, or NULL
4134 * @options: a combination of xmlParserOption(s)
4135 *
4136 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004137 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004138 *
4139 * Returns the new reader or NULL in case of error.
4140 */
4141xmlTextReaderPtr
4142xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4143{
4144 xmlTextReaderPtr reader;
4145 xmlParserInputBufferPtr input;
4146
4147 if (fd < 0)
4148 return (NULL);
4149
4150 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4151 if (input == NULL)
4152 return (NULL);
4153 reader = xmlNewTextReader(input, URL);
4154 if (reader == NULL) {
4155 xmlFreeParserInputBuffer(input);
4156 return (NULL);
4157 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004158 reader->allocs |= XML_TEXTREADER_INPUT;
4159 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004160 return (reader);
4161}
4162
4163/**
4164 * xmlReaderForIO:
4165 * @ioread: an I/O read function
4166 * @ioclose: an I/O close function
4167 * @ioctx: an I/O handler
4168 * @URL: the base URL to use for the document
4169 * @encoding: the document encoding, or NULL
4170 * @options: a combination of xmlParserOption(s)
4171 *
4172 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004173 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004174 *
4175 * Returns the new reader or NULL in case of error.
4176 */
4177xmlTextReaderPtr
4178xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4179 void *ioctx, const char *URL, const char *encoding,
4180 int options)
4181{
4182 xmlTextReaderPtr reader;
4183 xmlParserInputBufferPtr input;
4184
4185 if (ioread == NULL)
4186 return (NULL);
4187
4188 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4189 XML_CHAR_ENCODING_NONE);
4190 if (input == NULL)
4191 return (NULL);
4192 reader = xmlNewTextReader(input, URL);
4193 if (reader == NULL) {
4194 xmlFreeParserInputBuffer(input);
4195 return (NULL);
4196 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004197 reader->allocs |= XML_TEXTREADER_INPUT;
4198 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004199 return (reader);
4200}
4201
4202/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004203 * xmlReaderNewWalker:
4204 * @reader: an XML reader
4205 * @doc: a preparsed document
4206 *
4207 * Setup an xmltextReader to parse a preparsed XML document.
4208 * This reuses the existing @reader xmlTextReader.
4209 *
4210 * Returns 0 in case of success and -1 in case of error
4211 */
4212int
4213xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4214{
4215 if (doc == NULL)
4216 return (-1);
4217 if (reader == NULL)
4218 return (-1);
4219
4220 if (reader->ctxt != NULL) {
4221 xmlCtxtReset(reader->ctxt);
4222 }
4223
4224 reader->entNr = 0;
4225 reader->input = NULL;
4226 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4227 reader->node = NULL;
4228 reader->curnode = NULL;
4229 reader->base = 0;
4230 reader->cur = 0;
4231 reader->allocs = XML_TEXTREADER_CTXT;
4232 reader->doc = doc;
4233 reader->state = XML_TEXTREADER_START;
4234 if (reader->dict == NULL) {
4235 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4236 reader->dict = reader->ctxt->dict;
4237 else
4238 reader->dict = xmlDictCreate();
4239 }
4240 return(0);
4241}
4242
4243/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004244 * xmlReaderNewDoc:
4245 * @reader: an XML reader
4246 * @cur: a pointer to a zero terminated string
4247 * @URL: the base URL to use for the document
4248 * @encoding: the document encoding, or NULL
4249 * @options: a combination of xmlParserOption(s)
4250 *
4251 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004252 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004253 * This reuses the existing @reader xmlTextReader.
4254 *
4255 * Returns 0 in case of success and -1 in case of error
4256 */
4257int
4258xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4259 const char *URL, const char *encoding, int options)
4260{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004261
4262 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004263
4264 if (cur == NULL)
4265 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004266 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004267 return (-1);
4268
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004269 len = xmlStrlen(cur);
4270 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4271 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004272}
4273
4274/**
4275 * xmlReaderNewFile:
4276 * @reader: an XML reader
4277 * @filename: a file or URL
4278 * @encoding: the document encoding, or NULL
4279 * @options: a combination of xmlParserOption(s)
4280 *
4281 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004282 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004283 * This reuses the existing @reader xmlTextReader.
4284 *
4285 * Returns 0 in case of success and -1 in case of error
4286 */
4287int
4288xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4289 const char *encoding, int options)
4290{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004291 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004292
4293 if (filename == NULL)
4294 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004295 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004296 return (-1);
4297
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004298 input =
4299 xmlParserInputBufferCreateFilename(filename,
4300 XML_CHAR_ENCODING_NONE);
4301 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004302 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004303 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004304}
4305
4306/**
4307 * xmlReaderNewMemory:
4308 * @reader: an XML reader
4309 * @buffer: a pointer to a char array
4310 * @size: the size of the array
4311 * @URL: the base URL to use for the document
4312 * @encoding: the document encoding, or NULL
4313 * @options: a combination of xmlParserOption(s)
4314 *
4315 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004316 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004317 * This reuses the existing @reader xmlTextReader.
4318 *
4319 * Returns 0 in case of success and -1 in case of error
4320 */
4321int
4322xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4323 const char *URL, const char *encoding, int options)
4324{
4325 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004326
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004327 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004328 return (-1);
4329 if (buffer == NULL)
4330 return (-1);
4331
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004332 input = xmlParserInputBufferCreateMem(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004333 XML_CHAR_ENCODING_NONE);
4334 if (input == NULL) {
4335 return (-1);
4336 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004337 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004338}
4339
4340/**
4341 * xmlReaderNewFd:
4342 * @reader: an XML reader
4343 * @fd: an open file descriptor
4344 * @URL: the base URL to use for the document
4345 * @encoding: the document encoding, or NULL
4346 * @options: a combination of xmlParserOption(s)
4347 *
4348 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004349 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004350 * This reuses the existing @reader xmlTextReader.
4351 *
4352 * Returns 0 in case of success and -1 in case of error
4353 */
4354int
4355xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4356 const char *URL, const char *encoding, int options)
4357{
4358 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004359
4360 if (fd < 0)
4361 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004362 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004363 return (-1);
4364
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004365 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4366 if (input == NULL)
4367 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004368 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004369}
4370
4371/**
4372 * xmlReaderNewIO:
4373 * @reader: an XML reader
4374 * @ioread: an I/O read function
4375 * @ioclose: an I/O close function
4376 * @ioctx: an I/O handler
4377 * @URL: the base URL to use for the document
4378 * @encoding: the document encoding, or NULL
4379 * @options: a combination of xmlParserOption(s)
4380 *
4381 * Setup an xmltextReader to parse an XML document from I/O functions
4382 * and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004383 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004384 * This reuses the existing @reader xmlTextReader.
4385 *
4386 * Returns 0 in case of success and -1 in case of error
4387 */
4388int
4389xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4390 xmlInputCloseCallback ioclose, void *ioctx,
4391 const char *URL, const char *encoding, int options)
4392{
4393 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004394
4395 if (ioread == NULL)
4396 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004397 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004398 return (-1);
4399
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004400 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4401 XML_CHAR_ENCODING_NONE);
4402 if (input == NULL)
4403 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004404 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004405}
Daniel Veillard26f70262003-01-16 22:45:08 +00004406/************************************************************************
4407 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004408 * Utilities *
4409 * *
4410 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004411#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004412/**
4413 * xmlBase64Decode:
4414 * @in: the input buffer
4415 * @inlen: the size of the input (in), the size read from it (out)
4416 * @to: the output buffer
4417 * @tolen: the size of the output (in), the size written to (out)
4418 *
4419 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004420 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004421 *
4422 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4423 * 2 if there wasn't enough space on the output or -1 in case of error.
4424 */
4425static int
4426xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4427 unsigned char *to, unsigned long *tolen) {
4428 unsigned long incur; /* current index in in[] */
4429 unsigned long inblk; /* last block index in in[] */
4430 unsigned long outcur; /* current index in out[] */
4431 unsigned long inmax; /* size of in[] */
4432 unsigned long outmax; /* size of out[] */
4433 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004434 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004435 int nbintmp; /* number of byte in intmp[] */
4436 int is_ignore; /* cur should be ignored */
4437 int is_end = 0; /* the end of the base64 was found */
4438 int retval = 1;
4439 int i;
4440
4441 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4442 return(-1);
4443
4444 incur = 0;
4445 inblk = 0;
4446 outcur = 0;
4447 inmax = *inlen;
4448 outmax = *tolen;
4449 nbintmp = 0;
4450
4451 while (1) {
4452 if (incur >= inmax)
4453 break;
4454 cur = in[incur++];
4455 is_ignore = 0;
4456 if ((cur >= 'A') && (cur <= 'Z'))
4457 cur = cur - 'A';
4458 else if ((cur >= 'a') && (cur <= 'z'))
4459 cur = cur - 'a' + 26;
4460 else if ((cur >= '0') && (cur <= '9'))
4461 cur = cur - '0' + 52;
4462 else if (cur == '+')
4463 cur = 62;
4464 else if (cur == '/')
4465 cur = 63;
4466 else if (cur == '.')
4467 cur = 0;
4468 else if (cur == '=') /*no op , end of the base64 stream */
4469 is_end = 1;
4470 else {
4471 is_ignore = 1;
4472 if (nbintmp == 0)
4473 inblk = incur;
4474 }
4475
4476 if (!is_ignore) {
4477 int nbouttmp = 3;
4478 int is_break = 0;
4479
4480 if (is_end) {
4481 if (nbintmp == 0)
4482 break;
4483 if ((nbintmp == 1) || (nbintmp == 2))
4484 nbouttmp = 1;
4485 else
4486 nbouttmp = 2;
4487 nbintmp = 3;
4488 is_break = 1;
4489 }
4490 intmp[nbintmp++] = cur;
4491 /*
4492 * if intmp is full, push the 4byte sequence as a 3 byte
4493 * sequence out
4494 */
4495 if (nbintmp == 4) {
4496 nbintmp = 0;
4497 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4498 outtmp[1] =
4499 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4500 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4501 if (outcur + 3 >= outmax) {
4502 retval = 2;
4503 break;
4504 }
4505
4506 for (i = 0; i < nbouttmp; i++)
4507 to[outcur++] = outtmp[i];
4508 inblk = incur;
4509 }
4510
4511 if (is_break) {
4512 retval = 0;
4513 break;
4514 }
4515 }
4516 }
4517
4518 *tolen = outcur;
4519 *inlen = inblk;
4520 return (retval);
4521}
4522
4523/*
4524 * Test routine for the xmlBase64Decode function
4525 */
4526#if 0
4527int main(int argc, char **argv) {
4528 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4529 char output[100];
4530 char output2[100];
4531 char output3[100];
4532 unsigned long inlen = strlen(input);
4533 unsigned long outlen = 100;
4534 int ret;
4535 unsigned long cons, tmp, tmp2, prod;
4536
4537 /*
4538 * Direct
4539 */
4540 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4541
4542 output[outlen] = 0;
4543 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4544
4545 /*
4546 * output chunking
4547 */
4548 cons = 0;
4549 prod = 0;
4550 while (cons < inlen) {
4551 tmp = 5;
4552 tmp2 = inlen - cons;
4553
4554 printf("%ld %ld\n", cons, prod);
4555 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4556 cons += tmp2;
4557 prod += tmp;
4558 printf("%ld %ld\n", cons, prod);
4559 }
4560 output2[outlen] = 0;
4561 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4562
4563 /*
4564 * input chunking
4565 */
4566 cons = 0;
4567 prod = 0;
4568 while (cons < inlen) {
4569 tmp = 100 - prod;
4570 tmp2 = inlen - cons;
4571 if (tmp2 > 5)
4572 tmp2 = 5;
4573
4574 printf("%ld %ld\n", cons, prod);
4575 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4576 cons += tmp2;
4577 prod += tmp;
4578 printf("%ld %ld\n", cons, prod);
4579 }
4580 output3[outlen] = 0;
4581 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4582 return(0);
4583
4584}
4585#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004586#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004587#endif /* LIBXML_READER_ENABLED */