blob: 91c110223a02d95050fd948ecc2cf3df4dc5926e [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9#define IN_LIBXML
10#include "libxml.h"
11
12#include <string.h> /* for memset() only ! */
13
14#ifdef HAVE_CTYPE_H
15#include <ctype.h>
16#endif
17#ifdef HAVE_STDLIB_H
18#include <stdlib.h>
19#endif
20
21#include <libxml/xmlmemory.h>
22#include <libxml/xmlIO.h>
23#include <libxml/xmlreader.h>
24
25/* #define DEBUG_CALLBACKS */
26/* #define DEBUG_READER */
27
28/**
29 * TODO:
30 *
31 * macro to flag unimplemented blocks
32 */
33#define TODO \
34 xmlGenericError(xmlGenericErrorContext, \
35 "Unimplemented block at %s:%d\n", \
36 __FILE__, __LINE__);
37
38#ifdef DEBUG_READER
39#define DUMP_READER xmlTextReaderDebug(reader);
40#else
41#define DUMP_READER
42#endif
43
44/************************************************************************
45 * *
46 * The parser: maps the Text Reader API on top of the existing *
47 * parsing routines building a tree *
48 * *
49 ************************************************************************/
50
51#define XML_TEXTREADER_INPUT 1
52#define XML_TEXTREADER_CTXT 2
53
54typedef enum {
55 XML_TEXTREADER_MODE_NORMAL = 0,
Daniel Veillard0eb38c72002-12-14 23:00:35 +000056 XML_TEXTREADER_MODE_EOF = 1,
57 XML_TEXTREADER_MODE_CLOSED = 1
Daniel Veillarde1ca5032002-12-09 14:13:43 +000058} xmlTextReaderMode;
59
60typedef enum {
61 XML_TEXTREADER_NONE = -1,
62 XML_TEXTREADER_START= 0,
63 XML_TEXTREADER_ELEMENT= 1,
64 XML_TEXTREADER_END= 2,
65 XML_TEXTREADER_EMPTY= 3,
66 XML_TEXTREADER_BACKTRACK= 4
67} xmlTextReaderState;
68
69struct _xmlTextReader {
70 int mode; /* the parsing mode */
71 int allocs; /* what structure were deallocated */
72 xmlTextReaderState state;
73 xmlParserCtxtPtr ctxt; /* the parser context */
74 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
75 xmlParserInputBufferPtr input; /* the input */
76 startElementSAXFunc startElement;/* initial SAX callbacks */
77 endElementSAXFunc endElement; /* idem */
78 unsigned int base; /* base of the segment in the input */
79 unsigned int cur; /* current position in the input */
80 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +000081 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000082 int depth; /* depth of the current node */
83};
84
85#ifdef DEBUG_READER
86static void
87xmlTextReaderDebug(xmlTextReaderPtr reader) {
88 if ((reader == NULL) || (reader->ctxt == NULL)) {
89 fprintf(stderr, "xmlTextReader NULL\n");
90 return;
91 }
92 fprintf(stderr, "xmlTextReader: state %d depth %d ",
93 reader->state, reader->depth);
94 if (reader->node == NULL) {
95 fprintf(stderr, "node = NULL\n");
96 } else {
97 fprintf(stderr, "node %s\n", reader->node->name);
98 }
99 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
100 reader->base, reader->cur, reader->ctxt->nodeNr);
101 if (reader->input->buffer == NULL) {
102 fprintf(stderr, "buffer is NULL\n");
103 } else {
104#ifdef LIBXML_DEBUG_ENABLED
105 xmlDebugDumpString(stderr,
106 &reader->input->buffer->content[reader->cur]);
107#endif
108 fprintf(stderr, "\n");
109 }
110}
111#endif
112
113/**
114 * xmlTextReaderStartElement:
115 * @ctx: the user data (XML parser context)
116 * @fullname: The element name, including namespace prefix
117 * @atts: An array of name/value attributes pairs, NULL terminated
118 *
119 * called when an opening tag has been processed.
120 */
121static void
122xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
123 const xmlChar **atts) {
124 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
125 xmlTextReaderPtr reader = ctxt->_private;
126
127#ifdef DEBUG_CALLBACKS
128 printf("xmlTextReaderStartElement(%s)\n", fullname);
129#endif
130 if ((reader != NULL) && (reader->startElement != NULL))
131 reader->startElement(ctx, fullname, atts);
132 reader->state = XML_TEXTREADER_ELEMENT;
133}
134
135/**
136 * xmlTextReaderEndElement:
137 * @ctx: the user data (XML parser context)
138 * @fullname: The element name, including namespace prefix
139 *
140 * called when an ending tag has been processed.
141 */
142static void
143xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
144 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
145 xmlTextReaderPtr reader = ctxt->_private;
146
147#ifdef DEBUG_CALLBACKS
148 printf("xmlTextReaderEndElement(%s)\n", fullname);
149#endif
150 if ((reader != NULL) && (reader->endElement != NULL))
151 reader->endElement(ctx, fullname);
152 if (reader->state == XML_TEXTREADER_ELEMENT)
153 reader->state = XML_TEXTREADER_EMPTY;
154 else
155 reader->state = XML_TEXTREADER_END;
156}
157
158/**
159 * xmlTextReaderPushData:
160 * @reader: the xmlTextReaderPtr used
161 *
162 * Push data down the progressive parser until a significant callback
163 * got raised.
164 *
165 * Returns -1 in case of failure, 0 otherwise
166 */
167static int
168xmlTextReaderPushData(xmlTextReaderPtr reader) {
169 unsigned int cur = reader->cur;
170 xmlBufferPtr inbuf;
171 int val;
172
173 if ((reader->input == NULL) || (reader->input->buffer == NULL))
174 return(-1);
175
176 reader->state = XML_TEXTREADER_NONE;
177 inbuf = reader->input->buffer;
178 while (reader->state == XML_TEXTREADER_NONE) {
179 if (cur >= inbuf->use) {
180 /*
181 * Refill the buffer unless we are at the end of the stream
182 */
183 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
184 val = xmlParserInputBufferRead(reader->input, 4096);
185 if (val <= 0) {
186 reader->mode = XML_TEXTREADER_MODE_EOF;
187 return(val);
188 }
189 } else
190 break;
191 }
192 if ((inbuf->content[cur] == '>') || (inbuf->content[cur] == '&')) {
193 cur = cur + 1;
194 val = xmlParseChunk(reader->ctxt,
195 (const char *) &inbuf->content[reader->cur],
196 cur - reader->cur, 0);
197 if (val != 0)
198 return(-1);
199 reader->cur = cur;
200 break;
201 } else {
202 cur = cur + 1;
203
204 /*
205 * One may have to force a flush at some point when parsing really
206 * large CDATA sections
207 */
208 if ((cur - reader->cur > 4096) && (reader->base == 0) &&
209 (reader->mode == XML_TEXTREADER_MODE_NORMAL)) {
210 cur = cur + 1;
211 val = xmlParseChunk(reader->ctxt,
212 (const char *) &inbuf->content[reader->cur],
213 cur - reader->cur, 0);
214 if (val != 0)
215 return(-1);
216 reader->cur = cur;
217 }
218 }
219 }
220 /*
221 * Discard the consumed input when needed and possible
222 */
223 if (reader->mode == XML_TEXTREADER_MODE_NORMAL) {
224 if ((reader->cur >= 4096) && (reader->base == 0)) {
225 val = xmlBufferShrink(inbuf, cur);
226 if (val >= 0) {
227 reader->cur -= val;
228 }
229 }
230 }
231
232 /*
233 * At the end of the stream signal that the work is done to the Push
234 * parser.
235 */
236 if ((reader->mode == XML_TEXTREADER_MODE_EOF) && (cur >= inbuf->use)) {
237 val = xmlParseChunk(reader->ctxt,
238 (const char *) &inbuf->content[reader->cur], 0, 1);
239 }
240 return(0);
241}
242
243/**
244 * xmlTextReaderRead:
245 * @reader: the xmlTextReaderPtr used
246 *
247 * Moves the position of the current instance to the next node in
248 * the stream, exposing its properties.
249 *
250 * Returns 1 if the node was read successfully, 0 if there is no more
251 * nodes to read, or -1 in case of error
252 */
253int
254xmlTextReaderRead(xmlTextReaderPtr reader) {
255 int val, olddepth;
256 xmlTextReaderState oldstate;
257 xmlNodePtr oldnode;
258
259 if ((reader == NULL) || (reader->ctxt == NULL))
260 return(-1);
261 if (reader->ctxt->wellFormed != 1)
262 return(-1);
263
264#ifdef DEBUG_READER
265 fprintf(stderr, "\nREAD ");
266 DUMP_READER
267#endif
268 if (reader->node == NULL) {
269 /*
270 * Initial state
271 */
272 do {
273 val = xmlTextReaderPushData(reader);
274 if (val < 0)
275 return(-1);
276 } while ((reader->ctxt->node == NULL) &&
277 (reader->mode != XML_TEXTREADER_MODE_EOF));
278 if (reader->ctxt->node == NULL) {
279 if (reader->ctxt->myDoc != NULL)
280 reader->node = reader->ctxt->myDoc->children;
281 if (reader->node == NULL)
282 return(-1);
283 } else {
284 reader->node = reader->ctxt->node;
285 }
286 reader->depth = 1;
287 return(1);
288 }
289 oldstate = reader->state;
290 olddepth = reader->ctxt->nodeNr;
291 oldnode = reader->node;
292 /*
293 * If we are not backtracking on ancestors or examined nodes,
294 * that the parser didn't finished or that we arent at the end
295 * of stream, continue processing.
296 */
297 if (oldstate != XML_TEXTREADER_BACKTRACK) {
298 while (((reader->node->children == NULL) ||
299 (reader->node->type == XML_ENTITY_REF_NODE) ||
300 (reader->node->type == XML_DTD_NODE)) &&
301 (reader->node->next == NULL) &&
302 (reader->ctxt->nodeNr == olddepth) &&
303 (reader->ctxt->instate != XML_PARSER_EOF)) {
304 val = xmlTextReaderPushData(reader);
305 if (val < 0)
306 return(-1);
307 if (reader->node == NULL)
308 return(0);
309 }
310 if ((reader->node->children != NULL) &&
311 (reader->node->type != XML_ENTITY_REF_NODE) &&
312 (reader->node->type != XML_DTD_NODE)) {
313 reader->node = reader->node->children;
314 reader->depth++;
315 if ((reader->state != XML_TEXTREADER_ELEMENT) &&
316 (reader->state != XML_TEXTREADER_EMPTY))
317 reader->state = XML_TEXTREADER_ELEMENT;
318 DUMP_READER
319 return(1);
320 }
321 }
322 if (reader->node->next != NULL) {
323 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
324 (reader->node->type == XML_ELEMENT_NODE)) {
325 reader->state = XML_TEXTREADER_END;
326 DUMP_READER
327 return(1);
328 }
329 reader->node = reader->node->next;
330 reader->state = XML_TEXTREADER_ELEMENT;
331 DUMP_READER
332 /*
333 * Cleanup of the old node
334 */
335 if (oldnode->type != XML_DTD_NODE) {
336 xmlUnlinkNode(oldnode);
337 xmlFreeNode(oldnode);
338 }
339
340 return(1);
341 }
342 reader->node = reader->node->parent;
343 if ((reader->node == NULL) ||
344 (reader->node->type == XML_DOCUMENT_NODE) ||
345#ifdef LIBXML_DOCB_ENABLED
346 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
347#endif
348 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
349 reader->node = NULL;
350 reader->depth = 0;
351
352 /*
353 * Cleanup of the old node
354 */
355 if (oldnode->type != XML_DTD_NODE) {
356 xmlUnlinkNode(oldnode);
357 xmlFreeNode(oldnode);
358 }
359
360 return(0);
361 }
362 reader->depth--;
363 reader->state = XML_TEXTREADER_BACKTRACK;
364 DUMP_READER
365 return(1);
366}
367
368/************************************************************************
369 * *
370 * Constructor and destructors *
371 * *
372 ************************************************************************/
373/**
374 * xmlNewTextReader:
375 * @input: the xmlParserInputBufferPtr used to read data
376 *
377 * Create an xmlTextReader structure fed with @input
378 *
379 * Returns the new xmlTextReaderPtr or NULL in case of error
380 */
381xmlTextReaderPtr
382xmlNewTextReader(xmlParserInputBufferPtr input) {
383 xmlTextReaderPtr ret;
384 int val;
385
386 if (input == NULL)
387 return(NULL);
388 ret = xmlMalloc(sizeof(xmlTextReader));
389 if (ret == NULL) {
390 xmlGenericError(xmlGenericErrorContext,
391 "xmlNewTextReader : malloc failed\n");
392 return(NULL);
393 }
394 memset(ret, 0, sizeof(xmlTextReader));
395 ret->input = input;
396 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
397 if (ret->sax == NULL) {
398 xmlFree(ret);
399 xmlGenericError(xmlGenericErrorContext,
400 "xmlNewTextReader : malloc failed\n");
401 return(NULL);
402 }
403 memcpy(ret->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
404 ret->startElement = ret->sax->startElement;
405 ret->sax->startElement = xmlTextReaderStartElement;
406 ret->endElement = ret->sax->endElement;
407 ret->sax->endElement = xmlTextReaderEndElement;
408
409 ret->mode = XML_TEXTREADER_MODE_NORMAL;
410 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000411 ret->curnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000412 val = xmlParserInputBufferRead(input, 4);
413 if (val >= 4) {
414 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
415 (const char *) ret->input->buffer->content, 4, NULL);
416 ret->base = 0;
417 ret->cur = 4;
418 } else {
419 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, NULL);
420 ret->base = 0;
421 ret->cur = 0;
422 }
423 ret->ctxt->_private = ret;
424 ret->allocs = XML_TEXTREADER_CTXT;
425 return(ret);
426
427}
428
429/**
430 * xmlNewTextReaderFilename:
431 * @URI: the URI of the resource to process
432 *
433 * Create an xmlTextReader structure fed with the resource at @URI
434 *
435 * Returns the new xmlTextReaderPtr or NULL in case of error
436 */
437xmlTextReaderPtr
438xmlNewTextReaderFilename(const char *URI) {
439 xmlParserInputBufferPtr input;
440 xmlTextReaderPtr ret;
441
442 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
443 if (input == NULL)
444 return(NULL);
445 ret = xmlNewTextReader(input);
446 if (ret == NULL) {
447 xmlFreeParserInputBuffer(input);
448 return(NULL);
449 }
450 ret->allocs |= XML_TEXTREADER_INPUT;
451 return(ret);
452}
453
454/**
455 * xmlFreeTextReader:
456 * @reader: the xmlTextReaderPtr
457 *
458 * Deallocate all the resources associated to the reader
459 */
460void
461xmlFreeTextReader(xmlTextReaderPtr reader) {
462 if (reader == NULL)
463 return;
464 if (reader->ctxt != NULL) {
465 if (reader->ctxt->myDoc != NULL) {
466 xmlFreeDoc(reader->ctxt->myDoc);
467 reader->ctxt->myDoc = NULL;
468 }
469 if (reader->allocs & XML_TEXTREADER_CTXT)
470 xmlFreeParserCtxt(reader->ctxt);
471 }
472 if (reader->sax != NULL)
473 xmlFree(reader->sax);
474 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
475 xmlFreeParserInputBuffer(reader->input);
476 xmlFree(reader);
477}
478
479/************************************************************************
480 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000481 * Methods for XmlTextReader *
482 * *
483 ************************************************************************/
484/**
485 * xmlTextReaderClose:
486 * @reader: the xmlTextReaderPtr used
487 *
488 * This method releases any resources allocated by the current instance
489 * changes the state to Closed and close any underlying input.
490 *
491 * Returns 0 or -1 in case of error
492 */
493int
494xmlTextReaderClose(xmlTextReaderPtr reader) {
495 if (reader == NULL)
496 return(-1);
497 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000498 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000499 reader->mode = XML_TEXTREADER_MODE_CLOSED;
500 if (reader->ctxt != NULL) {
501 if (reader->ctxt->myDoc != NULL) {
502 xmlFreeDoc(reader->ctxt->myDoc);
503 reader->ctxt->myDoc = NULL;
504 }
505 if (reader->allocs & XML_TEXTREADER_CTXT) {
506 xmlFreeParserCtxt(reader->ctxt);
507 reader->allocs -= XML_TEXTREADER_CTXT;
508 }
509 }
510 if (reader->sax != NULL) {
511 xmlFree(reader->sax);
512 reader->sax = NULL;
513 }
514 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
515 xmlFreeParserInputBuffer(reader->input);
516 reader->allocs -= XML_TEXTREADER_INPUT;
517 }
518 return(0);
519}
520
521/**
522 * xmlTextReaderGetAttributeNo:
523 * @reader: the xmlTextReaderPtr used
524 * @no: the zero-based index of the attribute relative to the containing element
525 *
526 * Provides the value of the attribute with the specified index relative
527 * to the containing element.
528 *
529 * Returns a string containing the value of the specified attribute, or NULL
530 * in case of error. The string must be deallocated by the caller.
531 */
532xmlChar *
533xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
534 xmlChar *ret;
535 int i;
536 xmlAttrPtr cur;
537 xmlNsPtr ns;
538
539 if (reader == NULL)
540 return(NULL);
541 if (reader->node == NULL)
542 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000543 if (reader->curnode != NULL)
544 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000545 /* TODO: handle the xmlDecl */
546 if (reader->node->type != XML_ELEMENT_NODE)
547 return(NULL);
548
549 ns = reader->node->nsDef;
550 for (i = 0;(i < no) && (ns != NULL);i++) {
551 ns = ns->next;
552 }
553 if (ns != NULL)
554 return(xmlStrdup(ns->href));
555
556 cur = reader->node->properties;
557 if (cur == NULL)
558 return(NULL);
559 for (;i < no;i++) {
560 cur = cur->next;
561 if (cur == NULL)
562 return(NULL);
563 }
564 /* TODO walk the DTD if present */
565
566 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
567 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
568 return(ret);
569}
570
571/**
572 * xmlTextReaderGetAttribute:
573 * @reader: the xmlTextReaderPtr used
574 * @name: the qualified name of the attribute.
575 *
576 * Provides the value of the attribute with the specified qualified name.
577 *
578 * Returns a string containing the value of the specified attribute, or NULL
579 * in case of error. The string must be deallocated by the caller.
580 */
581xmlChar *
582xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
583 xmlChar *prefix = NULL;
584 xmlChar *localname;
585 xmlNsPtr ns;
586 xmlChar *ret = NULL;
587
588 if ((reader == NULL) || (name == NULL))
589 return(NULL);
590 if (reader->node == NULL)
591 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000592 if (reader->curnode != NULL)
593 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000594
595 /* TODO: handle the xmlDecl */
596 if (reader->node->type != XML_ELEMENT_NODE)
597 return(NULL);
598
599 localname = xmlSplitQName2(name, &prefix);
600 if (localname == NULL)
601 return(xmlGetProp(reader->node, name));
602
603 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
604 if (ns != NULL)
605 ret = xmlGetNsProp(reader->node, localname, ns->href);
606
607 if (localname != NULL)
608 xmlFree(localname);
609 if (prefix != NULL)
610 xmlFree(prefix);
611 return(ret);
612}
613
614
615/**
616 * xmlTextReaderGetAttributeNs:
617 * @reader: the xmlTextReaderPtr used
618 * @localName: the local name of the attribute.
619 * @namespaceURI: the namespace URI of the attribute.
620 *
621 * Provides the value of the specified attribute
622 *
623 * Returns a string containing the value of the specified attribute, or NULL
624 * in case of error. The string must be deallocated by the caller.
625 */
626xmlChar *
627xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
628 const xmlChar *namespaceURI) {
629 if ((reader == NULL) || (localName == NULL))
630 return(NULL);
631 if (reader->node == NULL)
632 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000633 if (reader->curnode != NULL)
634 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000635
636 /* TODO: handle the xmlDecl */
637 if (reader->node->type != XML_ELEMENT_NODE)
638 return(NULL);
639
640 return(xmlGetNsProp(reader->node, localName, namespaceURI));
641}
642
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000643/**
644 * xmlTextReaderGetRemainder:
645 * @reader: the xmlTextReaderPtr used
646 *
647 * Method to get the remainder of the buffered XML. this method stops the
648 * parser, set its state to End Of File and return the input stream with
649 * what is left that the parser did not use.
650 *
651 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
652 * in case of error.
653 */
654xmlParserInputBufferPtr
655xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
656 xmlParserInputBufferPtr ret = NULL;
657
658 if (reader == NULL)
659 return(NULL);
660 if (reader->node == NULL)
661 return(NULL);
662
663 reader->node = NULL;
664 reader->curnode = NULL;
665 reader->mode = XML_TEXTREADER_MODE_EOF;
666 if (reader->ctxt != NULL) {
667 if (reader->ctxt->myDoc != NULL) {
668 xmlFreeDoc(reader->ctxt->myDoc);
669 reader->ctxt->myDoc = NULL;
670 }
671 if (reader->allocs & XML_TEXTREADER_CTXT) {
672 xmlFreeParserCtxt(reader->ctxt);
673 reader->allocs -= XML_TEXTREADER_CTXT;
674 }
675 }
676 if (reader->sax != NULL) {
677 xmlFree(reader->sax);
678 reader->sax = NULL;
679 }
680 if (reader->allocs & XML_TEXTREADER_INPUT) {
681 ret = reader->input;
682 reader->allocs -= XML_TEXTREADER_INPUT;
683 } else {
684 /*
685 * Hum, one may need to duplicate the data structure because
686 * without reference counting the input may be freed twice:
687 * - by the layer which allocated it.
688 * - by the layer to which would have been returned to.
689 */
690 TODO
691 return(NULL);
692 }
693 return(ret);
694}
695
696/**
697 * xmlTextReaderLookupNamespace:
698 * @reader: the xmlTextReaderPtr used
699 * @prefix: the prefix whose namespace URI is to be resolved. To return
700 * the default namespace, specify NULL
701 *
702 * Resolves a namespace prefix in the scope of the current element.
703 *
704 * Returns a string containing the namespace URI to which the prefix maps
705 * or NULL in case of error. The string must be deallocated by the caller.
706 */
707xmlChar *
708xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
709 xmlNsPtr ns;
710
711 if (reader == NULL)
712 return(NULL);
713 if (reader->node == NULL)
714 return(NULL);
715
716 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
717 if (ns == NULL)
718 return(NULL);
719 return(xmlStrdup(ns->href));
720}
721
722/**
723 * xmlTextReaderMoveToAttributeNo:
724 * @reader: the xmlTextReaderPtr used
725 * @no: the zero-based index of the attribute relative to the containing
726 * element.
727 *
728 * Moves the position of the current instance to the attribute with
729 * the specified index relative to the containing element.
730 *
731 * Returns 1 in case of success, -1 in case of error, 0 if not found
732 */
733int
734xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
735 int i;
736 xmlAttrPtr cur;
737 xmlNsPtr ns;
738
739 if (reader == NULL)
740 return(-1);
741 if (reader->node == NULL)
742 return(-1);
743 /* TODO: handle the xmlDecl */
744 if (reader->node->type != XML_ELEMENT_NODE)
745 return(-1);
746
747 reader->curnode = NULL;
748
749 ns = reader->node->nsDef;
750 for (i = 0;(i < no) && (ns != NULL);i++) {
751 ns = ns->next;
752 }
753 if (ns != NULL) {
754 reader->curnode = (xmlNodePtr) ns;
755 return(1);
756 }
757
758 cur = reader->node->properties;
759 if (cur == NULL)
760 return(0);
761 for (;i < no;i++) {
762 cur = cur->next;
763 if (cur == NULL)
764 return(0);
765 }
766 /* TODO walk the DTD if present */
767
768 reader->curnode = (xmlNodePtr) cur;
769 return(1);
770}
771
772/**
773 * xmlTextReaderMoveToAttribute:
774 * @reader: the xmlTextReaderPtr used
775 * @name: the qualified name of the attribute.
776 *
777 * Moves the position of the current instance to the attribute with
778 * the specified qualified name.
779 *
780 * Returns 1 in case of success, -1 in case of error, 0 if not found
781 */
782int
783xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
784 xmlChar *prefix = NULL;
785 xmlChar *localname;
786 xmlNsPtr ns;
787 xmlAttrPtr prop;
788
789 if ((reader == NULL) || (name == NULL))
790 return(-1);
791 if (reader->node == NULL)
792 return(-1);
793
794 /* TODO: handle the xmlDecl */
795 if (reader->node->type != XML_ELEMENT_NODE)
796 return(0);
797
798 localname = xmlSplitQName2(name, &prefix);
799 if (localname == NULL) {
800 /*
801 * Namespace default decl
802 */
803 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
804 ns = reader->node->nsDef;
805 while (ns != NULL) {
806 if (ns->prefix == NULL) {
807 reader->curnode = (xmlNodePtr) ns;
808 return(1);
809 }
810 ns = ns->next;
811 }
812 return(0);
813 }
814
815 prop = reader->node->properties;
816 while (prop != NULL) {
817 /*
818 * One need to have
819 * - same attribute names
820 * - and the attribute carrying that namespace
821 */
822 if ((xmlStrEqual(prop->name, name)) &&
823 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
824 reader->curnode = (xmlNodePtr) prop;
825 return(1);
826 }
827 prop = prop->next;
828 }
829 return(0);
830 }
831
832 /*
833 * Namespace default decl
834 */
835 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
836 ns = reader->node->nsDef;
837 while (ns != NULL) {
838 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
839 reader->curnode = (xmlNodePtr) ns;
840 goto found;
841 }
842 ns = ns->next;
843 }
844 goto not_found;
845 }
846 prop = reader->node->properties;
847 while (prop != NULL) {
848 /*
849 * One need to have
850 * - same attribute names
851 * - and the attribute carrying that namespace
852 */
853 if ((xmlStrEqual(prop->name, localname)) &&
854 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
855 reader->curnode = (xmlNodePtr) prop;
856 goto found;
857 }
858 prop = prop->next;
859 }
860not_found:
861 if (localname != NULL)
862 xmlFree(localname);
863 if (prefix != NULL)
864 xmlFree(prefix);
865 return(0);
866
867found:
868 if (localname != NULL)
869 xmlFree(localname);
870 if (prefix != NULL)
871 xmlFree(prefix);
872 return(1);
873}
874
875/**
876 * xmlTextReaderMoveToAttributeNs:
877 * @reader: the xmlTextReaderPtr used
878 * @localName: the local name of the attribute.
879 * @namespaceURI: the namespace URI of the attribute.
880 *
881 * Moves the position of the current instance to the attribute with the
882 * specified local name and namespace URI.
883 *
884 * Returns 1 in case of success, -1 in case of error, 0 if not found
885 */
886int
887xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
888 const xmlChar *localName, const xmlChar *namespaceURI) {
889 xmlAttrPtr prop;
890 xmlNodePtr node;
891
892 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
893 return(-1);
894 if (reader->node == NULL)
895 return(-1);
896 if (reader->node->type != XML_ELEMENT_NODE)
897 return(0);
898 node = reader->node;
899
900 /*
901 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
902 * namespace name associated to "xmlns"
903 */
904 prop = node->properties;
905 while (prop != NULL) {
906 /*
907 * One need to have
908 * - same attribute names
909 * - and the attribute carrying that namespace
910 */
911 if (xmlStrEqual(prop->name, localName) &&
912 ((prop->ns != NULL) &&
913 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
914 reader->curnode = (xmlNodePtr) prop;
915 return(1);
916 }
917 prop = prop->next;
918 }
919 return(0);
920}
921
922/**
923 * xmlTextReaderMoveToFirstAttribute:
924 * @reader: the xmlTextReaderPtr used
925 *
926 * Moves the position of the current instance to the first attribute
927 * associated with the current node.
928 *
929 * Returns 1 in case of success, -1 in case of error, 0 if not found
930 */
931int
932xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
933 if (reader == NULL)
934 return(-1);
935 if (reader->node == NULL)
936 return(-1);
937 if (reader->node->type != XML_ELEMENT_NODE)
938 return(0);
939
940 if (reader->node->nsDef != NULL) {
941 reader->curnode = (xmlNodePtr) reader->node->nsDef;
942 return(1);
943 }
944 if (reader->node->properties != NULL) {
945 reader->curnode = (xmlNodePtr) reader->node->properties;
946 return(1);
947 }
948 return(0);
949}
950
951/**
952 * xmlTextReaderMoveToNextAttribute:
953 * @reader: the xmlTextReaderPtr used
954 *
955 * Moves the position of the current instance to the next attribute
956 * associated with the current node.
957 *
958 * Returns 1 in case of success, -1 in case of error, 0 if not found
959 */
960int
961xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
962 if (reader == NULL)
963 return(-1);
964 if (reader->node == NULL)
965 return(-1);
966 if (reader->node->type != XML_ELEMENT_NODE)
967 return(0);
968 if (reader->curnode == NULL)
969 return(xmlTextReaderMoveToFirstAttribute(reader));
970
971 if (reader->curnode->type == XML_NAMESPACE_DECL) {
972 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
973 if (ns->next != NULL) {
974 reader->curnode = (xmlNodePtr) ns->next;
975 return(1);
976 }
977 if (reader->node->properties != NULL) {
978 reader->curnode = (xmlNodePtr) reader->node->properties;
979 return(1);
980 }
981 return(0);
982 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
983 (reader->curnode->next != NULL)) {
984 reader->curnode = reader->curnode->next;
985 return(1);
986 }
987 return(0);
988}
989
990/**
991 * xmlTextReaderMoveToElement:
992 * @reader: the xmlTextReaderPtr used
993 *
994 * Moves the position of the current instance to the node that
995 * contains the current Attribute node.
996 *
997 * Returns 1 in case of success, -1 in case of error, 0 if not moved
998 */
999int
1000xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
1001 if (reader == NULL)
1002 return(-1);
1003 if (reader->node == NULL)
1004 return(-1);
1005 if (reader->node->type != XML_ELEMENT_NODE)
1006 return(0);
1007 if (reader->curnode != NULL) {
1008 reader->curnode = NULL;
1009 return(1);
1010 }
1011 return(0);
1012}
1013
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001014/************************************************************************
1015 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001016 * Acces API to the current node *
1017 * *
1018 ************************************************************************/
1019/**
1020 * xmlTextReaderAttributeCount:
1021 * @reader: the xmlTextReaderPtr used
1022 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001023 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001024 *
1025 * Returns 0 i no attributes, -1 in case of error or the attribute count
1026 */
1027int
1028xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
1029 int ret;
1030 xmlAttrPtr attr;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001031 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001032
1033 if (reader == NULL)
1034 return(-1);
1035 if (reader->node == NULL)
1036 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001037
1038 if (reader->curnode != NULL)
1039 node = reader->curnode;
1040 else
1041 node = reader->node;
1042
1043 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001044 return(0);
1045 if ((reader->state == XML_TEXTREADER_END) ||
1046 (reader->state == XML_TEXTREADER_BACKTRACK))
1047 return(0);
1048 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001049 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001050 while (attr != NULL) {
1051 ret++;
1052 attr = attr->next;
1053 }
1054 return(ret);
1055}
1056
1057/**
1058 * xmlTextReaderNodeType:
1059 * @reader: the xmlTextReaderPtr used
1060 *
1061 * Get the node type of the current node
1062 * Reference:
1063 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
1064 *
1065 * Returns the xmlNodeType of the current node or -1 in case of error
1066 */
1067int
1068xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001069 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001070 if (reader == NULL)
1071 return(-1);
1072 if (reader->node == NULL)
1073 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001074 if (reader->curnode != NULL)
1075 node = reader->curnode;
1076 else
1077 node = reader->node;
1078 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001079 case XML_ELEMENT_NODE:
1080 if ((reader->state == XML_TEXTREADER_END) ||
1081 (reader->state == XML_TEXTREADER_BACKTRACK))
1082 return(15);
1083 return(1);
1084 case XML_ATTRIBUTE_NODE:
1085 return(2);
1086 case XML_TEXT_NODE:
1087 return(3); /* TODO: SignificantWhitespace == 14 Whitespace == 13 */
1088 case XML_CDATA_SECTION_NODE:
1089 return(4);
1090 case XML_ENTITY_REF_NODE:
1091 return(5);
1092 case XML_ENTITY_NODE:
1093 return(6);
1094 case XML_PI_NODE:
1095 return(7);
1096 case XML_COMMENT_NODE:
1097 return(8);
1098 case XML_DOCUMENT_NODE:
1099 case XML_HTML_DOCUMENT_NODE:
1100#ifdef LIBXML_DOCB_ENABLED
1101 case XML_DOCB_DOCUMENT_NODE:
1102#endif
1103 return(9);
1104 case XML_DOCUMENT_FRAG_NODE:
1105 return(11);
1106 case XML_NOTATION_NODE:
1107 return(12);
1108 case XML_DOCUMENT_TYPE_NODE:
1109 case XML_DTD_NODE:
1110 return(10);
1111
1112 case XML_ELEMENT_DECL:
1113 case XML_ATTRIBUTE_DECL:
1114 case XML_ENTITY_DECL:
1115 case XML_NAMESPACE_DECL:
1116 case XML_XINCLUDE_START:
1117 case XML_XINCLUDE_END:
1118 return(0);
1119 }
1120 return(-1);
1121}
1122
1123/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00001124 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001125 * @reader: the xmlTextReaderPtr used
1126 *
1127 * Check if the current node is empty
1128 *
1129 * Returns 1 if empty, 0 if not and -1 in case of error
1130 */
1131int
1132xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
1133 if ((reader == NULL) || (reader->node == NULL))
1134 return(-1);
1135 if (reader->node->children != NULL)
1136 return(0);
1137 if ((reader->state == XML_TEXTREADER_EMPTY) ||
1138 (reader->state == XML_TEXTREADER_BACKTRACK))
1139 return(1);
1140 return(0);
1141}
1142
1143/**
1144 * xmlTextReaderLocalName:
1145 * @reader: the xmlTextReaderPtr used
1146 *
1147 * The local name of the node.
1148 *
1149 * Returns the local name or NULL if not available
1150 */
1151xmlChar *
1152xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001153 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001154 if ((reader == NULL) || (reader->node == NULL))
1155 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001156 if (reader->curnode != NULL)
1157 node = reader->curnode;
1158 else
1159 node = reader->node;
1160 if (node->type == XML_NAMESPACE_DECL) {
1161 xmlNsPtr ns = (xmlNsPtr) node;
1162 if (ns->prefix == NULL)
1163 return(xmlStrdup(BAD_CAST "xmlns"));
1164 else
1165 return(xmlStrdup(ns->prefix));
1166 }
1167 if ((node->type != XML_ELEMENT_NODE) &&
1168 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001169 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001170 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001171}
1172
1173/**
1174 * xmlTextReaderName:
1175 * @reader: the xmlTextReaderPtr used
1176 *
1177 * The qualified name of the node, equal to Prefix :LocalName.
1178 *
1179 * Returns the local name or NULL if not available
1180 */
1181xmlChar *
1182xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001183 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001184 xmlChar *ret;
1185
1186 if ((reader == NULL) || (reader->node == NULL))
1187 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001188 if (reader->curnode != NULL)
1189 node = reader->curnode;
1190 else
1191 node = reader->node;
1192 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001193 case XML_ELEMENT_NODE:
1194 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001195 if ((node->ns == NULL) ||
1196 (node->ns->prefix == NULL))
1197 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001198
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001199 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001200 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001201 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001202 return(ret);
1203 case XML_TEXT_NODE:
1204 return(xmlStrdup(BAD_CAST "#text"));
1205 case XML_CDATA_SECTION_NODE:
1206 return(xmlStrdup(BAD_CAST "#cdata-section"));
1207 case XML_ENTITY_NODE:
1208 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001209 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001210 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001211 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001212 case XML_COMMENT_NODE:
1213 return(xmlStrdup(BAD_CAST "#comment"));
1214 case XML_DOCUMENT_NODE:
1215 case XML_HTML_DOCUMENT_NODE:
1216#ifdef LIBXML_DOCB_ENABLED
1217 case XML_DOCB_DOCUMENT_NODE:
1218#endif
1219 return(xmlStrdup(BAD_CAST "#document"));
1220 case XML_DOCUMENT_FRAG_NODE:
1221 return(xmlStrdup(BAD_CAST "#document-fragment"));
1222 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001223 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001224 case XML_DOCUMENT_TYPE_NODE:
1225 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001226 return(xmlStrdup(node->name));
1227 case XML_NAMESPACE_DECL: {
1228 xmlNsPtr ns = (xmlNsPtr) node;
1229
1230 ret = xmlStrdup(BAD_CAST "xmlns");
1231 if (ns->prefix == NULL)
1232 return(ret);
1233 ret = xmlStrcat(ret, BAD_CAST ":");
1234 ret = xmlStrcat(ret, ns->prefix);
1235 return(ret);
1236 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001237
1238 case XML_ELEMENT_DECL:
1239 case XML_ATTRIBUTE_DECL:
1240 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001241 case XML_XINCLUDE_START:
1242 case XML_XINCLUDE_END:
1243 return(NULL);
1244 }
1245 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001246}
1247
1248/**
1249 * xmlTextReaderPrefix:
1250 * @reader: the xmlTextReaderPtr used
1251 *
1252 * A shorthand reference to the namespace associated with the node.
1253 *
1254 * Returns the prefix or NULL if not available
1255 */
1256xmlChar *
1257xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001258 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001259 if ((reader == NULL) || (reader->node == NULL))
1260 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001261 if (reader->curnode != NULL)
1262 node = reader->curnode;
1263 else
1264 node = reader->node;
1265 if (node->type == XML_NAMESPACE_DECL) {
1266 xmlNsPtr ns = (xmlNsPtr) node;
1267 if (ns->prefix == NULL)
1268 return(NULL);
1269 return(xmlStrdup(BAD_CAST "xmlns"));
1270 }
1271 if ((node->type != XML_ELEMENT_NODE) &&
1272 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001273 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001274 if ((node->ns != NULL) || (node->ns->prefix != NULL))
1275 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001276 return(NULL);
1277}
1278
1279/**
1280 * xmlTextReaderNamespaceUri:
1281 * @reader: the xmlTextReaderPtr used
1282 *
1283 * The URI defining the namespace associated with the node.
1284 *
1285 * Returns the namespace URI or NULL if not available
1286 */
1287xmlChar *
1288xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001289 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001290 if ((reader == NULL) || (reader->node == NULL))
1291 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001292 if (reader->curnode != NULL)
1293 node = reader->curnode;
1294 else
1295 node = reader->node;
1296 if (node->type == XML_NAMESPACE_DECL) {
1297 xmlNsPtr ns = (xmlNsPtr) node;
1298 return(xmlStrdup(ns->href));
1299 }
1300 if ((node->type != XML_ELEMENT_NODE) &&
1301 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001302 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001303 if (node->ns != NULL)
1304 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001305 return(NULL);
1306}
1307
1308/**
1309 * xmlTextReaderBaseUri:
1310 * @reader: the xmlTextReaderPtr used
1311 *
1312 * The base URI of the node.
1313 *
1314 * Returns the base URI or NULL if not available
1315 */
1316xmlChar *
1317xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
1318 if ((reader == NULL) || (reader->node == NULL))
1319 return(NULL);
1320 return(xmlNodeGetBase(NULL, reader->node));
1321}
1322
1323/**
1324 * xmlTextReaderDepth:
1325 * @reader: the xmlTextReaderPtr used
1326 *
1327 * The depth of the node in the tree.
1328 *
1329 * Returns the depth or -1 in case of error
1330 */
1331int
1332xmlTextReaderDepth(xmlTextReaderPtr reader) {
1333 if (reader == NULL)
1334 return(-1);
1335 if (reader->node == NULL)
1336 return(0);
1337
1338 return(reader->depth);
1339}
1340
1341/**
1342 * xmlTextReaderHasAttributes:
1343 * @reader: the xmlTextReaderPtr used
1344 *
1345 * Whether the node has attributes.
1346 *
1347 * Returns 1 if true, 0 if false, and -1 in case or error
1348 */
1349int
1350xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001351 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001352 if (reader == NULL)
1353 return(-1);
1354 if (reader->node == NULL)
1355 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001356 if (reader->curnode != NULL)
1357 node = reader->curnode;
1358 else
1359 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001360
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001361 if ((node->type == XML_ELEMENT_NODE) &&
1362 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001363 return(1);
1364 /* TODO: handle the xmlDecl */
1365 return(0);
1366}
1367
1368/**
1369 * xmlTextReaderHasValue:
1370 * @reader: the xmlTextReaderPtr used
1371 *
1372 * Whether the node can have a text value.
1373 *
1374 * Returns 1 if true, 0 if false, and -1 in case or error
1375 */
1376int
1377xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001378 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001379 if (reader == NULL)
1380 return(-1);
1381 if (reader->node == NULL)
1382 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001383 if (reader->curnode != NULL)
1384 node = reader->curnode;
1385 else
1386 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001387
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001388 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001389 case XML_ATTRIBUTE_NODE:
1390 case XML_TEXT_NODE:
1391 case XML_CDATA_SECTION_NODE:
1392 case XML_PI_NODE:
1393 case XML_COMMENT_NODE:
1394 return(1);
1395 default:
1396 return(0);
1397 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001398 return(0);
1399}
1400
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001401/**
1402 * xmlTextReaderValue:
1403 * @reader: the xmlTextReaderPtr used
1404 *
1405 * Provides the text value of the node if present
1406 *
1407 * Returns the string or NULL if not available. The retsult must be deallocated
1408 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001409 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001410xmlChar *
1411xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001412 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001413 if (reader == NULL)
1414 return(NULL);
1415 if (reader->node == NULL)
1416 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001417 if (reader->curnode != NULL)
1418 node = reader->curnode;
1419 else
1420 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001421
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001422 switch (node->type) {
1423 case XML_NAMESPACE_DECL:
1424 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001425 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001426 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001427
1428 if (attr->parent != NULL)
1429 return (xmlNodeListGetString
1430 (attr->parent->doc, attr->children, 1));
1431 else
1432 return (xmlNodeListGetString(NULL, attr->children, 1));
1433 break;
1434 }
1435 case XML_TEXT_NODE:
1436 case XML_CDATA_SECTION_NODE:
1437 case XML_PI_NODE:
1438 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001439 if (node->content != NULL)
1440 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001441 default:
1442 return(NULL);
1443 }
1444 return(NULL);
1445}
1446
1447/**
1448 * xmlTextReaderIsDefault:
1449 * @reader: the xmlTextReaderPtr used
1450 *
1451 * Whether an Attribute node was generated from the default value
1452 * defined in the DTD or schema.
1453 *
1454 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
1455 */
1456int
1457xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
1458 if (reader == NULL)
1459 return(-1);
1460 return(0);
1461}
1462
1463/**
1464 * xmlTextReaderQuoteChar:
1465 * @reader: the xmlTextReaderPtr used
1466 *
1467 * The quotation mark character used to enclose the value of an attribute.
1468 *
1469 * Returns " or ' and -1 in case of error
1470 */
1471int
1472xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
1473 if (reader == NULL)
1474 return(-1);
1475 /* TODO maybe lookup the attribute value for " first */
1476 return((int) '"');
1477}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001478
1479/**
1480 * xmlTextReaderXmlLang:
1481 * @reader: the xmlTextReaderPtr used
1482 *
1483 * The xml:lang scope within which the node resides.
1484 *
1485 * Returns the xml:lang value or NULL if none exists.
1486 */
1487xmlChar *
1488xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
1489 if (reader == NULL)
1490 return(NULL);
1491 if (reader->node == NULL)
1492 return(NULL);
1493 return(xmlNodeGetLang(reader->node));
1494}
1495