blob: 68632c6aca6dfb3f6cbe667b4d0c757291c63b01 [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
13#define IN_LIBXML
14#include "libxml.h"
15
16#include <string.h> /* for memset() only ! */
17
18#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
24
25#include <libxml/xmlmemory.h>
26#include <libxml/xmlIO.h>
27#include <libxml/xmlreader.h>
28
29/* #define DEBUG_CALLBACKS */
30/* #define DEBUG_READER */
31
32/**
33 * TODO:
34 *
35 * macro to flag unimplemented blocks
36 */
37#define TODO \
38 xmlGenericError(xmlGenericErrorContext, \
39 "Unimplemented block at %s:%d\n", \
40 __FILE__, __LINE__);
41
42#ifdef DEBUG_READER
43#define DUMP_READER xmlTextReaderDebug(reader);
44#else
45#define DUMP_READER
46#endif
47
48/************************************************************************
49 * *
50 * The parser: maps the Text Reader API on top of the existing *
51 * parsing routines building a tree *
52 * *
53 ************************************************************************/
54
55#define XML_TEXTREADER_INPUT 1
56#define XML_TEXTREADER_CTXT 2
57
58typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000059 XML_TEXTREADER_MODE_INITIAL = 0,
60 XML_TEXTREADER_MODE_INTERACTIVE = 1,
61 XML_TEXTREADER_MODE_ERROR = 2,
62 XML_TEXTREADER_MODE_EOF =3,
63 XML_TEXTREADER_MODE_CLOSED = 4,
64 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000065} xmlTextReaderMode;
66
67typedef enum {
68 XML_TEXTREADER_NONE = -1,
69 XML_TEXTREADER_START= 0,
70 XML_TEXTREADER_ELEMENT= 1,
71 XML_TEXTREADER_END= 2,
72 XML_TEXTREADER_EMPTY= 3,
73 XML_TEXTREADER_BACKTRACK= 4
74} xmlTextReaderState;
75
76struct _xmlTextReader {
77 int mode; /* the parsing mode */
78 int allocs; /* what structure were deallocated */
79 xmlTextReaderState state;
80 xmlParserCtxtPtr ctxt; /* the parser context */
81 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
82 xmlParserInputBufferPtr input; /* the input */
83 startElementSAXFunc startElement;/* initial SAX callbacks */
84 endElementSAXFunc endElement; /* idem */
85 unsigned int base; /* base of the segment in the input */
86 unsigned int cur; /* current position in the input */
87 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +000088 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000089 int depth; /* depth of the current node */
90};
91
92#ifdef DEBUG_READER
93static void
94xmlTextReaderDebug(xmlTextReaderPtr reader) {
95 if ((reader == NULL) || (reader->ctxt == NULL)) {
96 fprintf(stderr, "xmlTextReader NULL\n");
97 return;
98 }
99 fprintf(stderr, "xmlTextReader: state %d depth %d ",
100 reader->state, reader->depth);
101 if (reader->node == NULL) {
102 fprintf(stderr, "node = NULL\n");
103 } else {
104 fprintf(stderr, "node %s\n", reader->node->name);
105 }
106 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
107 reader->base, reader->cur, reader->ctxt->nodeNr);
108 if (reader->input->buffer == NULL) {
109 fprintf(stderr, "buffer is NULL\n");
110 } else {
111#ifdef LIBXML_DEBUG_ENABLED
112 xmlDebugDumpString(stderr,
113 &reader->input->buffer->content[reader->cur]);
114#endif
115 fprintf(stderr, "\n");
116 }
117}
118#endif
119
120/**
121 * xmlTextReaderStartElement:
122 * @ctx: the user data (XML parser context)
123 * @fullname: The element name, including namespace prefix
124 * @atts: An array of name/value attributes pairs, NULL terminated
125 *
126 * called when an opening tag has been processed.
127 */
128static void
129xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
130 const xmlChar **atts) {
131 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
132 xmlTextReaderPtr reader = ctxt->_private;
133
134#ifdef DEBUG_CALLBACKS
135 printf("xmlTextReaderStartElement(%s)\n", fullname);
136#endif
137 if ((reader != NULL) && (reader->startElement != NULL))
138 reader->startElement(ctx, fullname, atts);
139 reader->state = XML_TEXTREADER_ELEMENT;
140}
141
142/**
143 * xmlTextReaderEndElement:
144 * @ctx: the user data (XML parser context)
145 * @fullname: The element name, including namespace prefix
146 *
147 * called when an ending tag has been processed.
148 */
149static void
150xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
151 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
152 xmlTextReaderPtr reader = ctxt->_private;
153
154#ifdef DEBUG_CALLBACKS
155 printf("xmlTextReaderEndElement(%s)\n", fullname);
156#endif
157 if ((reader != NULL) && (reader->endElement != NULL))
158 reader->endElement(ctx, fullname);
159 if (reader->state == XML_TEXTREADER_ELEMENT)
160 reader->state = XML_TEXTREADER_EMPTY;
161 else
162 reader->state = XML_TEXTREADER_END;
163}
164
165/**
166 * xmlTextReaderPushData:
167 * @reader: the xmlTextReaderPtr used
168 *
169 * Push data down the progressive parser until a significant callback
170 * got raised.
171 *
172 * Returns -1 in case of failure, 0 otherwise
173 */
174static int
175xmlTextReaderPushData(xmlTextReaderPtr reader) {
176 unsigned int cur = reader->cur;
177 xmlBufferPtr inbuf;
178 int val;
179
180 if ((reader->input == NULL) || (reader->input->buffer == NULL))
181 return(-1);
182
183 reader->state = XML_TEXTREADER_NONE;
184 inbuf = reader->input->buffer;
185 while (reader->state == XML_TEXTREADER_NONE) {
186 if (cur >= inbuf->use) {
187 /*
188 * Refill the buffer unless we are at the end of the stream
189 */
190 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
191 val = xmlParserInputBufferRead(reader->input, 4096);
192 if (val <= 0) {
193 reader->mode = XML_TEXTREADER_MODE_EOF;
194 return(val);
195 }
196 } else
197 break;
198 }
199 if ((inbuf->content[cur] == '>') || (inbuf->content[cur] == '&')) {
200 cur = cur + 1;
201 val = xmlParseChunk(reader->ctxt,
202 (const char *) &inbuf->content[reader->cur],
203 cur - reader->cur, 0);
204 if (val != 0)
205 return(-1);
206 reader->cur = cur;
207 break;
208 } else {
209 cur = cur + 1;
210
211 /*
212 * One may have to force a flush at some point when parsing really
213 * large CDATA sections
214 */
215 if ((cur - reader->cur > 4096) && (reader->base == 0) &&
Daniel Veillard67df8092002-12-16 22:04:11 +0000216 (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000217 cur = cur + 1;
218 val = xmlParseChunk(reader->ctxt,
219 (const char *) &inbuf->content[reader->cur],
220 cur - reader->cur, 0);
221 if (val != 0)
222 return(-1);
223 reader->cur = cur;
224 }
225 }
226 }
227 /*
228 * Discard the consumed input when needed and possible
229 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000230 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000231 if ((reader->cur >= 4096) && (reader->base == 0)) {
232 val = xmlBufferShrink(inbuf, cur);
233 if (val >= 0) {
234 reader->cur -= val;
235 }
236 }
237 }
238
239 /*
240 * At the end of the stream signal that the work is done to the Push
241 * parser.
242 */
243 if ((reader->mode == XML_TEXTREADER_MODE_EOF) && (cur >= inbuf->use)) {
244 val = xmlParseChunk(reader->ctxt,
245 (const char *) &inbuf->content[reader->cur], 0, 1);
246 }
247 return(0);
248}
249
250/**
251 * xmlTextReaderRead:
252 * @reader: the xmlTextReaderPtr used
253 *
254 * Moves the position of the current instance to the next node in
255 * the stream, exposing its properties.
256 *
257 * Returns 1 if the node was read successfully, 0 if there is no more
258 * nodes to read, or -1 in case of error
259 */
260int
261xmlTextReaderRead(xmlTextReaderPtr reader) {
262 int val, olddepth;
263 xmlTextReaderState oldstate;
264 xmlNodePtr oldnode;
265
266 if ((reader == NULL) || (reader->ctxt == NULL))
267 return(-1);
268 if (reader->ctxt->wellFormed != 1)
269 return(-1);
270
271#ifdef DEBUG_READER
272 fprintf(stderr, "\nREAD ");
273 DUMP_READER
274#endif
Daniel Veillard67df8092002-12-16 22:04:11 +0000275 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
276 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000277 /*
278 * Initial state
279 */
280 do {
281 val = xmlTextReaderPushData(reader);
282 if (val < 0)
283 return(-1);
284 } while ((reader->ctxt->node == NULL) &&
285 (reader->mode != XML_TEXTREADER_MODE_EOF));
286 if (reader->ctxt->node == NULL) {
287 if (reader->ctxt->myDoc != NULL)
288 reader->node = reader->ctxt->myDoc->children;
289 if (reader->node == NULL)
290 return(-1);
291 } else {
292 reader->node = reader->ctxt->node;
293 }
294 reader->depth = 1;
295 return(1);
296 }
297 oldstate = reader->state;
298 olddepth = reader->ctxt->nodeNr;
299 oldnode = reader->node;
300 /*
301 * If we are not backtracking on ancestors or examined nodes,
302 * that the parser didn't finished or that we arent at the end
303 * of stream, continue processing.
304 */
305 if (oldstate != XML_TEXTREADER_BACKTRACK) {
306 while (((reader->node->children == NULL) ||
307 (reader->node->type == XML_ENTITY_REF_NODE) ||
308 (reader->node->type == XML_DTD_NODE)) &&
309 (reader->node->next == NULL) &&
310 (reader->ctxt->nodeNr == olddepth) &&
311 (reader->ctxt->instate != XML_PARSER_EOF)) {
312 val = xmlTextReaderPushData(reader);
313 if (val < 0)
314 return(-1);
315 if (reader->node == NULL)
316 return(0);
317 }
318 if ((reader->node->children != NULL) &&
319 (reader->node->type != XML_ENTITY_REF_NODE) &&
320 (reader->node->type != XML_DTD_NODE)) {
321 reader->node = reader->node->children;
322 reader->depth++;
323 if ((reader->state != XML_TEXTREADER_ELEMENT) &&
324 (reader->state != XML_TEXTREADER_EMPTY))
325 reader->state = XML_TEXTREADER_ELEMENT;
326 DUMP_READER
327 return(1);
328 }
329 }
330 if (reader->node->next != NULL) {
331 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
332 (reader->node->type == XML_ELEMENT_NODE)) {
333 reader->state = XML_TEXTREADER_END;
334 DUMP_READER
335 return(1);
336 }
337 reader->node = reader->node->next;
338 reader->state = XML_TEXTREADER_ELEMENT;
339 DUMP_READER
340 /*
341 * Cleanup of the old node
342 */
343 if (oldnode->type != XML_DTD_NODE) {
344 xmlUnlinkNode(oldnode);
345 xmlFreeNode(oldnode);
346 }
347
348 return(1);
349 }
350 reader->node = reader->node->parent;
351 if ((reader->node == NULL) ||
352 (reader->node->type == XML_DOCUMENT_NODE) ||
353#ifdef LIBXML_DOCB_ENABLED
354 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
355#endif
356 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
357 reader->node = NULL;
358 reader->depth = 0;
359
360 /*
361 * Cleanup of the old node
362 */
363 if (oldnode->type != XML_DTD_NODE) {
364 xmlUnlinkNode(oldnode);
365 xmlFreeNode(oldnode);
366 }
367
368 return(0);
369 }
370 reader->depth--;
371 reader->state = XML_TEXTREADER_BACKTRACK;
372 DUMP_READER
373 return(1);
374}
375
Daniel Veillard67df8092002-12-16 22:04:11 +0000376/**
377 * xmlTextReaderReadState:
378 * @reader: the xmlTextReaderPtr used
379 *
380 * Gets the read state of the reader.
381 *
382 * Returns the state value, or -1 in case of error
383 */
384int
385xmlTextReaderReadState(xmlTextReaderPtr reader) {
386 if (reader == NULL)
387 return(-1);
388 return(reader->mode);
389}
390
391/**
392 * xmlTextReaderReadInnerXml:
393 * @reader: the xmlTextReaderPtr used
394 *
395 * Reads the contents of the current node, including child nodes and markup.
396 *
397 * Returns a string containing the XML content, or NULL if the current node
398 * is neither an element nor attribute, or has no child nodes. The
399 * string must be deallocated by the caller.
400 */
401xmlChar *
402xmlTextReaderReadInnerXml(xmlTextReaderPtr reader) {
403 TODO
404 return(NULL);
405}
406
407/**
408 * xmlTextReaderReadOuterXml:
409 * @reader: the xmlTextReaderPtr used
410 *
411 * Reads the contents of the current node, including child nodes and markup.
412 *
413 * Returns a string containing the XML content, or NULL if the current node
414 * is neither an element nor attribute, or has no child nodes. The
415 * string must be deallocated by the caller.
416 */
417xmlChar *
418xmlTextReaderReadOuterXml(xmlTextReaderPtr reader) {
419 TODO
420 return(NULL);
421}
422
423/**
424 * xmlTextReaderReadString:
425 * @reader: the xmlTextReaderPtr used
426 *
427 * Reads the contents of an element or a text node as a string.
428 *
429 * Returns a string containing the contents of the Element or Text node,
430 * or NULL if the reader is positioned on any other type of node.
431 * The string must be deallocated by the caller.
432 */
433xmlChar *
434xmlTextReaderReadString(xmlTextReaderPtr reader) {
435 TODO
436 return(NULL);
437}
438
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000439/************************************************************************
440 * *
441 * Constructor and destructors *
442 * *
443 ************************************************************************/
444/**
445 * xmlNewTextReader:
446 * @input: the xmlParserInputBufferPtr used to read data
447 *
448 * Create an xmlTextReader structure fed with @input
449 *
450 * Returns the new xmlTextReaderPtr or NULL in case of error
451 */
452xmlTextReaderPtr
453xmlNewTextReader(xmlParserInputBufferPtr input) {
454 xmlTextReaderPtr ret;
455 int val;
456
457 if (input == NULL)
458 return(NULL);
459 ret = xmlMalloc(sizeof(xmlTextReader));
460 if (ret == NULL) {
461 xmlGenericError(xmlGenericErrorContext,
462 "xmlNewTextReader : malloc failed\n");
463 return(NULL);
464 }
465 memset(ret, 0, sizeof(xmlTextReader));
466 ret->input = input;
467 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
468 if (ret->sax == NULL) {
469 xmlFree(ret);
470 xmlGenericError(xmlGenericErrorContext,
471 "xmlNewTextReader : malloc failed\n");
472 return(NULL);
473 }
474 memcpy(ret->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
475 ret->startElement = ret->sax->startElement;
476 ret->sax->startElement = xmlTextReaderStartElement;
477 ret->endElement = ret->sax->endElement;
478 ret->sax->endElement = xmlTextReaderEndElement;
479
Daniel Veillard67df8092002-12-16 22:04:11 +0000480 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000481 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000482 ret->curnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000483 val = xmlParserInputBufferRead(input, 4);
484 if (val >= 4) {
485 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
486 (const char *) ret->input->buffer->content, 4, NULL);
487 ret->base = 0;
488 ret->cur = 4;
489 } else {
490 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, NULL);
491 ret->base = 0;
492 ret->cur = 0;
493 }
494 ret->ctxt->_private = ret;
495 ret->allocs = XML_TEXTREADER_CTXT;
496 return(ret);
497
498}
499
500/**
501 * xmlNewTextReaderFilename:
502 * @URI: the URI of the resource to process
503 *
504 * Create an xmlTextReader structure fed with the resource at @URI
505 *
506 * Returns the new xmlTextReaderPtr or NULL in case of error
507 */
508xmlTextReaderPtr
509xmlNewTextReaderFilename(const char *URI) {
510 xmlParserInputBufferPtr input;
511 xmlTextReaderPtr ret;
512
513 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
514 if (input == NULL)
515 return(NULL);
516 ret = xmlNewTextReader(input);
517 if (ret == NULL) {
518 xmlFreeParserInputBuffer(input);
519 return(NULL);
520 }
521 ret->allocs |= XML_TEXTREADER_INPUT;
522 return(ret);
523}
524
525/**
526 * xmlFreeTextReader:
527 * @reader: the xmlTextReaderPtr
528 *
529 * Deallocate all the resources associated to the reader
530 */
531void
532xmlFreeTextReader(xmlTextReaderPtr reader) {
533 if (reader == NULL)
534 return;
535 if (reader->ctxt != NULL) {
536 if (reader->ctxt->myDoc != NULL) {
537 xmlFreeDoc(reader->ctxt->myDoc);
538 reader->ctxt->myDoc = NULL;
539 }
540 if (reader->allocs & XML_TEXTREADER_CTXT)
541 xmlFreeParserCtxt(reader->ctxt);
542 }
543 if (reader->sax != NULL)
544 xmlFree(reader->sax);
545 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
546 xmlFreeParserInputBuffer(reader->input);
547 xmlFree(reader);
548}
549
550/************************************************************************
551 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000552 * Methods for XmlTextReader *
553 * *
554 ************************************************************************/
555/**
556 * xmlTextReaderClose:
557 * @reader: the xmlTextReaderPtr used
558 *
559 * This method releases any resources allocated by the current instance
560 * changes the state to Closed and close any underlying input.
561 *
562 * Returns 0 or -1 in case of error
563 */
564int
565xmlTextReaderClose(xmlTextReaderPtr reader) {
566 if (reader == NULL)
567 return(-1);
568 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000569 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000570 reader->mode = XML_TEXTREADER_MODE_CLOSED;
571 if (reader->ctxt != NULL) {
572 if (reader->ctxt->myDoc != NULL) {
573 xmlFreeDoc(reader->ctxt->myDoc);
574 reader->ctxt->myDoc = NULL;
575 }
576 if (reader->allocs & XML_TEXTREADER_CTXT) {
577 xmlFreeParserCtxt(reader->ctxt);
578 reader->allocs -= XML_TEXTREADER_CTXT;
579 }
580 }
581 if (reader->sax != NULL) {
582 xmlFree(reader->sax);
583 reader->sax = NULL;
584 }
585 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
586 xmlFreeParserInputBuffer(reader->input);
587 reader->allocs -= XML_TEXTREADER_INPUT;
588 }
589 return(0);
590}
591
592/**
593 * xmlTextReaderGetAttributeNo:
594 * @reader: the xmlTextReaderPtr used
595 * @no: the zero-based index of the attribute relative to the containing element
596 *
597 * Provides the value of the attribute with the specified index relative
598 * to the containing element.
599 *
600 * Returns a string containing the value of the specified attribute, or NULL
601 * in case of error. The string must be deallocated by the caller.
602 */
603xmlChar *
604xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
605 xmlChar *ret;
606 int i;
607 xmlAttrPtr cur;
608 xmlNsPtr ns;
609
610 if (reader == NULL)
611 return(NULL);
612 if (reader->node == NULL)
613 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000614 if (reader->curnode != NULL)
615 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000616 /* TODO: handle the xmlDecl */
617 if (reader->node->type != XML_ELEMENT_NODE)
618 return(NULL);
619
620 ns = reader->node->nsDef;
621 for (i = 0;(i < no) && (ns != NULL);i++) {
622 ns = ns->next;
623 }
624 if (ns != NULL)
625 return(xmlStrdup(ns->href));
626
627 cur = reader->node->properties;
628 if (cur == NULL)
629 return(NULL);
630 for (;i < no;i++) {
631 cur = cur->next;
632 if (cur == NULL)
633 return(NULL);
634 }
635 /* TODO walk the DTD if present */
636
637 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
638 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
639 return(ret);
640}
641
642/**
643 * xmlTextReaderGetAttribute:
644 * @reader: the xmlTextReaderPtr used
645 * @name: the qualified name of the attribute.
646 *
647 * Provides the value of the attribute with the specified qualified name.
648 *
649 * Returns a string containing the value of the specified attribute, or NULL
650 * in case of error. The string must be deallocated by the caller.
651 */
652xmlChar *
653xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
654 xmlChar *prefix = NULL;
655 xmlChar *localname;
656 xmlNsPtr ns;
657 xmlChar *ret = NULL;
658
659 if ((reader == NULL) || (name == NULL))
660 return(NULL);
661 if (reader->node == NULL)
662 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000663 if (reader->curnode != NULL)
664 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000665
666 /* TODO: handle the xmlDecl */
667 if (reader->node->type != XML_ELEMENT_NODE)
668 return(NULL);
669
670 localname = xmlSplitQName2(name, &prefix);
671 if (localname == NULL)
672 return(xmlGetProp(reader->node, name));
673
674 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
675 if (ns != NULL)
676 ret = xmlGetNsProp(reader->node, localname, ns->href);
677
678 if (localname != NULL)
679 xmlFree(localname);
680 if (prefix != NULL)
681 xmlFree(prefix);
682 return(ret);
683}
684
685
686/**
687 * xmlTextReaderGetAttributeNs:
688 * @reader: the xmlTextReaderPtr used
689 * @localName: the local name of the attribute.
690 * @namespaceURI: the namespace URI of the attribute.
691 *
692 * Provides the value of the specified attribute
693 *
694 * Returns a string containing the value of the specified attribute, or NULL
695 * in case of error. The string must be deallocated by the caller.
696 */
697xmlChar *
698xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
699 const xmlChar *namespaceURI) {
700 if ((reader == NULL) || (localName == NULL))
701 return(NULL);
702 if (reader->node == NULL)
703 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000704 if (reader->curnode != NULL)
705 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +0000706
707 /* TODO: handle the xmlDecl */
708 if (reader->node->type != XML_ELEMENT_NODE)
709 return(NULL);
710
711 return(xmlGetNsProp(reader->node, localName, namespaceURI));
712}
713
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000714/**
715 * xmlTextReaderGetRemainder:
716 * @reader: the xmlTextReaderPtr used
717 *
718 * Method to get the remainder of the buffered XML. this method stops the
719 * parser, set its state to End Of File and return the input stream with
720 * what is left that the parser did not use.
721 *
722 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
723 * in case of error.
724 */
725xmlParserInputBufferPtr
726xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
727 xmlParserInputBufferPtr ret = NULL;
728
729 if (reader == NULL)
730 return(NULL);
731 if (reader->node == NULL)
732 return(NULL);
733
734 reader->node = NULL;
735 reader->curnode = NULL;
736 reader->mode = XML_TEXTREADER_MODE_EOF;
737 if (reader->ctxt != NULL) {
738 if (reader->ctxt->myDoc != NULL) {
739 xmlFreeDoc(reader->ctxt->myDoc);
740 reader->ctxt->myDoc = NULL;
741 }
742 if (reader->allocs & XML_TEXTREADER_CTXT) {
743 xmlFreeParserCtxt(reader->ctxt);
744 reader->allocs -= XML_TEXTREADER_CTXT;
745 }
746 }
747 if (reader->sax != NULL) {
748 xmlFree(reader->sax);
749 reader->sax = NULL;
750 }
751 if (reader->allocs & XML_TEXTREADER_INPUT) {
752 ret = reader->input;
753 reader->allocs -= XML_TEXTREADER_INPUT;
754 } else {
755 /*
756 * Hum, one may need to duplicate the data structure because
757 * without reference counting the input may be freed twice:
758 * - by the layer which allocated it.
759 * - by the layer to which would have been returned to.
760 */
761 TODO
762 return(NULL);
763 }
764 return(ret);
765}
766
767/**
768 * xmlTextReaderLookupNamespace:
769 * @reader: the xmlTextReaderPtr used
770 * @prefix: the prefix whose namespace URI is to be resolved. To return
771 * the default namespace, specify NULL
772 *
773 * Resolves a namespace prefix in the scope of the current element.
774 *
775 * Returns a string containing the namespace URI to which the prefix maps
776 * or NULL in case of error. The string must be deallocated by the caller.
777 */
778xmlChar *
779xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
780 xmlNsPtr ns;
781
782 if (reader == NULL)
783 return(NULL);
784 if (reader->node == NULL)
785 return(NULL);
786
787 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
788 if (ns == NULL)
789 return(NULL);
790 return(xmlStrdup(ns->href));
791}
792
793/**
794 * xmlTextReaderMoveToAttributeNo:
795 * @reader: the xmlTextReaderPtr used
796 * @no: the zero-based index of the attribute relative to the containing
797 * element.
798 *
799 * Moves the position of the current instance to the attribute with
800 * the specified index relative to the containing element.
801 *
802 * Returns 1 in case of success, -1 in case of error, 0 if not found
803 */
804int
805xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
806 int i;
807 xmlAttrPtr cur;
808 xmlNsPtr ns;
809
810 if (reader == NULL)
811 return(-1);
812 if (reader->node == NULL)
813 return(-1);
814 /* TODO: handle the xmlDecl */
815 if (reader->node->type != XML_ELEMENT_NODE)
816 return(-1);
817
818 reader->curnode = NULL;
819
820 ns = reader->node->nsDef;
821 for (i = 0;(i < no) && (ns != NULL);i++) {
822 ns = ns->next;
823 }
824 if (ns != NULL) {
825 reader->curnode = (xmlNodePtr) ns;
826 return(1);
827 }
828
829 cur = reader->node->properties;
830 if (cur == NULL)
831 return(0);
832 for (;i < no;i++) {
833 cur = cur->next;
834 if (cur == NULL)
835 return(0);
836 }
837 /* TODO walk the DTD if present */
838
839 reader->curnode = (xmlNodePtr) cur;
840 return(1);
841}
842
843/**
844 * xmlTextReaderMoveToAttribute:
845 * @reader: the xmlTextReaderPtr used
846 * @name: the qualified name of the attribute.
847 *
848 * Moves the position of the current instance to the attribute with
849 * the specified qualified name.
850 *
851 * Returns 1 in case of success, -1 in case of error, 0 if not found
852 */
853int
854xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
855 xmlChar *prefix = NULL;
856 xmlChar *localname;
857 xmlNsPtr ns;
858 xmlAttrPtr prop;
859
860 if ((reader == NULL) || (name == NULL))
861 return(-1);
862 if (reader->node == NULL)
863 return(-1);
864
865 /* TODO: handle the xmlDecl */
866 if (reader->node->type != XML_ELEMENT_NODE)
867 return(0);
868
869 localname = xmlSplitQName2(name, &prefix);
870 if (localname == NULL) {
871 /*
872 * Namespace default decl
873 */
874 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
875 ns = reader->node->nsDef;
876 while (ns != NULL) {
877 if (ns->prefix == NULL) {
878 reader->curnode = (xmlNodePtr) ns;
879 return(1);
880 }
881 ns = ns->next;
882 }
883 return(0);
884 }
885
886 prop = reader->node->properties;
887 while (prop != NULL) {
888 /*
889 * One need to have
890 * - same attribute names
891 * - and the attribute carrying that namespace
892 */
893 if ((xmlStrEqual(prop->name, name)) &&
894 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
895 reader->curnode = (xmlNodePtr) prop;
896 return(1);
897 }
898 prop = prop->next;
899 }
900 return(0);
901 }
902
903 /*
904 * Namespace default decl
905 */
906 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
907 ns = reader->node->nsDef;
908 while (ns != NULL) {
909 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
910 reader->curnode = (xmlNodePtr) ns;
911 goto found;
912 }
913 ns = ns->next;
914 }
915 goto not_found;
916 }
917 prop = reader->node->properties;
918 while (prop != NULL) {
919 /*
920 * One need to have
921 * - same attribute names
922 * - and the attribute carrying that namespace
923 */
924 if ((xmlStrEqual(prop->name, localname)) &&
925 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
926 reader->curnode = (xmlNodePtr) prop;
927 goto found;
928 }
929 prop = prop->next;
930 }
931not_found:
932 if (localname != NULL)
933 xmlFree(localname);
934 if (prefix != NULL)
935 xmlFree(prefix);
936 return(0);
937
938found:
939 if (localname != NULL)
940 xmlFree(localname);
941 if (prefix != NULL)
942 xmlFree(prefix);
943 return(1);
944}
945
946/**
947 * xmlTextReaderMoveToAttributeNs:
948 * @reader: the xmlTextReaderPtr used
949 * @localName: the local name of the attribute.
950 * @namespaceURI: the namespace URI of the attribute.
951 *
952 * Moves the position of the current instance to the attribute with the
953 * specified local name and namespace URI.
954 *
955 * Returns 1 in case of success, -1 in case of error, 0 if not found
956 */
957int
958xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
959 const xmlChar *localName, const xmlChar *namespaceURI) {
960 xmlAttrPtr prop;
961 xmlNodePtr node;
962
963 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
964 return(-1);
965 if (reader->node == NULL)
966 return(-1);
967 if (reader->node->type != XML_ELEMENT_NODE)
968 return(0);
969 node = reader->node;
970
971 /*
972 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
973 * namespace name associated to "xmlns"
974 */
975 prop = node->properties;
976 while (prop != NULL) {
977 /*
978 * One need to have
979 * - same attribute names
980 * - and the attribute carrying that namespace
981 */
982 if (xmlStrEqual(prop->name, localName) &&
983 ((prop->ns != NULL) &&
984 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
985 reader->curnode = (xmlNodePtr) prop;
986 return(1);
987 }
988 prop = prop->next;
989 }
990 return(0);
991}
992
993/**
994 * xmlTextReaderMoveToFirstAttribute:
995 * @reader: the xmlTextReaderPtr used
996 *
997 * Moves the position of the current instance to the first attribute
998 * associated with the current node.
999 *
1000 * Returns 1 in case of success, -1 in case of error, 0 if not found
1001 */
1002int
1003xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
1004 if (reader == NULL)
1005 return(-1);
1006 if (reader->node == NULL)
1007 return(-1);
1008 if (reader->node->type != XML_ELEMENT_NODE)
1009 return(0);
1010
1011 if (reader->node->nsDef != NULL) {
1012 reader->curnode = (xmlNodePtr) reader->node->nsDef;
1013 return(1);
1014 }
1015 if (reader->node->properties != NULL) {
1016 reader->curnode = (xmlNodePtr) reader->node->properties;
1017 return(1);
1018 }
1019 return(0);
1020}
1021
1022/**
1023 * xmlTextReaderMoveToNextAttribute:
1024 * @reader: the xmlTextReaderPtr used
1025 *
1026 * Moves the position of the current instance to the next attribute
1027 * associated with the current node.
1028 *
1029 * Returns 1 in case of success, -1 in case of error, 0 if not found
1030 */
1031int
1032xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
1033 if (reader == NULL)
1034 return(-1);
1035 if (reader->node == NULL)
1036 return(-1);
1037 if (reader->node->type != XML_ELEMENT_NODE)
1038 return(0);
1039 if (reader->curnode == NULL)
1040 return(xmlTextReaderMoveToFirstAttribute(reader));
1041
1042 if (reader->curnode->type == XML_NAMESPACE_DECL) {
1043 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
1044 if (ns->next != NULL) {
1045 reader->curnode = (xmlNodePtr) ns->next;
1046 return(1);
1047 }
1048 if (reader->node->properties != NULL) {
1049 reader->curnode = (xmlNodePtr) reader->node->properties;
1050 return(1);
1051 }
1052 return(0);
1053 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
1054 (reader->curnode->next != NULL)) {
1055 reader->curnode = reader->curnode->next;
1056 return(1);
1057 }
1058 return(0);
1059}
1060
1061/**
1062 * xmlTextReaderMoveToElement:
1063 * @reader: the xmlTextReaderPtr used
1064 *
1065 * Moves the position of the current instance to the node that
1066 * contains the current Attribute node.
1067 *
1068 * Returns 1 in case of success, -1 in case of error, 0 if not moved
1069 */
1070int
1071xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
1072 if (reader == NULL)
1073 return(-1);
1074 if (reader->node == NULL)
1075 return(-1);
1076 if (reader->node->type != XML_ELEMENT_NODE)
1077 return(0);
1078 if (reader->curnode != NULL) {
1079 reader->curnode = NULL;
1080 return(1);
1081 }
1082 return(0);
1083}
1084
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001085/************************************************************************
1086 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001087 * Acces API to the current node *
1088 * *
1089 ************************************************************************/
1090/**
1091 * xmlTextReaderAttributeCount:
1092 * @reader: the xmlTextReaderPtr used
1093 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00001094 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001095 *
1096 * Returns 0 i no attributes, -1 in case of error or the attribute count
1097 */
1098int
1099xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
1100 int ret;
1101 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00001102 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001103 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001104
1105 if (reader == NULL)
1106 return(-1);
1107 if (reader->node == NULL)
1108 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001109
1110 if (reader->curnode != NULL)
1111 node = reader->curnode;
1112 else
1113 node = reader->node;
1114
1115 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001116 return(0);
1117 if ((reader->state == XML_TEXTREADER_END) ||
1118 (reader->state == XML_TEXTREADER_BACKTRACK))
1119 return(0);
1120 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001121 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001122 while (attr != NULL) {
1123 ret++;
1124 attr = attr->next;
1125 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001126 ns = node->nsDef;
1127 while (ns != NULL) {
1128 ret++;
1129 ns = ns->next;
1130 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001131 return(ret);
1132}
1133
1134/**
1135 * xmlTextReaderNodeType:
1136 * @reader: the xmlTextReaderPtr used
1137 *
1138 * Get the node type of the current node
1139 * Reference:
1140 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
1141 *
1142 * Returns the xmlNodeType of the current node or -1 in case of error
1143 */
1144int
1145xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001146 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001147 if (reader == NULL)
1148 return(-1);
1149 if (reader->node == NULL)
1150 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001151 if (reader->curnode != NULL)
1152 node = reader->curnode;
1153 else
1154 node = reader->node;
1155 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001156 case XML_ELEMENT_NODE:
1157 if ((reader->state == XML_TEXTREADER_END) ||
1158 (reader->state == XML_TEXTREADER_BACKTRACK))
1159 return(15);
1160 return(1);
1161 case XML_ATTRIBUTE_NODE:
1162 return(2);
1163 case XML_TEXT_NODE:
1164 return(3); /* TODO: SignificantWhitespace == 14 Whitespace == 13 */
1165 case XML_CDATA_SECTION_NODE:
1166 return(4);
1167 case XML_ENTITY_REF_NODE:
1168 return(5);
1169 case XML_ENTITY_NODE:
1170 return(6);
1171 case XML_PI_NODE:
1172 return(7);
1173 case XML_COMMENT_NODE:
1174 return(8);
1175 case XML_DOCUMENT_NODE:
1176 case XML_HTML_DOCUMENT_NODE:
1177#ifdef LIBXML_DOCB_ENABLED
1178 case XML_DOCB_DOCUMENT_NODE:
1179#endif
1180 return(9);
1181 case XML_DOCUMENT_FRAG_NODE:
1182 return(11);
1183 case XML_NOTATION_NODE:
1184 return(12);
1185 case XML_DOCUMENT_TYPE_NODE:
1186 case XML_DTD_NODE:
1187 return(10);
1188
1189 case XML_ELEMENT_DECL:
1190 case XML_ATTRIBUTE_DECL:
1191 case XML_ENTITY_DECL:
1192 case XML_NAMESPACE_DECL:
1193 case XML_XINCLUDE_START:
1194 case XML_XINCLUDE_END:
1195 return(0);
1196 }
1197 return(-1);
1198}
1199
1200/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00001201 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001202 * @reader: the xmlTextReaderPtr used
1203 *
1204 * Check if the current node is empty
1205 *
1206 * Returns 1 if empty, 0 if not and -1 in case of error
1207 */
1208int
1209xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
1210 if ((reader == NULL) || (reader->node == NULL))
1211 return(-1);
1212 if (reader->node->children != NULL)
1213 return(0);
1214 if ((reader->state == XML_TEXTREADER_EMPTY) ||
1215 (reader->state == XML_TEXTREADER_BACKTRACK))
1216 return(1);
1217 return(0);
1218}
1219
1220/**
1221 * xmlTextReaderLocalName:
1222 * @reader: the xmlTextReaderPtr used
1223 *
1224 * The local name of the node.
1225 *
1226 * Returns the local name or NULL if not available
1227 */
1228xmlChar *
1229xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001230 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001231 if ((reader == NULL) || (reader->node == NULL))
1232 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001233 if (reader->curnode != NULL)
1234 node = reader->curnode;
1235 else
1236 node = reader->node;
1237 if (node->type == XML_NAMESPACE_DECL) {
1238 xmlNsPtr ns = (xmlNsPtr) node;
1239 if (ns->prefix == NULL)
1240 return(xmlStrdup(BAD_CAST "xmlns"));
1241 else
1242 return(xmlStrdup(ns->prefix));
1243 }
1244 if ((node->type != XML_ELEMENT_NODE) &&
1245 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001246 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001247 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001248}
1249
1250/**
1251 * xmlTextReaderName:
1252 * @reader: the xmlTextReaderPtr used
1253 *
1254 * The qualified name of the node, equal to Prefix :LocalName.
1255 *
1256 * Returns the local name or NULL if not available
1257 */
1258xmlChar *
1259xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001260 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001261 xmlChar *ret;
1262
1263 if ((reader == NULL) || (reader->node == NULL))
1264 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001265 if (reader->curnode != NULL)
1266 node = reader->curnode;
1267 else
1268 node = reader->node;
1269 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001270 case XML_ELEMENT_NODE:
1271 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001272 if ((node->ns == NULL) ||
1273 (node->ns->prefix == NULL))
1274 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001275
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001276 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001277 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001278 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001279 return(ret);
1280 case XML_TEXT_NODE:
1281 return(xmlStrdup(BAD_CAST "#text"));
1282 case XML_CDATA_SECTION_NODE:
1283 return(xmlStrdup(BAD_CAST "#cdata-section"));
1284 case XML_ENTITY_NODE:
1285 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001286 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001287 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001288 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001289 case XML_COMMENT_NODE:
1290 return(xmlStrdup(BAD_CAST "#comment"));
1291 case XML_DOCUMENT_NODE:
1292 case XML_HTML_DOCUMENT_NODE:
1293#ifdef LIBXML_DOCB_ENABLED
1294 case XML_DOCB_DOCUMENT_NODE:
1295#endif
1296 return(xmlStrdup(BAD_CAST "#document"));
1297 case XML_DOCUMENT_FRAG_NODE:
1298 return(xmlStrdup(BAD_CAST "#document-fragment"));
1299 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001300 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001301 case XML_DOCUMENT_TYPE_NODE:
1302 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001303 return(xmlStrdup(node->name));
1304 case XML_NAMESPACE_DECL: {
1305 xmlNsPtr ns = (xmlNsPtr) node;
1306
1307 ret = xmlStrdup(BAD_CAST "xmlns");
1308 if (ns->prefix == NULL)
1309 return(ret);
1310 ret = xmlStrcat(ret, BAD_CAST ":");
1311 ret = xmlStrcat(ret, ns->prefix);
1312 return(ret);
1313 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001314
1315 case XML_ELEMENT_DECL:
1316 case XML_ATTRIBUTE_DECL:
1317 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001318 case XML_XINCLUDE_START:
1319 case XML_XINCLUDE_END:
1320 return(NULL);
1321 }
1322 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001323}
1324
1325/**
1326 * xmlTextReaderPrefix:
1327 * @reader: the xmlTextReaderPtr used
1328 *
1329 * A shorthand reference to the namespace associated with the node.
1330 *
1331 * Returns the prefix or NULL if not available
1332 */
1333xmlChar *
1334xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001335 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001336 if ((reader == NULL) || (reader->node == NULL))
1337 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001338 if (reader->curnode != NULL)
1339 node = reader->curnode;
1340 else
1341 node = reader->node;
1342 if (node->type == XML_NAMESPACE_DECL) {
1343 xmlNsPtr ns = (xmlNsPtr) node;
1344 if (ns->prefix == NULL)
1345 return(NULL);
1346 return(xmlStrdup(BAD_CAST "xmlns"));
1347 }
1348 if ((node->type != XML_ELEMENT_NODE) &&
1349 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001350 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001351 if ((node->ns != NULL) || (node->ns->prefix != NULL))
1352 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001353 return(NULL);
1354}
1355
1356/**
1357 * xmlTextReaderNamespaceUri:
1358 * @reader: the xmlTextReaderPtr used
1359 *
1360 * The URI defining the namespace associated with the node.
1361 *
1362 * Returns the namespace URI or NULL if not available
1363 */
1364xmlChar *
1365xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001366 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001367 if ((reader == NULL) || (reader->node == NULL))
1368 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001369 if (reader->curnode != NULL)
1370 node = reader->curnode;
1371 else
1372 node = reader->node;
1373 if (node->type == XML_NAMESPACE_DECL) {
1374 xmlNsPtr ns = (xmlNsPtr) node;
1375 return(xmlStrdup(ns->href));
1376 }
1377 if ((node->type != XML_ELEMENT_NODE) &&
1378 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001379 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001380 if (node->ns != NULL)
1381 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001382 return(NULL);
1383}
1384
1385/**
1386 * xmlTextReaderBaseUri:
1387 * @reader: the xmlTextReaderPtr used
1388 *
1389 * The base URI of the node.
1390 *
1391 * Returns the base URI or NULL if not available
1392 */
1393xmlChar *
1394xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
1395 if ((reader == NULL) || (reader->node == NULL))
1396 return(NULL);
1397 return(xmlNodeGetBase(NULL, reader->node));
1398}
1399
1400/**
1401 * xmlTextReaderDepth:
1402 * @reader: the xmlTextReaderPtr used
1403 *
1404 * The depth of the node in the tree.
1405 *
1406 * Returns the depth or -1 in case of error
1407 */
1408int
1409xmlTextReaderDepth(xmlTextReaderPtr reader) {
1410 if (reader == NULL)
1411 return(-1);
1412 if (reader->node == NULL)
1413 return(0);
1414
1415 return(reader->depth);
1416}
1417
1418/**
1419 * xmlTextReaderHasAttributes:
1420 * @reader: the xmlTextReaderPtr used
1421 *
1422 * Whether the node has attributes.
1423 *
1424 * Returns 1 if true, 0 if false, and -1 in case or error
1425 */
1426int
1427xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001428 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001429 if (reader == NULL)
1430 return(-1);
1431 if (reader->node == NULL)
1432 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001433 if (reader->curnode != NULL)
1434 node = reader->curnode;
1435 else
1436 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001437
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001438 if ((node->type == XML_ELEMENT_NODE) &&
1439 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001440 return(1);
1441 /* TODO: handle the xmlDecl */
1442 return(0);
1443}
1444
1445/**
1446 * xmlTextReaderHasValue:
1447 * @reader: the xmlTextReaderPtr used
1448 *
1449 * Whether the node can have a text value.
1450 *
1451 * Returns 1 if true, 0 if false, and -1 in case or error
1452 */
1453int
1454xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001455 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001456 if (reader == NULL)
1457 return(-1);
1458 if (reader->node == NULL)
1459 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001460 if (reader->curnode != NULL)
1461 node = reader->curnode;
1462 else
1463 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001464
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001465 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001466 case XML_ATTRIBUTE_NODE:
1467 case XML_TEXT_NODE:
1468 case XML_CDATA_SECTION_NODE:
1469 case XML_PI_NODE:
1470 case XML_COMMENT_NODE:
1471 return(1);
1472 default:
1473 return(0);
1474 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001475 return(0);
1476}
1477
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001478/**
1479 * xmlTextReaderValue:
1480 * @reader: the xmlTextReaderPtr used
1481 *
1482 * Provides the text value of the node if present
1483 *
1484 * Returns the string or NULL if not available. The retsult must be deallocated
1485 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001486 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001487xmlChar *
1488xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001489 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001490 if (reader == NULL)
1491 return(NULL);
1492 if (reader->node == NULL)
1493 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001494 if (reader->curnode != NULL)
1495 node = reader->curnode;
1496 else
1497 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001498
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001499 switch (node->type) {
1500 case XML_NAMESPACE_DECL:
1501 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001502 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001503 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001504
1505 if (attr->parent != NULL)
1506 return (xmlNodeListGetString
1507 (attr->parent->doc, attr->children, 1));
1508 else
1509 return (xmlNodeListGetString(NULL, attr->children, 1));
1510 break;
1511 }
1512 case XML_TEXT_NODE:
1513 case XML_CDATA_SECTION_NODE:
1514 case XML_PI_NODE:
1515 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001516 if (node->content != NULL)
1517 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00001518 default:
1519 return(NULL);
1520 }
1521 return(NULL);
1522}
1523
1524/**
1525 * xmlTextReaderIsDefault:
1526 * @reader: the xmlTextReaderPtr used
1527 *
1528 * Whether an Attribute node was generated from the default value
1529 * defined in the DTD or schema.
1530 *
1531 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
1532 */
1533int
1534xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
1535 if (reader == NULL)
1536 return(-1);
1537 return(0);
1538}
1539
1540/**
1541 * xmlTextReaderQuoteChar:
1542 * @reader: the xmlTextReaderPtr used
1543 *
1544 * The quotation mark character used to enclose the value of an attribute.
1545 *
1546 * Returns " or ' and -1 in case of error
1547 */
1548int
1549xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
1550 if (reader == NULL)
1551 return(-1);
1552 /* TODO maybe lookup the attribute value for " first */
1553 return((int) '"');
1554}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001555
1556/**
1557 * xmlTextReaderXmlLang:
1558 * @reader: the xmlTextReaderPtr used
1559 *
1560 * The xml:lang scope within which the node resides.
1561 *
1562 * Returns the xml:lang value or NULL if none exists.
1563 */
1564xmlChar *
1565xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
1566 if (reader == NULL)
1567 return(NULL);
1568 if (reader->node == NULL)
1569 return(NULL);
1570 return(xmlNodeGetLang(reader->node));
1571}
1572
Daniel Veillard67df8092002-12-16 22:04:11 +00001573/**
1574 * xmlTextReaderNormalization:
1575 * @reader: the xmlTextReaderPtr used
1576 *
1577 * The value indicating whether to normalize white space and attribute values.
1578 * Since attribute value and end of line normalizations are a MUST in the XML
1579 * specification only the value true is accepted. The broken bahaviour of
1580 * accepting out of range character entities like &#0; is of course not
1581 * supported either.
1582 *
1583 * Returns 1 or -1 in case of error.
1584 */
1585int
1586xmlTextReaderNormalization(xmlTextReaderPtr reader) {
1587 if (reader == NULL)
1588 return(-1);
1589 return(1);
1590}
1591