blob: 6efb27fac3ac2896440cde6e24a4601fe8b4ef9c [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillard67df8092002-12-16 22:04:11 +00004 * NOTE:
5 * XmlTextReader.Normalization Property won't be supported, since
6 * it makes the parser non compliant to the XML recommendation
7 *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00008 * See Copyright for the status of this software.
9 *
10 * daniel@veillard.com
11 */
12
Daniel Veillard7704fb12003-01-03 16:19:51 +000013/*
14 * TODOs:
Daniel Veillard7704fb12003-01-03 16:19:51 +000015 * - provide an API to preserve part of the tree
16 * - Streaming XInclude support
Daniel Veillard067bae52003-01-05 01:27:54 +000017 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000018 * - setting(s) for NoBlanks
19 * - performances and tuning ...
20 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#define IN_LIBXML
22#include "libxml.h"
23
Daniel Veillard81273902003-09-30 00:43:48 +000024#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000025#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000026#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000027
28#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#include <libxml/xmlmemory.h>
36#include <libxml/xmlIO.h>
37#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000038#include <libxml/parserInternals.h>
Daniel Veillardf4e55762003-04-15 23:32:22 +000039#include <libxml/relaxng.h>
Daniel Veillard198c1bf2003-10-20 17:07:41 +000040#include <libxml/uri.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000041
42/* #define DEBUG_CALLBACKS */
43/* #define DEBUG_READER */
44
45/**
46 * TODO:
47 *
48 * macro to flag unimplemented blocks
49 */
50#define TODO \
51 xmlGenericError(xmlGenericErrorContext, \
52 "Unimplemented block at %s:%d\n", \
53 __FILE__, __LINE__);
54
55#ifdef DEBUG_READER
56#define DUMP_READER xmlTextReaderDebug(reader);
57#else
58#define DUMP_READER
59#endif
60
Daniel Veillarda880b122003-04-21 21:36:41 +000061#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000062/************************************************************************
63 * *
64 * The parser: maps the Text Reader API on top of the existing *
65 * parsing routines building a tree *
66 * *
67 ************************************************************************/
68
69#define XML_TEXTREADER_INPUT 1
70#define XML_TEXTREADER_CTXT 2
71
72typedef enum {
Daniel Veillard67df8092002-12-16 22:04:11 +000073 XML_TEXTREADER_MODE_INITIAL = 0,
74 XML_TEXTREADER_MODE_INTERACTIVE = 1,
75 XML_TEXTREADER_MODE_ERROR = 2,
76 XML_TEXTREADER_MODE_EOF =3,
77 XML_TEXTREADER_MODE_CLOSED = 4,
78 XML_TEXTREADER_MODE_READING = 5
Daniel Veillarde1ca5032002-12-09 14:13:43 +000079} xmlTextReaderMode;
80
81typedef enum {
82 XML_TEXTREADER_NONE = -1,
83 XML_TEXTREADER_START= 0,
84 XML_TEXTREADER_ELEMENT= 1,
85 XML_TEXTREADER_END= 2,
86 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +000087 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +000088 XML_TEXTREADER_DONE= 5,
89 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +000090} xmlTextReaderState;
91
Daniel Veillardf4e55762003-04-15 23:32:22 +000092typedef enum {
93 XML_TEXTREADER_NOT_VALIDATE = 0,
94 XML_TEXTREADER_VALIDATE_DTD = 1,
95 XML_TEXTREADER_VALIDATE_RNG = 2
96} xmlTextReaderValidate;
97
Daniel Veillarde1ca5032002-12-09 14:13:43 +000098struct _xmlTextReader {
99 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000100 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000101 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000102 int allocs; /* what structure were deallocated */
103 xmlTextReaderState state;
104 xmlParserCtxtPtr ctxt; /* the parser context */
105 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
106 xmlParserInputBufferPtr input; /* the input */
107 startElementSAXFunc startElement;/* initial SAX callbacks */
108 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000109 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000110 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000111 charactersSAXFunc characters;
112 cdataBlockSAXFunc cdataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000113 unsigned int base; /* base of the segment in the input */
114 unsigned int cur; /* current position in the input */
115 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000116 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000117 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000118 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000119 int preserve;/* preserve the resulting document */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000120 xmlBufferPtr buffer; /* used to return const xmlChar * */
121 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000122
123 /* entity stack when traversing entities content */
124 xmlNodePtr ent; /* Current Entity Ref Node */
125 int entNr; /* Depth of the entities stack */
126 int entMax; /* Max depth of the entities stack */
127 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000128
129 /* error handling */
130 xmlTextReaderErrorFunc errorFunc; /* callback function */
131 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000132
133#ifdef LIBXML_SCHEMAS_ENABLED
134 /* Handling of RelaxNG validation */
135 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
136 xmlRelaxNGValidCtxtPtr rngValidCtxt; /* The Relax NG validation context */
137 int rngValidErrors; /* The number of errors detected */
138 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
139#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000140};
141
Daniel Veillard067bae52003-01-05 01:27:54 +0000142static const char *xmlTextReaderIsEmpty = "This element is empty";
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000143static const char *xmlTextReaderIsEmptyPreserved = "Preserve this element";
144static const char *xmlTextReaderIsPreserved = "Preserve this element";
Daniel Veillard067bae52003-01-05 01:27:54 +0000145
Daniel Veillarde72c5082003-09-19 12:44:05 +0000146/**
147 * CONSTSTR:
148 *
149 * Macro used to return an interned string
150 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000151#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
152#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
153
154static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
155static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000156
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000157/************************************************************************
158 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000159 * Our own version of the freeing routines as we recycle nodes *
160 * *
161 ************************************************************************/
162/**
163 * DICT_FREE:
164 * @str: a string
165 *
166 * Free a string if it is not owned by the "dict" dictionnary in the
167 * current scope
168 */
169#define DICT_FREE(str) \
170 if ((str) && ((!dict) || \
171 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
172 xmlFree((char *)(str));
173
174static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
175static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
176
177/**
178 * xmlTextReaderFreeProp:
179 * @reader: the xmlTextReaderPtr used
180 * @cur: the node
181 *
182 * Free a node.
183 */
184static void
185xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
186 xmlDictPtr dict;
187
188 dict = reader->ctxt->dict;
189 if (cur == NULL) return;
190
191 /* Check for ID removal -> leading to invalid references ! */
192 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
193 ((cur->parent->doc->intSubset != NULL) ||
194 (cur->parent->doc->extSubset != NULL))) {
195 if (xmlIsID(cur->parent->doc, cur->parent, cur))
196 xmlRemoveID(cur->parent->doc, cur);
197 }
198 if (cur->children != NULL)
199 xmlTextReaderFreeNodeList(reader, cur->children);
200
201 DICT_FREE(cur->name);
202 if ((reader != NULL) && (reader->ctxt != NULL) &&
203 (reader->ctxt->freeAttrsNr < 100)) {
204 cur->next = reader->ctxt->freeAttrs;
205 reader->ctxt->freeAttrs = cur;
206 reader->ctxt->freeAttrsNr++;
207 } else {
208 xmlFree(cur);
209 }
210}
211
212/**
213 * xmlTextReaderFreePropList:
214 * @reader: the xmlTextReaderPtr used
215 * @cur: the first property in the list
216 *
217 * Free a property and all its siblings, all the children are freed too.
218 */
219static void
220xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
221 xmlAttrPtr next;
222 if (cur == NULL) return;
223 while (cur != NULL) {
224 next = cur->next;
225 xmlTextReaderFreeProp(reader, cur);
226 cur = next;
227 }
228}
229
230/**
231 * xmlTextReaderFreeNodeList:
232 * @reader: the xmlTextReaderPtr used
233 * @cur: the first node in the list
234 *
235 * Free a node and all its siblings, this is a recursive behaviour, all
236 * the children are freed too.
237 */
238static void
239xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
240 xmlNodePtr next;
241 xmlDictPtr dict;
242
243 dict = reader->ctxt->dict;
244 if (cur == NULL) return;
245 if (cur->type == XML_NAMESPACE_DECL) {
246 xmlFreeNsList((xmlNsPtr) cur);
247 return;
248 }
249 if ((cur->type == XML_DOCUMENT_NODE) ||
250 (cur->type == XML_HTML_DOCUMENT_NODE)) {
251 xmlFreeDoc((xmlDocPtr) cur);
252 return;
253 }
254 while (cur != NULL) {
255 next = cur->next;
256 /* unroll to speed up freeing the document */
257 if (cur->type != XML_DTD_NODE) {
258
259 if ((cur->children != NULL) &&
260 (cur->type != XML_ENTITY_REF_NODE))
261 xmlTextReaderFreeNodeList(reader, cur->children);
262 if (((cur->type == XML_ELEMENT_NODE) ||
263 (cur->type == XML_XINCLUDE_START) ||
264 (cur->type == XML_XINCLUDE_END)) &&
265 (cur->properties != NULL))
266 xmlTextReaderFreePropList(reader, cur->properties);
267 if ((cur->type != XML_ELEMENT_NODE) &&
268 (cur->type != XML_XINCLUDE_START) &&
269 (cur->type != XML_XINCLUDE_END) &&
270 (cur->type != XML_ENTITY_REF_NODE)) {
271 DICT_FREE(cur->content);
272 }
273 if (((cur->type == XML_ELEMENT_NODE) ||
274 (cur->type == XML_XINCLUDE_START) ||
275 (cur->type == XML_XINCLUDE_END)) &&
276 (cur->nsDef != NULL))
277 xmlFreeNsList(cur->nsDef);
278
279 /*
280 * we don't free element names here they are interned now
281 */
282 if ((cur->type != XML_TEXT_NODE) &&
283 (cur->type != XML_COMMENT_NODE))
284 DICT_FREE(cur->name);
285 if (((cur->type == XML_ELEMENT_NODE) ||
286 (cur->type == XML_TEXT_NODE)) &&
287 (reader != NULL) && (reader->ctxt != NULL) &&
288 (reader->ctxt->freeElemsNr < 100)) {
289 cur->next = reader->ctxt->freeElems;
290 reader->ctxt->freeElems = cur;
291 reader->ctxt->freeElemsNr++;
292 } else {
293 xmlFree(cur);
294 }
295 }
296 cur = next;
297 }
298}
299
300/**
301 * xmlTextReaderFreeNode:
302 * @reader: the xmlTextReaderPtr used
303 * @cur: the node
304 *
305 * Free a node, this is a recursive behaviour, all the children are freed too.
306 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
307 */
308static void
309xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
310 xmlDictPtr dict;
311
312 dict = reader->ctxt->dict;
313 if (cur->type == XML_DTD_NODE) {
314 xmlFreeDtd((xmlDtdPtr) cur);
315 return;
316 }
317 if (cur->type == XML_NAMESPACE_DECL) {
318 xmlFreeNs((xmlNsPtr) cur);
319 return;
320 }
321 if (cur->type == XML_ATTRIBUTE_NODE) {
322 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
323 return;
324 }
325
326 if ((cur->children != NULL) &&
327 (cur->type != XML_ENTITY_REF_NODE))
328 xmlTextReaderFreeNodeList(reader, cur->children);
329 if (((cur->type == XML_ELEMENT_NODE) ||
330 (cur->type == XML_XINCLUDE_START) ||
331 (cur->type == XML_XINCLUDE_END)) &&
332 (cur->properties != NULL))
333 xmlTextReaderFreePropList(reader, cur->properties);
334 if ((cur->type != XML_ELEMENT_NODE) &&
335 (cur->type != XML_XINCLUDE_START) &&
336 (cur->type != XML_XINCLUDE_END) &&
337 (cur->type != XML_ENTITY_REF_NODE)) {
338 DICT_FREE(cur->content);
339 }
340 if (((cur->type == XML_ELEMENT_NODE) ||
341 (cur->type == XML_XINCLUDE_START) ||
342 (cur->type == XML_XINCLUDE_END)) &&
343 (cur->nsDef != NULL))
344 xmlFreeNsList(cur->nsDef);
345
346 /*
347 * we don't free names here they are interned now
348 */
349 if ((cur->type != XML_TEXT_NODE) &&
350 (cur->type != XML_COMMENT_NODE))
351 DICT_FREE(cur->name);
352 if (((cur->type == XML_ELEMENT_NODE) ||
353 (cur->type == XML_TEXT_NODE)) &&
354 (reader != NULL) && (reader->ctxt != NULL) &&
355 (reader->ctxt->freeElemsNr < 100)) {
356 cur->next = reader->ctxt->freeElems;
357 reader->ctxt->freeElems = cur;
358 reader->ctxt->freeElemsNr++;
359 } else {
360 xmlFree(cur);
361 }
362}
363
364/**
365 * xmlTextReaderFreeDoc:
366 * @reader: the xmlTextReaderPtr used
367 * @cur: pointer to the document
368 *
369 * Free up all the structures used by a document, tree included.
370 */
371static void
372xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
373 xmlDtdPtr extSubset, intSubset;
374
375 if (cur == NULL) return;
376
377 /*
378 * Do this before freeing the children list to avoid ID lookups
379 */
380 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
381 cur->ids = NULL;
382 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
383 cur->refs = NULL;
384 extSubset = cur->extSubset;
385 intSubset = cur->intSubset;
386 if (intSubset == extSubset)
387 extSubset = NULL;
388 if (extSubset != NULL) {
389 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
390 cur->extSubset = NULL;
391 xmlFreeDtd(extSubset);
392 }
393 if (intSubset != NULL) {
394 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
395 cur->intSubset = NULL;
396 xmlFreeDtd(intSubset);
397 }
398
399 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
400
401 if (cur->version != NULL) xmlFree((char *) cur->version);
402 if (cur->name != NULL) xmlFree((char *) cur->name);
403 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
404 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
405 if (cur->URL != NULL) xmlFree((char *) cur->URL);
406 xmlFree(cur);
407}
408
409/************************************************************************
410 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000411 * The reader core parser *
412 * *
413 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000414#ifdef DEBUG_READER
415static void
416xmlTextReaderDebug(xmlTextReaderPtr reader) {
417 if ((reader == NULL) || (reader->ctxt == NULL)) {
418 fprintf(stderr, "xmlTextReader NULL\n");
419 return;
420 }
421 fprintf(stderr, "xmlTextReader: state %d depth %d ",
422 reader->state, reader->depth);
423 if (reader->node == NULL) {
424 fprintf(stderr, "node = NULL\n");
425 } else {
426 fprintf(stderr, "node %s\n", reader->node->name);
427 }
428 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
429 reader->base, reader->cur, reader->ctxt->nodeNr);
430 if (reader->input->buffer == NULL) {
431 fprintf(stderr, "buffer is NULL\n");
432 } else {
433#ifdef LIBXML_DEBUG_ENABLED
434 xmlDebugDumpString(stderr,
435 &reader->input->buffer->content[reader->cur]);
436#endif
437 fprintf(stderr, "\n");
438 }
439}
440#endif
441
442/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000443 * xmlTextReaderEntPush:
444 * @reader: the xmlTextReaderPtr used
445 * @value: the entity reference node
446 *
447 * Pushes a new entity reference node on top of the entities stack
448 *
449 * Returns 0 in case of error, the index in the stack otherwise
450 */
451static int
452xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
453{
454 if (reader->entMax <= 0) {
455 reader->entMax = 10;
456 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
457 sizeof(reader->entTab[0]));
458 if (reader->entTab == NULL) {
459 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
460 return (0);
461 }
462 }
463 if (reader->entNr >= reader->entMax) {
464 reader->entMax *= 2;
465 reader->entTab =
466 (xmlNodePtr *) xmlRealloc(reader->entTab,
467 reader->entMax *
468 sizeof(reader->entTab[0]));
469 if (reader->entTab == NULL) {
470 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
471 return (0);
472 }
473 }
474 reader->entTab[reader->entNr] = value;
475 reader->ent = value;
476 return (reader->entNr++);
477}
478
479/**
480 * xmlTextReaderEntPop:
481 * @reader: the xmlTextReaderPtr used
482 *
483 * Pops the top element entity from the entities stack
484 *
485 * Returns the entity just removed
486 */
487static xmlNodePtr
488xmlTextReaderEntPop(xmlTextReaderPtr reader)
489{
490 xmlNodePtr ret;
491
492 if (reader->entNr <= 0)
493 return (0);
494 reader->entNr--;
495 if (reader->entNr > 0)
496 reader->ent = reader->entTab[reader->entNr - 1];
497 else
498 reader->ent = NULL;
499 ret = reader->entTab[reader->entNr];
500 reader->entTab[reader->entNr] = 0;
501 return (ret);
502}
503
504/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000505 * xmlTextReaderStartElement:
506 * @ctx: the user data (XML parser context)
507 * @fullname: The element name, including namespace prefix
508 * @atts: An array of name/value attributes pairs, NULL terminated
509 *
510 * called when an opening tag has been processed.
511 */
512static void
513xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
514 const xmlChar **atts) {
515 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
516 xmlTextReaderPtr reader = ctxt->_private;
517
518#ifdef DEBUG_CALLBACKS
519 printf("xmlTextReaderStartElement(%s)\n", fullname);
520#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000521 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000522 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000523 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
524 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
525 (ctxt->input->cur[1] == '>'))
526 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000527 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000528 if (reader != NULL)
529 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000530}
531
532/**
533 * xmlTextReaderEndElement:
534 * @ctx: the user data (XML parser context)
535 * @fullname: The element name, including namespace prefix
536 *
537 * called when an ending tag has been processed.
538 */
539static void
540xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
541 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
542 xmlTextReaderPtr reader = ctxt->_private;
543
544#ifdef DEBUG_CALLBACKS
545 printf("xmlTextReaderEndElement(%s)\n", fullname);
546#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000547 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000548 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000549 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000550}
551
552/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000553 * xmlTextReaderStartElementNs:
554 * @ctx: the user data (XML parser context)
555 * @localname: the local name of the element
556 * @prefix: the element namespace prefix if available
557 * @URI: the element namespace name if available
558 * @nb_namespaces: number of namespace definitions on that node
559 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
560 * @nb_attributes: the number of attributes on that node
561 * nb_defaulted: the number of defaulted attributes.
562 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
563 * attribute values.
564 *
565 * called when an opening tag has been processed.
566 */
567static void
568xmlTextReaderStartElementNs(void *ctx,
569 const xmlChar *localname,
570 const xmlChar *prefix,
571 const xmlChar *URI,
572 int nb_namespaces,
573 const xmlChar **namespaces,
574 int nb_attributes,
575 int nb_defaulted,
576 const xmlChar **attributes)
577{
578 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
579 xmlTextReaderPtr reader = ctxt->_private;
580
581#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000582 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000583#endif
584 if ((reader != NULL) && (reader->startElementNs != NULL)) {
585 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
586 namespaces, nb_attributes, nb_defaulted,
587 attributes);
588 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
589 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
590 (ctxt->input->cur[1] == '>'))
591 ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
592 }
593 if (reader != NULL)
594 reader->state = XML_TEXTREADER_ELEMENT;
595}
596
597/**
598 * xmlTextReaderEndElementNs:
599 * @ctx: the user data (XML parser context)
600 * @localname: the local name of the element
601 * @prefix: the element namespace prefix if available
602 * @URI: the element namespace name if available
603 *
604 * called when an ending tag has been processed.
605 */
606static void
607xmlTextReaderEndElementNs(void *ctx,
608 const xmlChar * localname,
609 const xmlChar * prefix,
610 const xmlChar * URI)
611{
612 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
613 xmlTextReaderPtr reader = ctxt->_private;
614
615#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000616 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000617#endif
618 if ((reader != NULL) && (reader->endElementNs != NULL)) {
619 reader->endElementNs(ctx, localname, prefix, URI);
620 }
621}
622
623
624/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000625 * xmlTextReaderCharacters:
626 * @ctx: the user data (XML parser context)
627 * @ch: a xmlChar string
628 * @len: the number of xmlChar
629 *
630 * receiving some chars from the parser.
631 */
632static void
633xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
634{
635 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
636 xmlTextReaderPtr reader = ctxt->_private;
637
638#ifdef DEBUG_CALLBACKS
639 printf("xmlTextReaderCharacters()\n");
640#endif
641 if ((reader != NULL) && (reader->characters != NULL)) {
642 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000643 }
644}
645
646/**
647 * xmlTextReaderCDataBlock:
648 * @ctx: the user data (XML parser context)
649 * @value: The pcdata content
650 * @len: the block length
651 *
652 * called when a pcdata block has been parsed
653 */
654static void
655xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
656{
657 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
658 xmlTextReaderPtr reader = ctxt->_private;
659
660#ifdef DEBUG_CALLBACKS
661 printf("xmlTextReaderCDataBlock()\n");
662#endif
663 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
664 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000665 }
666}
667
668/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000669 * xmlTextReaderPushData:
670 * @reader: the xmlTextReaderPtr used
671 *
672 * Push data down the progressive parser until a significant callback
673 * got raised.
674 *
675 * Returns -1 in case of failure, 0 otherwise
676 */
677static int
678xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000679 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000680 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000681 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000682
683 if ((reader->input == NULL) || (reader->input->buffer == NULL))
684 return(-1);
685
Daniel Veillardea7751d2002-12-20 00:16:24 +0000686 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000687 reader->state = XML_TEXTREADER_NONE;
688 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000689
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000690 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000691 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000692 /*
693 * Refill the buffer unless we are at the end of the stream
694 */
695 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
696 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000697 if ((val == 0) &&
698 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
699 if (inbuf->use == reader->cur) {
700 reader->mode = XML_TEXTREADER_MODE_EOF;
701 reader->state = oldstate;
702 if ((oldstate != XML_TEXTREADER_START) ||
703 (reader->ctxt->myDoc != NULL))
704 return(val);
705 }
706 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000707 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000708 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000709 if ((oldstate != XML_TEXTREADER_START) ||
710 (reader->ctxt->myDoc != NULL))
711 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000712 } else if (val == 0) {
713 /* mark the end of the stream and process the remains */
714 reader->mode = XML_TEXTREADER_MODE_EOF;
715 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000716 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000717
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000718 } else
719 break;
720 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000721 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000722 * parse by block of CHUNK_SIZE bytes, various tests show that
723 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000724 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000725 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000726 val = xmlParseChunk(reader->ctxt,
727 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000728 CHUNK_SIZE, 0);
729 reader->cur += CHUNK_SIZE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000730 if (val != 0)
731 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000732 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000733 s = inbuf->use - reader->cur;
734 val = xmlParseChunk(reader->ctxt,
735 (const char *) &inbuf->content[reader->cur],
736 s, 0);
737 reader->cur += s;
738 if (val != 0)
739 return(-1);
740 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000741 }
742 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000743
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000744 /*
745 * Discard the consumed input when needed and possible
746 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000747 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000748 if ((reader->cur >= 4096) &&
749 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000750 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000751 if (val >= 0) {
752 reader->cur -= val;
753 }
754 }
755 }
756
757 /*
758 * At the end of the stream signal that the work is done to the Push
759 * parser.
760 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000761 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000762 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000763 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000764 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000765 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000766 s, 1);
767 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000768 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000769 if (val != 0) return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000770 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000771 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000772 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000773 return(0);
774}
775
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000776#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000777/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000778 * xmlTextReaderValidatePush:
779 * @reader: the xmlTextReaderPtr used
780 *
781 * Push the current node for validation
782 */
783static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000784xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000785 xmlNodePtr node = reader->node;
786
Daniel Veillardf4e55762003-04-15 23:32:22 +0000787 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
788 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
789 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
790 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
791 reader->ctxt->myDoc, node, node->name);
792 } else {
793 /* TODO use the BuildQName interface */
794 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000795
Daniel Veillardf4e55762003-04-15 23:32:22 +0000796 qname = xmlStrdup(node->ns->prefix);
797 qname = xmlStrcat(qname, BAD_CAST ":");
798 qname = xmlStrcat(qname, node->name);
799 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
800 reader->ctxt->myDoc, node, qname);
801 if (qname != NULL)
802 xmlFree(qname);
803 }
804#ifdef LIBXML_SCHEMAS_ENABLED
805 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
806 (reader->rngValidCtxt != NULL)) {
807 int ret;
808
809 if (reader->rngFullNode != NULL) return;
810 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
811 reader->ctxt->myDoc,
812 node);
813 if (ret == 0) {
814 /*
815 * this element requires a full tree
816 */
817 node = xmlTextReaderExpand(reader);
818 if (node == NULL) {
819printf("Expand failed !\n");
820 ret = -1;
821 } else {
822 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
823 reader->ctxt->myDoc,
824 node);
825 reader->rngFullNode = node;
826 }
827 }
828 if (ret != 1)
829 reader->rngValidErrors++;
830#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000831 }
832}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000833
834/**
835 * xmlTextReaderValidateCData:
836 * @reader: the xmlTextReaderPtr used
837 * @data: pointer to the CData
838 * @len: lenght of the CData block in bytes.
839 *
840 * Push some CData for validation
841 */
842static void
843xmlTextReaderValidateCData(xmlTextReaderPtr reader,
844 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000845 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
846 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
847 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
848 data, len);
849#ifdef LIBXML_SCHEMAS_ENABLED
850 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
851 (reader->rngValidCtxt != NULL)) {
852 int ret;
853
854 if (reader->rngFullNode != NULL) return;
855 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
856 if (ret != 1)
857 reader->rngValidErrors++;
858#endif
859 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000860}
861
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000862/**
863 * xmlTextReaderValidatePop:
864 * @reader: the xmlTextReaderPtr used
865 *
866 * Pop the current node from validation
867 */
868static void
869xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
870 xmlNodePtr node = reader->node;
871
Daniel Veillardf4e55762003-04-15 23:32:22 +0000872 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
873 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
874 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
875 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
876 reader->ctxt->myDoc, node, node->name);
877 } else {
878 /* TODO use the BuildQName interface */
879 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000880
Daniel Veillardf4e55762003-04-15 23:32:22 +0000881 qname = xmlStrdup(node->ns->prefix);
882 qname = xmlStrcat(qname, BAD_CAST ":");
883 qname = xmlStrcat(qname, node->name);
884 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
885 reader->ctxt->myDoc, node, qname);
886 if (qname != NULL)
887 xmlFree(qname);
888 }
889#ifdef LIBXML_SCHEMAS_ENABLED
890 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
891 (reader->rngValidCtxt != NULL)) {
892 int ret;
893
894 if (reader->rngFullNode != NULL) {
895 if (node == reader->rngFullNode)
896 reader->rngFullNode = NULL;
897 return;
898 }
899 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
900 reader->ctxt->myDoc,
901 node);
902 if (ret != 1)
903 reader->rngValidErrors++;
904#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000905 }
906}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000907
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000908/**
909 * xmlTextReaderValidateEntity:
910 * @reader: the xmlTextReaderPtr used
911 *
912 * Handle the validation when an entity reference is encountered and
913 * entity substitution is not activated. As a result the parser interface
914 * must walk through the entity and do the validation calls
915 */
916static void
917xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
918 xmlNodePtr oldnode = reader->node;
919 xmlNodePtr node = reader->node;
920 xmlParserCtxtPtr ctxt = reader->ctxt;
921
922 do {
923 if (node->type == XML_ENTITY_REF_NODE) {
924 /*
925 * Case where the underlying tree is not availble, lookup the entity
926 * and walk it.
927 */
928 if ((node->children == NULL) && (ctxt->sax != NULL) &&
929 (ctxt->sax->getEntity != NULL)) {
930 node->children = (xmlNodePtr)
931 ctxt->sax->getEntity(ctxt, node->name);
932 }
933
934 if ((node->children != NULL) &&
935 (node->children->type == XML_ENTITY_DECL) &&
936 (node->children->children != NULL)) {
937 xmlTextReaderEntPush(reader, node);
938 node = node->children->children;
939 continue;
940 } else {
941 /*
942 * The error has probably be raised already.
943 */
944 if (node == oldnode)
945 break;
946 node = node->next;
947 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000948#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000949 } else if (node->type == XML_ELEMENT_NODE) {
950 reader->node = node;
951 xmlTextReaderValidatePush(reader);
952 } else if ((node->type == XML_TEXT_NODE) ||
953 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000954 xmlTextReaderValidateCData(reader, node->content,
955 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000956#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000957 }
958
959 /*
960 * go to next node
961 */
962 if (node->children != NULL) {
963 node = node->children;
964 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +0000965 } else if (node->type == XML_ELEMENT_NODE) {
966 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000967 }
968 if (node->next != NULL) {
969 node = node->next;
970 continue;
971 }
972 do {
973 node = node->parent;
974 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000975 xmlNodePtr tmp;
976 while ((tmp = node->last) != NULL) {
977 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
978 (tmp->_private != xmlTextReaderIsPreserved)) {
979 xmlUnlinkNode(tmp);
980 xmlTextReaderFreeNode(reader, tmp);
981 } else
982 break;
983 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000984 reader->node = node;
985 xmlTextReaderValidatePop(reader);
986 }
987 if ((node->type == XML_ENTITY_DECL) &&
988 (reader->ent != NULL) && (reader->ent->children == node)) {
989 node = xmlTextReaderEntPop(reader);
990 }
991 if (node == oldnode)
992 break;
993 if (node->next != NULL) {
994 node = node->next;
995 break;
996 }
997 } while ((node != NULL) && (node != oldnode));
998 } while ((node != NULL) && (node != oldnode));
999 reader->node = oldnode;
1000}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001001#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001002
1003
1004/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001005 * xmlTextReaderGetSuccessor:
1006 * @cur: the current node
1007 *
1008 * Get the successor of a node if available.
1009 *
1010 * Returns the successor node or NULL
1011 */
1012static xmlNodePtr
1013xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1014 if (cur == NULL) return(NULL) ; /* ERROR */
1015 if (cur->next != NULL) return(cur->next) ;
1016 do {
1017 cur = cur->parent;
1018 if (cur == NULL) return(NULL);
1019 if (cur->next != NULL) return(cur->next);
1020 } while (cur != NULL);
1021 return(cur);
1022}
1023
1024/**
1025 * xmlTextReaderDoExpand:
1026 * @reader: the xmlTextReaderPtr used
1027 *
1028 * Makes sure that the current node is fully read as well as all its
1029 * descendant. It means the full DOM subtree must be available at the
1030 * end of the call.
1031 *
1032 * Returns 1 if the node was expanded successfully, 0 if there is no more
1033 * nodes to read, or -1 in case of error
1034 */
1035static int
1036xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1037 int val;
1038
1039 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1040 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001041 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001042 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1043
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001044 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1045 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001046 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001047 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001048 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1049 return(1);
1050 val = xmlTextReaderPushData(reader);
1051 if (val < 0)
1052 return(-1);
1053 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1054 return(1);
1055}
1056
1057/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001058 * xmlTextReaderRead:
1059 * @reader: the xmlTextReaderPtr used
1060 *
1061 * Moves the position of the current instance to the next node in
1062 * the stream, exposing its properties.
1063 *
1064 * Returns 1 if the node was read successfully, 0 if there is no more
1065 * nodes to read, or -1 in case of error
1066 */
1067int
1068xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001069 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001070 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001071 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001072
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001073
1074 if (reader == NULL)
1075 return(-1);
1076 if (reader->doc != NULL)
1077 return(xmlTextReaderReadTree(reader));
1078 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001079 return(-1);
1080 if (reader->ctxt->wellFormed != 1)
1081 return(-1);
1082
1083#ifdef DEBUG_READER
1084 fprintf(stderr, "\nREAD ");
1085 DUMP_READER
1086#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001087 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001088 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1089 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001090 /*
1091 * Initial state
1092 */
1093 do {
1094 val = xmlTextReaderPushData(reader);
1095 if (val < 0)
1096 return(-1);
1097 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001098 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1099 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001100 if (reader->ctxt->myDoc != NULL)
1101 reader->ctxt->myDoc->_private = reader;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001102 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001103 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001104 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001105 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001106 if (reader->node == NULL)
1107 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001108 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001109 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001110 if (reader->ctxt->myDoc != NULL) {
1111 reader->node = reader->ctxt->myDoc->children;
1112 }
1113 if (reader->node == NULL)
1114 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001115 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001116 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001117 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001118 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001119 }
1120 oldstate = reader->state;
1121 olddepth = reader->ctxt->nodeNr;
1122 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001123
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001124get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001125 /*
1126 * If we are not backtracking on ancestors or examined nodes,
1127 * that the parser didn't finished or that we arent at the end
1128 * of stream, continue processing.
1129 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001130 while ((reader->node->next == NULL) &&
1131 (reader->ctxt->nodeNr == olddepth) &&
1132 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001133 (reader->node->children == NULL) ||
1134 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001135 ((reader->node->children != NULL) &&
1136 (reader->node->children->type == XML_TEXT_NODE) &&
1137 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001138 (reader->node->type == XML_DTD_NODE) ||
1139 (reader->node->type == XML_DOCUMENT_NODE) ||
1140 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001141 ((reader->ctxt->node == NULL) ||
1142 (reader->ctxt->node == reader->node) ||
1143 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001144 (reader->ctxt->instate != XML_PARSER_EOF)) {
1145 val = xmlTextReaderPushData(reader);
1146 if (val < 0)
1147 return(-1);
1148 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001149 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001150 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001151 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001152 if ((reader->node->children != NULL) &&
1153 (reader->node->type != XML_ENTITY_REF_NODE) &&
1154 (reader->node->type != XML_DTD_NODE)) {
1155 reader->node = reader->node->children;
1156 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001157 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001158 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001159 }
1160 }
1161 if (reader->node->next != NULL) {
1162 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001163 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001164 (reader->node->children == NULL) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001165 (reader->node->_private != (void *)xmlTextReaderIsEmpty) &&
1166 (reader->node->_private != (void *)xmlTextReaderIsEmptyPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001167 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001168 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001169 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001170#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001171 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001172 (reader->node->type == XML_ELEMENT_NODE))
1173 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001174#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001175 reader->node = reader->node->next;
1176 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001177
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001178 /*
1179 * Cleanup of the old node
1180 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001181 if ((reader->node->prev != NULL) &&
1182 (reader->node->prev->type != XML_DTD_NODE)) {
1183 xmlNodePtr tmp = reader->node->prev;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001184 if ((tmp->_private != xmlTextReaderIsEmptyPreserved) &&
1185 (tmp->_private != xmlTextReaderIsPreserved)) {
1186 xmlUnlinkNode(tmp);
1187 xmlTextReaderFreeNode(reader, tmp);
1188 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001189 }
1190
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001191 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001192 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001193 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001194 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001195 (reader->node->children == NULL) &&
1196 (reader->node->_private != (void *)xmlTextReaderIsEmpty)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001197 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001198 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001199 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001200#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001201 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001202 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001203#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001204 reader->node = reader->node->parent;
1205 if ((reader->node == NULL) ||
1206 (reader->node->type == XML_DOCUMENT_NODE) ||
1207#ifdef LIBXML_DOCB_ENABLED
1208 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1209#endif
1210 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001211 if (reader->mode != XML_TEXTREADER_DONE) {
1212 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1213 reader->mode = XML_TEXTREADER_DONE;
1214 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001215 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001216 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001217
1218 /*
1219 * Cleanup of the old node
1220 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001221 if ((oldnode->type != XML_DTD_NODE) &&
1222 (oldnode->_private != xmlTextReaderIsEmptyPreserved) &&
1223 (oldnode->_private != xmlTextReaderIsPreserved)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001224 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001225 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001226 }
1227
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001228 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001229 }
1230 reader->depth--;
1231 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001232
1233node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001234 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001235
1236 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001237 * If we are in the middle of a piece of CDATA make sure it's finished
1238 */
1239 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001240 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001241 ((reader->node->type == XML_TEXT_NODE) ||
1242 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1243 xmlTextReaderExpand(reader);
1244 }
1245
1246 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001247 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001248 */
1249 if ((reader->node != NULL) &&
1250 (reader->node->type == XML_ENTITY_REF_NODE) &&
1251 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1252 /*
1253 * Case where the underlying tree is not availble, lookup the entity
1254 * and walk it.
1255 */
1256 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1257 (reader->ctxt->sax->getEntity != NULL)) {
1258 reader->node->children = (xmlNodePtr)
1259 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1260 }
1261
1262 if ((reader->node->children != NULL) &&
1263 (reader->node->children->type == XML_ENTITY_DECL) &&
1264 (reader->node->children->children != NULL)) {
1265 xmlTextReaderEntPush(reader, reader->node);
1266 reader->node = reader->node->children->children;
1267 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001268#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001269 } else if ((reader->node != NULL) &&
1270 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001271 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001272 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001273#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001274 }
1275 if ((reader->node != NULL) &&
1276 (reader->node->type == XML_ENTITY_DECL) &&
1277 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1278 reader->node = xmlTextReaderEntPop(reader);
1279 reader->depth++;
1280 goto get_next_node;
1281 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001282#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001283 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001284 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001285
1286 if ((node->type == XML_ELEMENT_NODE) &&
1287 ((reader->state != XML_TEXTREADER_END) &&
1288 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1289 xmlTextReaderValidatePush(reader);
1290 } else if ((node->type == XML_TEXT_NODE) ||
1291 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001292 xmlTextReaderValidateCData(reader, node->content,
1293 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001294 }
1295 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001296#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001297 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001298node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001299 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001300 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001301}
1302
Daniel Veillard67df8092002-12-16 22:04:11 +00001303/**
1304 * xmlTextReaderReadState:
1305 * @reader: the xmlTextReaderPtr used
1306 *
1307 * Gets the read state of the reader.
1308 *
1309 * Returns the state value, or -1 in case of error
1310 */
1311int
1312xmlTextReaderReadState(xmlTextReaderPtr reader) {
1313 if (reader == NULL)
1314 return(-1);
1315 return(reader->mode);
1316}
1317
1318/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001319 * xmlTextReaderExpand:
1320 * @reader: the xmlTextReaderPtr used
1321 *
1322 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001323 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001324 *
1325 * Returns a node pointer valid until the next xmlTextReaderRead() call
1326 * or NULL in case of error.
1327 */
1328xmlNodePtr
1329xmlTextReaderExpand(xmlTextReaderPtr reader) {
1330 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1331 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001332 if (reader->doc != NULL)
1333 return(reader->node);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001334 if (xmlTextReaderDoExpand(reader) < 0)
1335 return(NULL);
1336 return(reader->node);
1337}
1338
1339/**
1340 * xmlTextReaderNext:
1341 * @reader: the xmlTextReaderPtr used
1342 *
1343 * Skip to the node following the current one in document order while
1344 * avoiding the subtree if any.
1345 *
1346 * Returns 1 if the node was read successfully, 0 if there is no more
1347 * nodes to read, or -1 in case of error
1348 */
1349int
1350xmlTextReaderNext(xmlTextReaderPtr reader) {
1351 int ret;
1352 xmlNodePtr cur;
1353
1354 if (reader == NULL)
1355 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001356 if (reader->doc != NULL)
1357 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001358 cur = reader->node;
1359 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1360 return(xmlTextReaderRead(reader));
1361 if (reader->state == XML_TEXTREADER_END)
1362 return(xmlTextReaderRead(reader));
1363 if (cur->_private == (void *)xmlTextReaderIsEmpty)
1364 return(xmlTextReaderRead(reader));
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001365 if (cur->_private == (void *)xmlTextReaderIsEmptyPreserved)
1366 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001367 do {
1368 ret = xmlTextReaderRead(reader);
1369 if (ret != 1)
1370 return(ret);
1371 } while (reader->node != cur);
1372 return(xmlTextReaderRead(reader));
1373}
1374
1375/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001376 * xmlTextReaderReadInnerXml:
1377 * @reader: the xmlTextReaderPtr used
1378 *
1379 * Reads the contents of the current node, including child nodes and markup.
1380 *
1381 * Returns a string containing the XML content, or NULL if the current node
1382 * is neither an element nor attribute, or has no child nodes. The
1383 * string must be deallocated by the caller.
1384 */
1385xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001386xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001387 TODO
1388 return(NULL);
1389}
1390
1391/**
1392 * xmlTextReaderReadOuterXml:
1393 * @reader: the xmlTextReaderPtr used
1394 *
1395 * Reads the contents of the current node, including child nodes and markup.
1396 *
1397 * Returns a string containing the XML content, or NULL if the current node
1398 * is neither an element nor attribute, or has no child nodes. The
1399 * string must be deallocated by the caller.
1400 */
1401xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001402xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001403 TODO
1404 return(NULL);
1405}
1406
1407/**
1408 * xmlTextReaderReadString:
1409 * @reader: the xmlTextReaderPtr used
1410 *
1411 * Reads the contents of an element or a text node as a string.
1412 *
1413 * Returns a string containing the contents of the Element or Text node,
1414 * or NULL if the reader is positioned on any other type of node.
1415 * The string must be deallocated by the caller.
1416 */
1417xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001418xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001419 TODO
1420 return(NULL);
1421}
1422
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001423#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001424/**
1425 * xmlTextReaderReadBase64:
1426 * @reader: the xmlTextReaderPtr used
1427 * @array: a byte array to store the content.
1428 * @offset: the zero-based index into array where the method should
1429 * begin to write.
1430 * @len: the number of bytes to write.
1431 *
1432 * Reads and decodes the Base64 encoded contents of an element and
1433 * stores the result in a byte buffer.
1434 *
1435 * Returns the number of bytes written to array, or zero if the current
1436 * instance is not positioned on an element or -1 in case of error.
1437 */
1438int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001439xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1440 unsigned char *array ATTRIBUTE_UNUSED,
1441 int offset ATTRIBUTE_UNUSED,
1442 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001443 if ((reader == NULL) || (reader->ctxt == NULL))
1444 return(-1);
1445 if (reader->ctxt->wellFormed != 1)
1446 return(-1);
1447
1448 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1449 return(0);
1450 TODO
1451 return(0);
1452}
1453
1454/**
1455 * xmlTextReaderReadBinHex:
1456 * @reader: the xmlTextReaderPtr used
1457 * @array: a byte array to store the content.
1458 * @offset: the zero-based index into array where the method should
1459 * begin to write.
1460 * @len: the number of bytes to write.
1461 *
1462 * Reads and decodes the BinHex encoded contents of an element and
1463 * stores the result in a byte buffer.
1464 *
1465 * Returns the number of bytes written to array, or zero if the current
1466 * instance is not positioned on an element or -1 in case of error.
1467 */
1468int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001469xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1470 unsigned char *array ATTRIBUTE_UNUSED,
1471 int offset ATTRIBUTE_UNUSED,
1472 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001473 if ((reader == NULL) || (reader->ctxt == NULL))
1474 return(-1);
1475 if (reader->ctxt->wellFormed != 1)
1476 return(-1);
1477
1478 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1479 return(0);
1480 TODO
1481 return(0);
1482}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001483#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001484
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485/************************************************************************
1486 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001487 * Operating on a preparsed tree *
1488 * *
1489 ************************************************************************/
1490static int
1491xmlTextReaderNextTree(xmlTextReaderPtr reader)
1492{
1493 if (reader == 0)
1494 return(-1);
1495
1496 if (reader->state == XML_TEXTREADER_END)
1497 return(0);
1498
1499 if (reader->node == 0) {
1500 if (reader->doc->children == 0) {
1501 reader->state = XML_TEXTREADER_END;
1502 return(0);
1503 }
1504
1505 reader->node = reader->doc->children;
1506 reader->state = XML_TEXTREADER_START;
1507 return(1);
1508 }
1509
1510 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1511 if (reader->node->children != 0) {
1512 reader->node = reader->node->children;
1513 reader->depth++;
1514 reader->state = XML_TEXTREADER_START;
1515 return(1);
1516 }
1517
1518 if ((reader->node->type == XML_ELEMENT_NODE) ||
1519 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1520 reader->state = XML_TEXTREADER_BACKTRACK;
1521 return(1);
1522 }
1523 }
1524
1525 if (reader->node->next != 0) {
1526 reader->node = reader->node->next;
1527 reader->state = XML_TEXTREADER_START;
1528 return(1);
1529 }
1530
1531 if (reader->node->parent != 0) {
1532 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1533 reader->state = XML_TEXTREADER_END;
1534 return(0);
1535 }
1536
1537 reader->node = reader->node->parent;
1538 reader->depth--;
1539 reader->state = XML_TEXTREADER_BACKTRACK;
1540 return(1);
1541 }
1542
1543 reader->state = XML_TEXTREADER_END;
1544
1545 return(1);
1546}
1547
1548/**
1549 * xmlTextReaderReadTree:
1550 * @reader: the xmlTextReaderPtr used
1551 *
1552 * Moves the position of the current instance to the next node in
1553 * the stream, exposing its properties.
1554 *
1555 * Returns 1 if the node was read successfully, 0 if there is no more
1556 * nodes to read, or -1 in case of error
1557 */
1558static int
1559xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1560 if (reader->state == XML_TEXTREADER_END)
1561 return(0);
1562
1563 if (reader->node == NULL) {
1564 if (reader->doc->children == NULL) {
1565 reader->state = XML_TEXTREADER_END;
1566 return(0);
1567 }
1568
1569 reader->node = reader->doc->children;
1570 reader->state = XML_TEXTREADER_START;
1571 return(1);
1572 }
1573
1574 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1575 if (reader->node->children != 0) {
1576 reader->node = reader->node->children;
1577 reader->depth++;
1578 reader->state = XML_TEXTREADER_START;
1579 return(1);
1580 }
1581
1582 if ((reader->node->type == XML_ELEMENT_NODE) ||
1583 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1584 reader->state = XML_TEXTREADER_BACKTRACK;
1585 return(1);
1586 }
1587 }
1588
1589 if (reader->node->next != 0) {
1590 reader->node = reader->node->next;
1591 reader->state = XML_TEXTREADER_START;
1592 return(1);
1593 }
1594
1595 if (reader->node->parent != 0) {
1596 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1597 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1598 reader->state = XML_TEXTREADER_END;
1599 return(0);
1600 }
1601
1602 reader->node = reader->node->parent;
1603 reader->depth--;
1604 reader->state = XML_TEXTREADER_BACKTRACK;
1605 return(1);
1606 }
1607
1608 reader->state = XML_TEXTREADER_END;
1609
1610 return(1);
1611}
1612
1613/**
1614 * xmlTextReaderNextTree:
1615 * @reader: the xmlTextReaderPtr used
1616 *
1617 * Skip to the node following the current one in document order while
1618 * avoiding the subtree if any.
1619 * Currently implemented only for Readers built on a document
1620 *
1621 * Returns 1 if the node was read successfully, 0 if there is no more
1622 * nodes to read, or -1 in case of error
1623 */
1624int
1625xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1626 if (reader == NULL)
1627 return(-1);
1628 if (reader->doc == NULL) {
1629 TODO
1630 return(-1);
1631 }
1632
1633 if (reader->state == XML_TEXTREADER_END)
1634 return(0);
1635
1636 if (reader->node == 0)
1637 return(xmlTextReaderNextTree(reader));
1638
1639 if (reader->node->next != 0) {
1640 reader->node = reader->node->next;
1641 reader->state = XML_TEXTREADER_START;
1642 return(1);
1643 }
1644
1645 return(0);
1646}
1647
1648/************************************************************************
1649 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001650 * Constructor and destructors *
1651 * *
1652 ************************************************************************/
1653/**
1654 * xmlNewTextReader:
1655 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001656 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001657 *
1658 * Create an xmlTextReader structure fed with @input
1659 *
1660 * Returns the new xmlTextReaderPtr or NULL in case of error
1661 */
1662xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001663xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001664 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001665
1666 if (input == NULL)
1667 return(NULL);
1668 ret = xmlMalloc(sizeof(xmlTextReader));
1669 if (ret == NULL) {
1670 xmlGenericError(xmlGenericErrorContext,
1671 "xmlNewTextReader : malloc failed\n");
1672 return(NULL);
1673 }
1674 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001675 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001676 ret->entTab = NULL;
1677 ret->entMax = 0;
1678 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001679 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001680 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001681 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1682 if (ret->sax == NULL) {
1683 xmlFree(ret);
1684 xmlGenericError(xmlGenericErrorContext,
1685 "xmlNewTextReader : malloc failed\n");
1686 return(NULL);
1687 }
Daniel Veillard81273902003-09-30 00:43:48 +00001688 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001689 ret->startElement = ret->sax->startElement;
1690 ret->sax->startElement = xmlTextReaderStartElement;
1691 ret->endElement = ret->sax->endElement;
1692 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001693#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001694 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001695#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001696 ret->startElementNs = ret->sax->startElementNs;
1697 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1698 ret->endElementNs = ret->sax->endElementNs;
1699 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001700#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001701 } else {
1702 ret->startElementNs = NULL;
1703 ret->endElementNs = NULL;
1704 }
Daniel Veillard81273902003-09-30 00:43:48 +00001705#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001706 ret->characters = ret->sax->characters;
1707 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001708 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001709 ret->cdataBlock = ret->sax->cdataBlock;
1710 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001711
Daniel Veillard67df8092002-12-16 22:04:11 +00001712 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001713 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001714 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001715 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001716 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001717 }
1718 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001719 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001720 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001721 ret->base = 0;
1722 ret->cur = 4;
1723 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001724 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001725 ret->base = 0;
1726 ret->cur = 0;
1727 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001728 if (ret->ctxt == NULL) {
1729 xmlGenericError(xmlGenericErrorContext,
1730 "xmlNewTextReader : malloc failed\n");
1731 xmlFree(ret->sax);
1732 xmlFree(ret);
1733 return(NULL);
1734 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001735 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001736 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001737 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001738 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001739 /*
1740 * use the parser dictionnary to allocate all elements and attributes names
1741 */
1742 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001743 ret->dict = ret->ctxt->dict;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001744 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001745}
1746
1747/**
1748 * xmlNewTextReaderFilename:
1749 * @URI: the URI of the resource to process
1750 *
1751 * Create an xmlTextReader structure fed with the resource at @URI
1752 *
1753 * Returns the new xmlTextReaderPtr or NULL in case of error
1754 */
1755xmlTextReaderPtr
1756xmlNewTextReaderFilename(const char *URI) {
1757 xmlParserInputBufferPtr input;
1758 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001759 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001760
1761 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1762 if (input == NULL)
1763 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001764 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001765 if (ret == NULL) {
1766 xmlFreeParserInputBuffer(input);
1767 return(NULL);
1768 }
1769 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001770 if (ret->ctxt->directory == NULL)
1771 directory = xmlParserGetDirectory(URI);
1772 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1773 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1774 if (directory != NULL)
1775 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001776 return(ret);
1777}
1778
1779/**
1780 * xmlFreeTextReader:
1781 * @reader: the xmlTextReaderPtr
1782 *
1783 * Deallocate all the resources associated to the reader
1784 */
1785void
1786xmlFreeTextReader(xmlTextReaderPtr reader) {
1787 if (reader == NULL)
1788 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001789#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001790 if (reader->rngSchemas != NULL) {
1791 xmlRelaxNGFree(reader->rngSchemas);
1792 reader->rngSchemas = NULL;
1793 }
1794 if (reader->rngValidCtxt != NULL) {
1795 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1796 reader->rngValidCtxt = NULL;
1797 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001798#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001799 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001800 if (reader->dict == reader->ctxt->dict)
1801 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001802 if (reader->ctxt->myDoc != NULL) {
1803 if (reader->preserve == 0)
1804 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1805 reader->ctxt->myDoc = NULL;
1806 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001807 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1808 (reader->ctxt->vctxt.vstateMax > 0)){
1809 xmlFree(reader->ctxt->vctxt.vstateTab);
1810 reader->ctxt->vctxt.vstateTab = 0;
1811 reader->ctxt->vctxt.vstateMax = 0;
1812 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001813 if (reader->allocs & XML_TEXTREADER_CTXT)
1814 xmlFreeParserCtxt(reader->ctxt);
1815 }
1816 if (reader->sax != NULL)
1817 xmlFree(reader->sax);
1818 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1819 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001820 if (reader->faketext != NULL) {
1821 xmlFreeNode(reader->faketext);
1822 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001823 if (reader->buffer != NULL)
1824 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001825 if (reader->entTab != NULL)
1826 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001827 if (reader->dict != NULL)
1828 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001829 xmlFree(reader);
1830}
1831
1832/************************************************************************
1833 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001834 * Methods for XmlTextReader *
1835 * *
1836 ************************************************************************/
1837/**
1838 * xmlTextReaderClose:
1839 * @reader: the xmlTextReaderPtr used
1840 *
1841 * This method releases any resources allocated by the current instance
1842 * changes the state to Closed and close any underlying input.
1843 *
1844 * Returns 0 or -1 in case of error
1845 */
1846int
1847xmlTextReaderClose(xmlTextReaderPtr reader) {
1848 if (reader == NULL)
1849 return(-1);
1850 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001851 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001852 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1853 if (reader->ctxt != NULL) {
1854 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001855 if (reader->preserve == 0)
1856 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001857 reader->ctxt->myDoc = NULL;
1858 }
1859 if (reader->allocs & XML_TEXTREADER_CTXT) {
1860 xmlFreeParserCtxt(reader->ctxt);
1861 reader->allocs -= XML_TEXTREADER_CTXT;
1862 }
1863 }
1864 if (reader->sax != NULL) {
1865 xmlFree(reader->sax);
1866 reader->sax = NULL;
1867 }
1868 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1869 xmlFreeParserInputBuffer(reader->input);
1870 reader->allocs -= XML_TEXTREADER_INPUT;
1871 }
1872 return(0);
1873}
1874
1875/**
1876 * xmlTextReaderGetAttributeNo:
1877 * @reader: the xmlTextReaderPtr used
1878 * @no: the zero-based index of the attribute relative to the containing element
1879 *
1880 * Provides the value of the attribute with the specified index relative
1881 * to the containing element.
1882 *
1883 * Returns a string containing the value of the specified attribute, or NULL
1884 * in case of error. The string must be deallocated by the caller.
1885 */
1886xmlChar *
1887xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1888 xmlChar *ret;
1889 int i;
1890 xmlAttrPtr cur;
1891 xmlNsPtr ns;
1892
1893 if (reader == NULL)
1894 return(NULL);
1895 if (reader->node == NULL)
1896 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001897 if (reader->curnode != NULL)
1898 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001899 /* TODO: handle the xmlDecl */
1900 if (reader->node->type != XML_ELEMENT_NODE)
1901 return(NULL);
1902
1903 ns = reader->node->nsDef;
1904 for (i = 0;(i < no) && (ns != NULL);i++) {
1905 ns = ns->next;
1906 }
1907 if (ns != NULL)
1908 return(xmlStrdup(ns->href));
1909
1910 cur = reader->node->properties;
1911 if (cur == NULL)
1912 return(NULL);
1913 for (;i < no;i++) {
1914 cur = cur->next;
1915 if (cur == NULL)
1916 return(NULL);
1917 }
1918 /* TODO walk the DTD if present */
1919
1920 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1921 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1922 return(ret);
1923}
1924
1925/**
1926 * xmlTextReaderGetAttribute:
1927 * @reader: the xmlTextReaderPtr used
1928 * @name: the qualified name of the attribute.
1929 *
1930 * Provides the value of the attribute with the specified qualified name.
1931 *
1932 * Returns a string containing the value of the specified attribute, or NULL
1933 * in case of error. The string must be deallocated by the caller.
1934 */
1935xmlChar *
1936xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1937 xmlChar *prefix = NULL;
1938 xmlChar *localname;
1939 xmlNsPtr ns;
1940 xmlChar *ret = NULL;
1941
1942 if ((reader == NULL) || (name == NULL))
1943 return(NULL);
1944 if (reader->node == NULL)
1945 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001946 if (reader->curnode != NULL)
1947 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001948
1949 /* TODO: handle the xmlDecl */
1950 if (reader->node->type != XML_ELEMENT_NODE)
1951 return(NULL);
1952
1953 localname = xmlSplitQName2(name, &prefix);
1954 if (localname == NULL)
1955 return(xmlGetProp(reader->node, name));
1956
1957 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1958 if (ns != NULL)
1959 ret = xmlGetNsProp(reader->node, localname, ns->href);
1960
1961 if (localname != NULL)
1962 xmlFree(localname);
1963 if (prefix != NULL)
1964 xmlFree(prefix);
1965 return(ret);
1966}
1967
1968
1969/**
1970 * xmlTextReaderGetAttributeNs:
1971 * @reader: the xmlTextReaderPtr used
1972 * @localName: the local name of the attribute.
1973 * @namespaceURI: the namespace URI of the attribute.
1974 *
1975 * Provides the value of the specified attribute
1976 *
1977 * Returns a string containing the value of the specified attribute, or NULL
1978 * in case of error. The string must be deallocated by the caller.
1979 */
1980xmlChar *
1981xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
1982 const xmlChar *namespaceURI) {
1983 if ((reader == NULL) || (localName == NULL))
1984 return(NULL);
1985 if (reader->node == NULL)
1986 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001987 if (reader->curnode != NULL)
1988 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001989
1990 /* TODO: handle the xmlDecl */
1991 if (reader->node->type != XML_ELEMENT_NODE)
1992 return(NULL);
1993
1994 return(xmlGetNsProp(reader->node, localName, namespaceURI));
1995}
1996
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001997/**
1998 * xmlTextReaderGetRemainder:
1999 * @reader: the xmlTextReaderPtr used
2000 *
2001 * Method to get the remainder of the buffered XML. this method stops the
2002 * parser, set its state to End Of File and return the input stream with
2003 * what is left that the parser did not use.
2004 *
2005 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2006 * in case of error.
2007 */
2008xmlParserInputBufferPtr
2009xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2010 xmlParserInputBufferPtr ret = NULL;
2011
2012 if (reader == NULL)
2013 return(NULL);
2014 if (reader->node == NULL)
2015 return(NULL);
2016
2017 reader->node = NULL;
2018 reader->curnode = NULL;
2019 reader->mode = XML_TEXTREADER_MODE_EOF;
2020 if (reader->ctxt != NULL) {
2021 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002022 if (reader->preserve == 0)
2023 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002024 reader->ctxt->myDoc = NULL;
2025 }
2026 if (reader->allocs & XML_TEXTREADER_CTXT) {
2027 xmlFreeParserCtxt(reader->ctxt);
2028 reader->allocs -= XML_TEXTREADER_CTXT;
2029 }
2030 }
2031 if (reader->sax != NULL) {
2032 xmlFree(reader->sax);
2033 reader->sax = NULL;
2034 }
2035 if (reader->allocs & XML_TEXTREADER_INPUT) {
2036 ret = reader->input;
2037 reader->allocs -= XML_TEXTREADER_INPUT;
2038 } else {
2039 /*
2040 * Hum, one may need to duplicate the data structure because
2041 * without reference counting the input may be freed twice:
2042 * - by the layer which allocated it.
2043 * - by the layer to which would have been returned to.
2044 */
2045 TODO
2046 return(NULL);
2047 }
2048 return(ret);
2049}
2050
2051/**
2052 * xmlTextReaderLookupNamespace:
2053 * @reader: the xmlTextReaderPtr used
2054 * @prefix: the prefix whose namespace URI is to be resolved. To return
2055 * the default namespace, specify NULL
2056 *
2057 * Resolves a namespace prefix in the scope of the current element.
2058 *
2059 * Returns a string containing the namespace URI to which the prefix maps
2060 * or NULL in case of error. The string must be deallocated by the caller.
2061 */
2062xmlChar *
2063xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2064 xmlNsPtr ns;
2065
2066 if (reader == NULL)
2067 return(NULL);
2068 if (reader->node == NULL)
2069 return(NULL);
2070
2071 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2072 if (ns == NULL)
2073 return(NULL);
2074 return(xmlStrdup(ns->href));
2075}
2076
2077/**
2078 * xmlTextReaderMoveToAttributeNo:
2079 * @reader: the xmlTextReaderPtr used
2080 * @no: the zero-based index of the attribute relative to the containing
2081 * element.
2082 *
2083 * Moves the position of the current instance to the attribute with
2084 * the specified index relative to the containing element.
2085 *
2086 * Returns 1 in case of success, -1 in case of error, 0 if not found
2087 */
2088int
2089xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2090 int i;
2091 xmlAttrPtr cur;
2092 xmlNsPtr ns;
2093
2094 if (reader == NULL)
2095 return(-1);
2096 if (reader->node == NULL)
2097 return(-1);
2098 /* TODO: handle the xmlDecl */
2099 if (reader->node->type != XML_ELEMENT_NODE)
2100 return(-1);
2101
2102 reader->curnode = NULL;
2103
2104 ns = reader->node->nsDef;
2105 for (i = 0;(i < no) && (ns != NULL);i++) {
2106 ns = ns->next;
2107 }
2108 if (ns != NULL) {
2109 reader->curnode = (xmlNodePtr) ns;
2110 return(1);
2111 }
2112
2113 cur = reader->node->properties;
2114 if (cur == NULL)
2115 return(0);
2116 for (;i < no;i++) {
2117 cur = cur->next;
2118 if (cur == NULL)
2119 return(0);
2120 }
2121 /* TODO walk the DTD if present */
2122
2123 reader->curnode = (xmlNodePtr) cur;
2124 return(1);
2125}
2126
2127/**
2128 * xmlTextReaderMoveToAttribute:
2129 * @reader: the xmlTextReaderPtr used
2130 * @name: the qualified name of the attribute.
2131 *
2132 * Moves the position of the current instance to the attribute with
2133 * the specified qualified name.
2134 *
2135 * Returns 1 in case of success, -1 in case of error, 0 if not found
2136 */
2137int
2138xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2139 xmlChar *prefix = NULL;
2140 xmlChar *localname;
2141 xmlNsPtr ns;
2142 xmlAttrPtr prop;
2143
2144 if ((reader == NULL) || (name == NULL))
2145 return(-1);
2146 if (reader->node == NULL)
2147 return(-1);
2148
2149 /* TODO: handle the xmlDecl */
2150 if (reader->node->type != XML_ELEMENT_NODE)
2151 return(0);
2152
2153 localname = xmlSplitQName2(name, &prefix);
2154 if (localname == NULL) {
2155 /*
2156 * Namespace default decl
2157 */
2158 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2159 ns = reader->node->nsDef;
2160 while (ns != NULL) {
2161 if (ns->prefix == NULL) {
2162 reader->curnode = (xmlNodePtr) ns;
2163 return(1);
2164 }
2165 ns = ns->next;
2166 }
2167 return(0);
2168 }
2169
2170 prop = reader->node->properties;
2171 while (prop != NULL) {
2172 /*
2173 * One need to have
2174 * - same attribute names
2175 * - and the attribute carrying that namespace
2176 */
2177 if ((xmlStrEqual(prop->name, name)) &&
2178 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2179 reader->curnode = (xmlNodePtr) prop;
2180 return(1);
2181 }
2182 prop = prop->next;
2183 }
2184 return(0);
2185 }
2186
2187 /*
2188 * Namespace default decl
2189 */
2190 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2191 ns = reader->node->nsDef;
2192 while (ns != NULL) {
2193 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2194 reader->curnode = (xmlNodePtr) ns;
2195 goto found;
2196 }
2197 ns = ns->next;
2198 }
2199 goto not_found;
2200 }
2201 prop = reader->node->properties;
2202 while (prop != NULL) {
2203 /*
2204 * One need to have
2205 * - same attribute names
2206 * - and the attribute carrying that namespace
2207 */
2208 if ((xmlStrEqual(prop->name, localname)) &&
2209 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2210 reader->curnode = (xmlNodePtr) prop;
2211 goto found;
2212 }
2213 prop = prop->next;
2214 }
2215not_found:
2216 if (localname != NULL)
2217 xmlFree(localname);
2218 if (prefix != NULL)
2219 xmlFree(prefix);
2220 return(0);
2221
2222found:
2223 if (localname != NULL)
2224 xmlFree(localname);
2225 if (prefix != NULL)
2226 xmlFree(prefix);
2227 return(1);
2228}
2229
2230/**
2231 * xmlTextReaderMoveToAttributeNs:
2232 * @reader: the xmlTextReaderPtr used
2233 * @localName: the local name of the attribute.
2234 * @namespaceURI: the namespace URI of the attribute.
2235 *
2236 * Moves the position of the current instance to the attribute with the
2237 * specified local name and namespace URI.
2238 *
2239 * Returns 1 in case of success, -1 in case of error, 0 if not found
2240 */
2241int
2242xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2243 const xmlChar *localName, const xmlChar *namespaceURI) {
2244 xmlAttrPtr prop;
2245 xmlNodePtr node;
2246
2247 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2248 return(-1);
2249 if (reader->node == NULL)
2250 return(-1);
2251 if (reader->node->type != XML_ELEMENT_NODE)
2252 return(0);
2253 node = reader->node;
2254
2255 /*
2256 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2257 * namespace name associated to "xmlns"
2258 */
2259 prop = node->properties;
2260 while (prop != NULL) {
2261 /*
2262 * One need to have
2263 * - same attribute names
2264 * - and the attribute carrying that namespace
2265 */
2266 if (xmlStrEqual(prop->name, localName) &&
2267 ((prop->ns != NULL) &&
2268 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2269 reader->curnode = (xmlNodePtr) prop;
2270 return(1);
2271 }
2272 prop = prop->next;
2273 }
2274 return(0);
2275}
2276
2277/**
2278 * xmlTextReaderMoveToFirstAttribute:
2279 * @reader: the xmlTextReaderPtr used
2280 *
2281 * Moves the position of the current instance to the first attribute
2282 * associated with the current node.
2283 *
2284 * Returns 1 in case of success, -1 in case of error, 0 if not found
2285 */
2286int
2287xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2288 if (reader == NULL)
2289 return(-1);
2290 if (reader->node == NULL)
2291 return(-1);
2292 if (reader->node->type != XML_ELEMENT_NODE)
2293 return(0);
2294
2295 if (reader->node->nsDef != NULL) {
2296 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2297 return(1);
2298 }
2299 if (reader->node->properties != NULL) {
2300 reader->curnode = (xmlNodePtr) reader->node->properties;
2301 return(1);
2302 }
2303 return(0);
2304}
2305
2306/**
2307 * xmlTextReaderMoveToNextAttribute:
2308 * @reader: the xmlTextReaderPtr used
2309 *
2310 * Moves the position of the current instance to the next attribute
2311 * associated with the current node.
2312 *
2313 * Returns 1 in case of success, -1 in case of error, 0 if not found
2314 */
2315int
2316xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2317 if (reader == NULL)
2318 return(-1);
2319 if (reader->node == NULL)
2320 return(-1);
2321 if (reader->node->type != XML_ELEMENT_NODE)
2322 return(0);
2323 if (reader->curnode == NULL)
2324 return(xmlTextReaderMoveToFirstAttribute(reader));
2325
2326 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2327 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2328 if (ns->next != NULL) {
2329 reader->curnode = (xmlNodePtr) ns->next;
2330 return(1);
2331 }
2332 if (reader->node->properties != NULL) {
2333 reader->curnode = (xmlNodePtr) reader->node->properties;
2334 return(1);
2335 }
2336 return(0);
2337 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2338 (reader->curnode->next != NULL)) {
2339 reader->curnode = reader->curnode->next;
2340 return(1);
2341 }
2342 return(0);
2343}
2344
2345/**
2346 * xmlTextReaderMoveToElement:
2347 * @reader: the xmlTextReaderPtr used
2348 *
2349 * Moves the position of the current instance to the node that
2350 * contains the current Attribute node.
2351 *
2352 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2353 */
2354int
2355xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2356 if (reader == NULL)
2357 return(-1);
2358 if (reader->node == NULL)
2359 return(-1);
2360 if (reader->node->type != XML_ELEMENT_NODE)
2361 return(0);
2362 if (reader->curnode != NULL) {
2363 reader->curnode = NULL;
2364 return(1);
2365 }
2366 return(0);
2367}
2368
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002369/**
2370 * xmlTextReaderReadAttributeValue:
2371 * @reader: the xmlTextReaderPtr used
2372 *
2373 * Parses an attribute value into one or more Text and EntityReference nodes.
2374 *
2375 * Returns 1 in case of success, 0 if the reader was not positionned on an
2376 * ttribute node or all the attribute values have been read, or -1
2377 * in case of error.
2378 */
2379int
2380xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2381 if (reader == NULL)
2382 return(-1);
2383 if (reader->node == NULL)
2384 return(-1);
2385 if (reader->curnode == NULL)
2386 return(0);
2387 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2388 if (reader->curnode->children == NULL)
2389 return(0);
2390 reader->curnode = reader->curnode->children;
2391 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2392 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2393
2394 if (reader->faketext == NULL) {
2395 reader->faketext = xmlNewDocText(reader->node->doc,
2396 ns->href);
2397 } else {
2398 if (reader->faketext->content != NULL)
2399 xmlFree(reader->faketext->content);
2400 reader->faketext->content = xmlStrdup(ns->href);
2401 }
2402 reader->curnode = reader->faketext;
2403 } else {
2404 if (reader->curnode->next == NULL)
2405 return(0);
2406 reader->curnode = reader->curnode->next;
2407 }
2408 return(1);
2409}
2410
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002411/************************************************************************
2412 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002413 * Acces API to the current node *
2414 * *
2415 ************************************************************************/
2416/**
2417 * xmlTextReaderAttributeCount:
2418 * @reader: the xmlTextReaderPtr used
2419 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002420 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002421 *
2422 * Returns 0 i no attributes, -1 in case of error or the attribute count
2423 */
2424int
2425xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2426 int ret;
2427 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002428 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002429 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002430
2431 if (reader == NULL)
2432 return(-1);
2433 if (reader->node == NULL)
2434 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002435
2436 if (reader->curnode != NULL)
2437 node = reader->curnode;
2438 else
2439 node = reader->node;
2440
2441 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002442 return(0);
2443 if ((reader->state == XML_TEXTREADER_END) ||
2444 (reader->state == XML_TEXTREADER_BACKTRACK))
2445 return(0);
2446 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002447 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002448 while (attr != NULL) {
2449 ret++;
2450 attr = attr->next;
2451 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002452 ns = node->nsDef;
2453 while (ns != NULL) {
2454 ret++;
2455 ns = ns->next;
2456 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002457 return(ret);
2458}
2459
2460/**
2461 * xmlTextReaderNodeType:
2462 * @reader: the xmlTextReaderPtr used
2463 *
2464 * Get the node type of the current node
2465 * Reference:
2466 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2467 *
2468 * Returns the xmlNodeType of the current node or -1 in case of error
2469 */
2470int
2471xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002472 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002473
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002474 if (reader == NULL)
2475 return(-1);
2476 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002477 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002478 if (reader->curnode != NULL)
2479 node = reader->curnode;
2480 else
2481 node = reader->node;
2482 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002483 case XML_ELEMENT_NODE:
2484 if ((reader->state == XML_TEXTREADER_END) ||
2485 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002486 return(XML_READER_TYPE_END_ELEMENT);
2487 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002488 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002489 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002490 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002491 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002492 if (xmlIsBlankNode(reader->node)) {
2493 if (xmlNodeGetSpacePreserve(reader->node))
2494 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2495 else
2496 return(XML_READER_TYPE_WHITESPACE);
2497 } else {
2498 return(XML_READER_TYPE_TEXT);
2499 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002500 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002501 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002502 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002503 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002504 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002505 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002506 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002507 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002508 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002509 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002510 case XML_DOCUMENT_NODE:
2511 case XML_HTML_DOCUMENT_NODE:
2512#ifdef LIBXML_DOCB_ENABLED
2513 case XML_DOCB_DOCUMENT_NODE:
2514#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002515 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002516 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002517 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002518 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002519 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002520 case XML_DOCUMENT_TYPE_NODE:
2521 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002522 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002523
2524 case XML_ELEMENT_DECL:
2525 case XML_ATTRIBUTE_DECL:
2526 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002527 case XML_XINCLUDE_START:
2528 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002529 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002530 }
2531 return(-1);
2532}
2533
2534/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002535 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002536 * @reader: the xmlTextReaderPtr used
2537 *
2538 * Check if the current node is empty
2539 *
2540 * Returns 1 if empty, 0 if not and -1 in case of error
2541 */
2542int
2543xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2544 if ((reader == NULL) || (reader->node == NULL))
2545 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002546 if (reader->node->type != XML_ELEMENT_NODE)
2547 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002548 if (reader->curnode != NULL)
2549 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002550 if (reader->node->children != NULL)
2551 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002552 if (reader->state == XML_TEXTREADER_END)
2553 return(0);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002554 return((reader->node->_private == (void *)xmlTextReaderIsEmpty) ||
2555 (reader->node->_private == (void *)xmlTextReaderIsEmptyPreserved));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002556}
2557
2558/**
2559 * xmlTextReaderLocalName:
2560 * @reader: the xmlTextReaderPtr used
2561 *
2562 * The local name of the node.
2563 *
2564 * Returns the local name or NULL if not available
2565 */
2566xmlChar *
2567xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002568 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002569 if ((reader == NULL) || (reader->node == NULL))
2570 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002571 if (reader->curnode != NULL)
2572 node = reader->curnode;
2573 else
2574 node = reader->node;
2575 if (node->type == XML_NAMESPACE_DECL) {
2576 xmlNsPtr ns = (xmlNsPtr) node;
2577 if (ns->prefix == NULL)
2578 return(xmlStrdup(BAD_CAST "xmlns"));
2579 else
2580 return(xmlStrdup(ns->prefix));
2581 }
2582 if ((node->type != XML_ELEMENT_NODE) &&
2583 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002584 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002585 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002586}
2587
2588/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002589 * xmlTextReaderConstLocalName:
2590 * @reader: the xmlTextReaderPtr used
2591 *
2592 * The local name of the node.
2593 *
2594 * Returns the local name or NULL if not available, the
2595 * string will be deallocated with the reader.
2596 */
2597const xmlChar *
2598xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
2599 xmlNodePtr node;
2600 if ((reader == NULL) || (reader->node == NULL))
2601 return(NULL);
2602 if (reader->curnode != NULL)
2603 node = reader->curnode;
2604 else
2605 node = reader->node;
2606 if (node->type == XML_NAMESPACE_DECL) {
2607 xmlNsPtr ns = (xmlNsPtr) node;
2608 if (ns->prefix == NULL)
2609 return(CONSTSTR(BAD_CAST "xmlns"));
2610 else
2611 return(ns->prefix);
2612 }
2613 if ((node->type != XML_ELEMENT_NODE) &&
2614 (node->type != XML_ATTRIBUTE_NODE))
2615 return(xmlTextReaderConstName(reader));
2616 return(node->name);
2617}
2618
2619/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002620 * xmlTextReaderName:
2621 * @reader: the xmlTextReaderPtr used
2622 *
2623 * The qualified name of the node, equal to Prefix :LocalName.
2624 *
2625 * Returns the local name or NULL if not available
2626 */
2627xmlChar *
2628xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002629 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002630 xmlChar *ret;
2631
2632 if ((reader == NULL) || (reader->node == NULL))
2633 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002634 if (reader->curnode != NULL)
2635 node = reader->curnode;
2636 else
2637 node = reader->node;
2638 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002639 case XML_ELEMENT_NODE:
2640 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002641 if ((node->ns == NULL) ||
2642 (node->ns->prefix == NULL))
2643 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002644
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002645 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002646 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002647 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002648 return(ret);
2649 case XML_TEXT_NODE:
2650 return(xmlStrdup(BAD_CAST "#text"));
2651 case XML_CDATA_SECTION_NODE:
2652 return(xmlStrdup(BAD_CAST "#cdata-section"));
2653 case XML_ENTITY_NODE:
2654 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002655 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002656 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002657 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002658 case XML_COMMENT_NODE:
2659 return(xmlStrdup(BAD_CAST "#comment"));
2660 case XML_DOCUMENT_NODE:
2661 case XML_HTML_DOCUMENT_NODE:
2662#ifdef LIBXML_DOCB_ENABLED
2663 case XML_DOCB_DOCUMENT_NODE:
2664#endif
2665 return(xmlStrdup(BAD_CAST "#document"));
2666 case XML_DOCUMENT_FRAG_NODE:
2667 return(xmlStrdup(BAD_CAST "#document-fragment"));
2668 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002669 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002670 case XML_DOCUMENT_TYPE_NODE:
2671 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002672 return(xmlStrdup(node->name));
2673 case XML_NAMESPACE_DECL: {
2674 xmlNsPtr ns = (xmlNsPtr) node;
2675
2676 ret = xmlStrdup(BAD_CAST "xmlns");
2677 if (ns->prefix == NULL)
2678 return(ret);
2679 ret = xmlStrcat(ret, BAD_CAST ":");
2680 ret = xmlStrcat(ret, ns->prefix);
2681 return(ret);
2682 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002683
2684 case XML_ELEMENT_DECL:
2685 case XML_ATTRIBUTE_DECL:
2686 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002687 case XML_XINCLUDE_START:
2688 case XML_XINCLUDE_END:
2689 return(NULL);
2690 }
2691 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002692}
2693
2694/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002695 * xmlTextReaderConstName:
2696 * @reader: the xmlTextReaderPtr used
2697 *
2698 * The qualified name of the node, equal to Prefix :LocalName.
2699 *
2700 * Returns the local name or NULL if not available, the string is
2701 * deallocated with the reader.
2702 */
2703const xmlChar *
2704xmlTextReaderConstName(xmlTextReaderPtr reader) {
2705 xmlNodePtr node;
2706
2707 if ((reader == NULL) || (reader->node == NULL))
2708 return(NULL);
2709 if (reader->curnode != NULL)
2710 node = reader->curnode;
2711 else
2712 node = reader->node;
2713 switch (node->type) {
2714 case XML_ELEMENT_NODE:
2715 case XML_ATTRIBUTE_NODE:
2716 if ((node->ns == NULL) ||
2717 (node->ns->prefix == NULL))
2718 return(node->name);
2719 return(CONSTQSTR(node->ns->prefix, node->name));
2720 case XML_TEXT_NODE:
2721 return(CONSTSTR(BAD_CAST "#text"));
2722 case XML_CDATA_SECTION_NODE:
2723 return(CONSTSTR(BAD_CAST "#cdata-section"));
2724 case XML_ENTITY_NODE:
2725 case XML_ENTITY_REF_NODE:
2726 return(CONSTSTR(node->name));
2727 case XML_PI_NODE:
2728 return(CONSTSTR(node->name));
2729 case XML_COMMENT_NODE:
2730 return(CONSTSTR(BAD_CAST "#comment"));
2731 case XML_DOCUMENT_NODE:
2732 case XML_HTML_DOCUMENT_NODE:
2733#ifdef LIBXML_DOCB_ENABLED
2734 case XML_DOCB_DOCUMENT_NODE:
2735#endif
2736 return(CONSTSTR(BAD_CAST "#document"));
2737 case XML_DOCUMENT_FRAG_NODE:
2738 return(CONSTSTR(BAD_CAST "#document-fragment"));
2739 case XML_NOTATION_NODE:
2740 return(CONSTSTR(node->name));
2741 case XML_DOCUMENT_TYPE_NODE:
2742 case XML_DTD_NODE:
2743 return(CONSTSTR(node->name));
2744 case XML_NAMESPACE_DECL: {
2745 xmlNsPtr ns = (xmlNsPtr) node;
2746
2747 if (ns->prefix == NULL)
2748 return(CONSTSTR(BAD_CAST "xmlns"));
2749 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
2750 }
2751
2752 case XML_ELEMENT_DECL:
2753 case XML_ATTRIBUTE_DECL:
2754 case XML_ENTITY_DECL:
2755 case XML_XINCLUDE_START:
2756 case XML_XINCLUDE_END:
2757 return(NULL);
2758 }
2759 return(NULL);
2760}
2761
2762/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002763 * xmlTextReaderPrefix:
2764 * @reader: the xmlTextReaderPtr used
2765 *
2766 * A shorthand reference to the namespace associated with the node.
2767 *
2768 * Returns the prefix or NULL if not available
2769 */
2770xmlChar *
2771xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002772 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002773 if ((reader == NULL) || (reader->node == NULL))
2774 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002775 if (reader->curnode != NULL)
2776 node = reader->curnode;
2777 else
2778 node = reader->node;
2779 if (node->type == XML_NAMESPACE_DECL) {
2780 xmlNsPtr ns = (xmlNsPtr) node;
2781 if (ns->prefix == NULL)
2782 return(NULL);
2783 return(xmlStrdup(BAD_CAST "xmlns"));
2784 }
2785 if ((node->type != XML_ELEMENT_NODE) &&
2786 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002787 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00002788 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002789 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002790 return(NULL);
2791}
2792
2793/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002794 * xmlTextReaderConstPrefix:
2795 * @reader: the xmlTextReaderPtr used
2796 *
2797 * A shorthand reference to the namespace associated with the node.
2798 *
2799 * Returns the prefix or NULL if not available, the string is deallocated
2800 * with the reader.
2801 */
2802const xmlChar *
2803xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
2804 xmlNodePtr node;
2805 if ((reader == NULL) || (reader->node == NULL))
2806 return(NULL);
2807 if (reader->curnode != NULL)
2808 node = reader->curnode;
2809 else
2810 node = reader->node;
2811 if (node->type == XML_NAMESPACE_DECL) {
2812 xmlNsPtr ns = (xmlNsPtr) node;
2813 if (ns->prefix == NULL)
2814 return(NULL);
2815 return(CONSTSTR(BAD_CAST "xmlns"));
2816 }
2817 if ((node->type != XML_ELEMENT_NODE) &&
2818 (node->type != XML_ATTRIBUTE_NODE))
2819 return(NULL);
2820 if ((node->ns != NULL) && (node->ns->prefix != NULL))
2821 return(CONSTSTR(node->ns->prefix));
2822 return(NULL);
2823}
2824
2825/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002826 * xmlTextReaderNamespaceUri:
2827 * @reader: the xmlTextReaderPtr used
2828 *
2829 * The URI defining the namespace associated with the node.
2830 *
2831 * Returns the namespace URI or NULL if not available
2832 */
2833xmlChar *
2834xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002835 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002836 if ((reader == NULL) || (reader->node == NULL))
2837 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002838 if (reader->curnode != NULL)
2839 node = reader->curnode;
2840 else
2841 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00002842 if (node->type == XML_NAMESPACE_DECL)
2843 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002844 if ((node->type != XML_ELEMENT_NODE) &&
2845 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002846 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002847 if (node->ns != NULL)
2848 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002849 return(NULL);
2850}
2851
2852/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002853 * xmlTextReaderConstNamespaceUri:
2854 * @reader: the xmlTextReaderPtr used
2855 *
2856 * The URI defining the namespace associated with the node.
2857 *
2858 * Returns the namespace URI or NULL if not available, the string
2859 * will be deallocated with the reader
2860 */
2861const xmlChar *
2862xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
2863 xmlNodePtr node;
2864 if ((reader == NULL) || (reader->node == NULL))
2865 return(NULL);
2866 if (reader->curnode != NULL)
2867 node = reader->curnode;
2868 else
2869 node = reader->node;
2870 if (node->type == XML_NAMESPACE_DECL)
2871 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
2872 if ((node->type != XML_ELEMENT_NODE) &&
2873 (node->type != XML_ATTRIBUTE_NODE))
2874 return(NULL);
2875 if (node->ns != NULL)
2876 return(CONSTSTR(node->ns->href));
2877 return(NULL);
2878}
2879
2880/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002881 * xmlTextReaderBaseUri:
2882 * @reader: the xmlTextReaderPtr used
2883 *
2884 * The base URI of the node.
2885 *
2886 * Returns the base URI or NULL if not available
2887 */
2888xmlChar *
2889xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
2890 if ((reader == NULL) || (reader->node == NULL))
2891 return(NULL);
2892 return(xmlNodeGetBase(NULL, reader->node));
2893}
2894
2895/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00002896 * xmlTextReaderConstBaseUri:
2897 * @reader: the xmlTextReaderPtr used
2898 *
2899 * The base URI of the node.
2900 *
2901 * Returns the base URI or NULL if not available, the string
2902 * will be deallocated with the reader
2903 */
2904const xmlChar *
2905xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
2906 xmlChar *tmp;
2907 const xmlChar *ret;
2908
2909 if ((reader == NULL) || (reader->node == NULL))
2910 return(NULL);
2911 tmp = xmlNodeGetBase(NULL, reader->node);
2912 if (tmp == NULL)
2913 return(NULL);
2914 ret = CONSTSTR(tmp);
2915 xmlFree(tmp);
2916 return(ret);
2917}
2918
2919/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002920 * xmlTextReaderDepth:
2921 * @reader: the xmlTextReaderPtr used
2922 *
2923 * The depth of the node in the tree.
2924 *
2925 * Returns the depth or -1 in case of error
2926 */
2927int
2928xmlTextReaderDepth(xmlTextReaderPtr reader) {
2929 if (reader == NULL)
2930 return(-1);
2931 if (reader->node == NULL)
2932 return(0);
2933
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002934 if (reader->curnode != NULL) {
2935 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
2936 (reader->curnode->type == XML_NAMESPACE_DECL))
2937 return(reader->depth + 1);
2938 return(reader->depth + 2);
2939 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002940 return(reader->depth);
2941}
2942
2943/**
2944 * xmlTextReaderHasAttributes:
2945 * @reader: the xmlTextReaderPtr used
2946 *
2947 * Whether the node has attributes.
2948 *
2949 * Returns 1 if true, 0 if false, and -1 in case or error
2950 */
2951int
2952xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002953 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002954 if (reader == NULL)
2955 return(-1);
2956 if (reader->node == NULL)
2957 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002958 if (reader->curnode != NULL)
2959 node = reader->curnode;
2960 else
2961 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002962
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002963 if ((node->type == XML_ELEMENT_NODE) &&
2964 (node->properties != NULL))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002965 return(1);
2966 /* TODO: handle the xmlDecl */
2967 return(0);
2968}
2969
2970/**
2971 * xmlTextReaderHasValue:
2972 * @reader: the xmlTextReaderPtr used
2973 *
2974 * Whether the node can have a text value.
2975 *
2976 * Returns 1 if true, 0 if false, and -1 in case or error
2977 */
2978int
2979xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002980 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002981 if (reader == NULL)
2982 return(-1);
2983 if (reader->node == NULL)
2984 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002985 if (reader->curnode != NULL)
2986 node = reader->curnode;
2987 else
2988 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002989
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002990 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002991 case XML_ATTRIBUTE_NODE:
2992 case XML_TEXT_NODE:
2993 case XML_CDATA_SECTION_NODE:
2994 case XML_PI_NODE:
2995 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00002996 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00002997 return(1);
2998 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00002999 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003000 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003001 return(0);
3002}
3003
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003004/**
3005 * xmlTextReaderValue:
3006 * @reader: the xmlTextReaderPtr used
3007 *
3008 * Provides the text value of the node if present
3009 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003010 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003011 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003012 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003013xmlChar *
3014xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003015 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003016 if (reader == NULL)
3017 return(NULL);
3018 if (reader->node == NULL)
3019 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003020 if (reader->curnode != NULL)
3021 node = reader->curnode;
3022 else
3023 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003024
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003025 switch (node->type) {
3026 case XML_NAMESPACE_DECL:
3027 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003028 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003029 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003030
3031 if (attr->parent != NULL)
3032 return (xmlNodeListGetString
3033 (attr->parent->doc, attr->children, 1));
3034 else
3035 return (xmlNodeListGetString(NULL, attr->children, 1));
3036 break;
3037 }
3038 case XML_TEXT_NODE:
3039 case XML_CDATA_SECTION_NODE:
3040 case XML_PI_NODE:
3041 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003042 if (node->content != NULL)
3043 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003044 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003045 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003046 }
3047 return(NULL);
3048}
3049
3050/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003051 * xmlTextReaderConstValue:
3052 * @reader: the xmlTextReaderPtr used
3053 *
3054 * Provides the text value of the node if present
3055 *
3056 * Returns the string or NULL if not available. The result will be
3057 * deallocated on the next Read() operation.
3058 */
3059const xmlChar *
3060xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3061 xmlNodePtr node;
3062 if (reader == NULL)
3063 return(NULL);
3064 if (reader->node == NULL)
3065 return(NULL);
3066 if (reader->curnode != NULL)
3067 node = reader->curnode;
3068 else
3069 node = reader->node;
3070
3071 switch (node->type) {
3072 case XML_NAMESPACE_DECL:
3073 return(((xmlNsPtr) node)->href);
3074 case XML_ATTRIBUTE_NODE:{
3075 xmlAttrPtr attr = (xmlAttrPtr) node;
3076
3077 if ((attr->children != NULL) &&
3078 (attr->children->type == XML_TEXT_NODE) &&
3079 (attr->children->next == NULL))
3080 return(attr->children->content);
3081 else {
3082 reader->buffer->use = 0;
3083 xmlNodeBufGetContent(reader->buffer, node);
3084 return(reader->buffer->content);
3085 }
3086 break;
3087 }
3088 case XML_TEXT_NODE:
3089 case XML_CDATA_SECTION_NODE:
3090 case XML_PI_NODE:
3091 case XML_COMMENT_NODE:
3092 return(node->content);
3093 default:
3094 break;
3095 }
3096 return(NULL);
3097}
3098
3099/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003100 * xmlTextReaderIsDefault:
3101 * @reader: the xmlTextReaderPtr used
3102 *
3103 * Whether an Attribute node was generated from the default value
3104 * defined in the DTD or schema.
3105 *
3106 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3107 */
3108int
3109xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3110 if (reader == NULL)
3111 return(-1);
3112 return(0);
3113}
3114
3115/**
3116 * xmlTextReaderQuoteChar:
3117 * @reader: the xmlTextReaderPtr used
3118 *
3119 * The quotation mark character used to enclose the value of an attribute.
3120 *
3121 * Returns " or ' and -1 in case of error
3122 */
3123int
3124xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3125 if (reader == NULL)
3126 return(-1);
3127 /* TODO maybe lookup the attribute value for " first */
3128 return((int) '"');
3129}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003130
3131/**
3132 * xmlTextReaderXmlLang:
3133 * @reader: the xmlTextReaderPtr used
3134 *
3135 * The xml:lang scope within which the node resides.
3136 *
3137 * Returns the xml:lang value or NULL if none exists.
3138 */
3139xmlChar *
3140xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3141 if (reader == NULL)
3142 return(NULL);
3143 if (reader->node == NULL)
3144 return(NULL);
3145 return(xmlNodeGetLang(reader->node));
3146}
3147
Daniel Veillard67df8092002-12-16 22:04:11 +00003148/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003149 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003150 * @reader: the xmlTextReaderPtr used
3151 *
3152 * The xml:lang scope within which the node resides.
3153 *
3154 * Returns the xml:lang value or NULL if none exists.
3155 */
3156const xmlChar *
3157xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3158 xmlChar *tmp;
3159 const xmlChar *ret;
3160
3161 if (reader == NULL)
3162 return(NULL);
3163 if (reader->node == NULL)
3164 return(NULL);
3165 tmp = xmlNodeGetLang(reader->node);
3166 if (tmp == NULL)
3167 return(NULL);
3168 ret = CONSTSTR(tmp);
3169 xmlFree(tmp);
3170 return(ret);
3171}
3172
3173/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003174 * xmlTextReaderConstString:
3175 * @reader: the xmlTextReaderPtr used
3176 * @str: the string to intern.
3177 *
3178 * Get an interned string from the reader, allows for example to
3179 * speedup string name comparisons
3180 *
3181 * Returns an interned copy of the string or NULL in case of error. The
3182 * string will be deallocated with the reader.
3183 */
3184const xmlChar *
3185xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3186 if (reader == NULL)
3187 return(NULL);
3188 return(CONSTSTR(str));
3189}
3190
3191/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003192 * xmlTextReaderNormalization:
3193 * @reader: the xmlTextReaderPtr used
3194 *
3195 * The value indicating whether to normalize white space and attribute values.
3196 * Since attribute value and end of line normalizations are a MUST in the XML
3197 * specification only the value true is accepted. The broken bahaviour of
3198 * accepting out of range character entities like &#0; is of course not
3199 * supported either.
3200 *
3201 * Returns 1 or -1 in case of error.
3202 */
3203int
3204xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3205 if (reader == NULL)
3206 return(-1);
3207 return(1);
3208}
3209
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003210/************************************************************************
3211 * *
3212 * Extensions to the base APIs *
3213 * *
3214 ************************************************************************/
3215
3216/**
3217 * xmlTextReaderSetParserProp:
3218 * @reader: the xmlTextReaderPtr used
3219 * @prop: the xmlParserProperties to set
3220 * @value: usually 0 or 1 to (de)activate it
3221 *
3222 * Change the parser processing behaviour by changing some of its internal
3223 * properties. Note that some properties can only be changed before any
3224 * read has been done.
3225 *
3226 * Returns 0 if the call was successful, or -1 in case of error
3227 */
3228int
3229xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3230 xmlParserProperties p = (xmlParserProperties) prop;
3231 xmlParserCtxtPtr ctxt;
3232
3233 if ((reader == NULL) || (reader->ctxt == NULL))
3234 return(-1);
3235 ctxt = reader->ctxt;
3236
3237 switch (p) {
3238 case XML_PARSER_LOADDTD:
3239 if (value != 0) {
3240 if (ctxt->loadsubset == 0) {
3241 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3242 return(-1);
3243 ctxt->loadsubset = XML_DETECT_IDS;
3244 }
3245 } else {
3246 ctxt->loadsubset = 0;
3247 }
3248 return(0);
3249 case XML_PARSER_DEFAULTATTRS:
3250 if (value != 0) {
3251 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3252 } else {
3253 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3254 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3255 }
3256 return(0);
3257 case XML_PARSER_VALIDATE:
3258 if (value != 0) {
3259 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003260 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003261 } else {
3262 ctxt->validate = 0;
3263 }
3264 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003265 case XML_PARSER_SUBST_ENTITIES:
3266 if (value != 0) {
3267 ctxt->replaceEntities = 1;
3268 } else {
3269 ctxt->replaceEntities = 0;
3270 }
3271 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003272 }
3273 return(-1);
3274}
3275
3276/**
3277 * xmlTextReaderGetParserProp:
3278 * @reader: the xmlTextReaderPtr used
3279 * @prop: the xmlParserProperties to get
3280 *
3281 * Read the parser internal property.
3282 *
3283 * Returns the value, usually 0 or 1, or -1 in case of error.
3284 */
3285int
3286xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3287 xmlParserProperties p = (xmlParserProperties) prop;
3288 xmlParserCtxtPtr ctxt;
3289
3290 if ((reader == NULL) || (reader->ctxt == NULL))
3291 return(-1);
3292 ctxt = reader->ctxt;
3293
3294 switch (p) {
3295 case XML_PARSER_LOADDTD:
3296 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3297 return(1);
3298 return(0);
3299 case XML_PARSER_DEFAULTATTRS:
3300 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3301 return(1);
3302 return(0);
3303 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003304 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003305 case XML_PARSER_SUBST_ENTITIES:
3306 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003307 }
3308 return(-1);
3309}
3310
Daniel Veillarde18fc182002-12-28 22:56:33 +00003311/**
3312 * xmlTextReaderCurrentNode:
3313 * @reader: the xmlTextReaderPtr used
3314 *
3315 * Hacking interface allowing to get the xmlNodePtr correponding to the
3316 * current node being accessed by the xmlTextReader. This is dangerous
3317 * because the underlying node may be destroyed on the next Reads.
3318 *
3319 * Returns the xmlNodePtr or NULL in case of error.
3320 */
3321xmlNodePtr
3322xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3323 if (reader == NULL)
3324 return(NULL);
3325
3326 if (reader->curnode != NULL)
3327 return(reader->curnode);
3328 return(reader->node);
3329}
3330
3331/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003332 * xmlTextReaderPreserve:
3333 * @reader: the xmlTextReaderPtr used
3334 *
3335 *
3336 * current node being accessed by the xmlTextReader. This is dangerous
3337 * because the underlying node may be destroyed on the next Reads.
3338 *
3339 * Returns the xmlNodePtr or NULL in case of error.
3340 */
3341xmlNodePtr
3342xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3343 xmlNodePtr cur, parent;
3344
3345 if (reader == NULL)
3346 return(NULL);
3347
3348 if (reader->curnode != NULL)
3349 cur = reader->curnode;
3350 else
3351 cur = reader->node;
3352 if (cur == NULL)
3353 return(NULL);
3354 if (cur->_private == (void *)xmlTextReaderIsEmpty)
3355 cur->_private = (void *)xmlTextReaderIsEmptyPreserved;
3356 else
3357 cur->_private = (void *)xmlTextReaderIsPreserved;
3358
3359 parent = cur->parent;;
3360 while (parent != NULL) {
3361 parent->_private = (void *)xmlTextReaderIsPreserved;
3362 parent = parent->parent;
3363 }
3364 return(cur);
3365}
3366
3367/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003368 * xmlTextReaderCurrentDoc:
3369 * @reader: the xmlTextReaderPtr used
3370 *
3371 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003372 * current document being accessed by the xmlTextReader.
3373 * NOTE: as a result of this call, the reader will not destroy the
3374 * associated XML document and calling xmlFreeDoc() on the result
3375 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003376 *
3377 * Returns the xmlDocPtr or NULL in case of error.
3378 */
3379xmlDocPtr
3380xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003381 if (reader == NULL)
3382 return(NULL);
3383 if (reader->doc != NULL)
3384 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003385 if ((reader == NULL) || (reader->ctxt == NULL) ||
3386 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003387 return(NULL);
3388
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003389 reader->preserve = 1;
3390 if ((reader->ctxt->myDoc->dict != NULL) &&
3391 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3392 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003393 return(reader->ctxt->myDoc);
3394}
3395
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003396#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003397/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003398 * xmlTextReaderRelaxNGSetSchema:
3399 * @reader: the xmlTextReaderPtr used
3400 * @schema: a precompiled RelaxNG schema
3401 *
3402 * Use RelaxNG to validate the document as it is processed.
3403 * Activation is only possible before the first Read().
3404 * if @schema is NULL, then RelaxNG validation is desactivated.
3405 @ The @schema should not be freed until the reader is deallocated
3406 * or its use has been deactivated.
3407 *
3408 * Returns 0 in case the RelaxNG validation could be (des)activated and
3409 * -1 in case of error.
3410 */
3411int
3412xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3413 if (schema == NULL) {
3414 if (reader->rngSchemas != NULL) {
3415 xmlRelaxNGFree(reader->rngSchemas);
3416 reader->rngSchemas = NULL;
3417 }
3418 if (reader->rngValidCtxt != NULL) {
3419 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3420 reader->rngValidCtxt = NULL;
3421 }
3422 return(0);
3423 }
3424 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3425 return(-1);
3426 if (reader->rngSchemas != NULL) {
3427 xmlRelaxNGFree(reader->rngSchemas);
3428 reader->rngSchemas = NULL;
3429 }
3430 if (reader->rngValidCtxt != NULL) {
3431 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3432 reader->rngValidCtxt = NULL;
3433 }
3434 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3435 if (reader->rngValidCtxt == NULL)
3436 return(-1);
3437 if (reader->errorFunc != NULL) {
3438 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3439 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3440 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3441 reader->errorFuncArg);
3442 }
3443 reader->rngValidErrors = 0;
3444 reader->rngFullNode = NULL;
3445 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3446 return(0);
3447}
3448
3449/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003450 * xmlTextReaderRelaxNGValidate:
3451 * @reader: the xmlTextReaderPtr used
3452 * @rng: the path to a RelaxNG schema or NULL
3453 *
3454 * Use RelaxNG to validate the document as it is processed.
3455 * Activation is only possible before the first Read().
3456 * if @rng is NULL, then RelaxNG validation is desactivated.
3457 *
3458 * Returns 0 in case the RelaxNG validation could be (des)activated and
3459 * -1 in case of error.
3460 */
3461int
3462xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3463 xmlRelaxNGParserCtxtPtr ctxt;
3464
3465 if (reader == NULL)
3466 return(-1);
3467
3468 if (rng == NULL) {
3469 if (reader->rngSchemas != NULL) {
3470 xmlRelaxNGFree(reader->rngSchemas);
3471 reader->rngSchemas = NULL;
3472 }
3473 if (reader->rngValidCtxt != NULL) {
3474 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3475 reader->rngValidCtxt = NULL;
3476 }
3477 return(0);
3478 }
3479 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3480 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003481 if (reader->rngSchemas != NULL) {
3482 xmlRelaxNGFree(reader->rngSchemas);
3483 reader->rngSchemas = NULL;
3484 }
3485 if (reader->rngValidCtxt != NULL) {
3486 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3487 reader->rngValidCtxt = NULL;
3488 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003489 ctxt = xmlRelaxNGNewParserCtxt(rng);
3490 if (reader->errorFunc != NULL) {
3491 xmlRelaxNGSetParserErrors(ctxt,
3492 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3493 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3494 reader->errorFuncArg);
3495 }
3496 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3497 xmlRelaxNGFreeParserCtxt(ctxt);
3498 if (reader->rngSchemas == NULL)
3499 return(-1);
3500 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3501 if (reader->rngValidCtxt == NULL)
3502 return(-1);
3503 if (reader->errorFunc != NULL) {
3504 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3505 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3506 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3507 reader->errorFuncArg);
3508 }
3509 reader->rngValidErrors = 0;
3510 reader->rngFullNode = NULL;
3511 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3512 return(0);
3513}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003514#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003515
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003516/************************************************************************
3517 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003518 * Error Handling Extensions *
3519 * *
3520 ************************************************************************/
3521
3522/* helper to build a xmlMalloc'ed string from a format and va_list */
3523static char *
3524xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3525 int size;
3526 int chars;
3527 char *larger;
3528 char *str;
3529
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003530 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003531 if (str == NULL) {
3532 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3533 return NULL;
3534 }
3535
3536 size = 150;
3537
3538 while (1) {
3539 chars = vsnprintf(str, size, msg, ap);
3540 if ((chars > -1) && (chars < size))
3541 break;
3542 if (chars > -1)
3543 size += chars + 1;
3544 else
3545 size += 100;
3546 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3547 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3548 xmlFree(str);
3549 return NULL;
3550 }
3551 str = larger;
3552 }
3553
3554 return str;
3555}
3556
Daniel Veillard417be3a2003-01-20 21:26:34 +00003557/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003558 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003559 * @locator: the xmlTextReaderLocatorPtr used
3560 *
3561 * Obtain the line number for the given locator.
3562 *
3563 * Returns the line number or -1 in case of error.
3564 */
3565int
3566xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3567 /* we know that locator is a xmlParserCtxtPtr */
3568 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3569 int ret = -1;
3570
3571 if (ctx->node != NULL) {
3572 ret = xmlGetLineNo(ctx->node);
3573 }
3574 else {
3575 /* inspired from error.c */
3576 xmlParserInputPtr input;
3577 input = ctx->input;
3578 if ((input->filename == NULL) && (ctx->inputNr > 1))
3579 input = ctx->inputTab[ctx->inputNr - 2];
3580 if (input != NULL) {
3581 ret = input->line;
3582 }
3583 else {
3584 ret = -1;
3585 }
3586 }
3587
3588 return ret;
3589}
3590
3591/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003592 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003593 * @locator: the xmlTextReaderLocatorPtr used
3594 *
3595 * Obtain the base URI for the given locator.
3596 *
3597 * Returns the base URI or NULL in case of error.
3598 */
3599xmlChar *
3600xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3601 /* we know that locator is a xmlParserCtxtPtr */
3602 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3603 xmlChar *ret = NULL;
3604
3605 if (ctx->node != NULL) {
3606 ret = xmlNodeGetBase(NULL,ctx->node);
3607 }
3608 else {
3609 /* inspired from error.c */
3610 xmlParserInputPtr input;
3611 input = ctx->input;
3612 if ((input->filename == NULL) && (ctx->inputNr > 1))
3613 input = ctx->inputTab[ctx->inputNr - 2];
3614 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003615 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003616 }
3617 else {
3618 ret = NULL;
3619 }
3620 }
3621
3622 return ret;
3623}
3624
Daniel Veillard26f70262003-01-16 22:45:08 +00003625static void
William M. Brack899e64a2003-09-26 18:03:42 +00003626xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003627 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3628 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3629
3630 if (str != NULL) {
3631 reader->errorFunc(reader->errorFuncArg,
3632 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003633 severity,
3634 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003635 xmlFree(str);
3636 }
3637}
3638
3639static void
3640xmlTextReaderError(void *ctxt, const char *msg, ...) {
3641 va_list ap;
3642
3643 va_start(ap,msg);
3644 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003645 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003646 xmlTextReaderBuildMessage(msg,ap));
3647 va_end(ap);
3648
3649}
3650
3651static void
3652xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3653 va_list ap;
3654
3655 va_start(ap,msg);
3656 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003657 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003658 xmlTextReaderBuildMessage(msg,ap));
3659 va_end(ap);
3660}
3661
3662static void
3663xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3664 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003665 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003666
Daniel Veillard417be3a2003-01-20 21:26:34 +00003667 if ((len > 1) && (msg[len - 2] != ':')) {
3668 /*
3669 * some callbacks only report locator information:
3670 * skip them (mimicking behaviour in error.c)
3671 */
3672 va_start(ap,msg);
3673 xmlTextReaderGenericError(ctxt,
3674 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3675 xmlTextReaderBuildMessage(msg,ap));
3676 va_end(ap);
3677 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003678}
3679
3680static void
3681xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3682 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003683 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003684
Daniel Veillard417be3a2003-01-20 21:26:34 +00003685 if ((len != 0) && (msg[len - 1] != ':')) {
3686 /*
3687 * some callbacks only report locator information:
3688 * skip them (mimicking behaviour in error.c)
3689 */
3690 va_start(ap,msg);
3691 xmlTextReaderGenericError(ctxt,
3692 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3693 xmlTextReaderBuildMessage(msg,ap));
3694 va_end(ap);
3695 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003696}
3697
3698/**
3699 * xmlTextReaderSetErrorHandler:
3700 * @reader: the xmlTextReaderPtr used
3701 * @f: the callback function to call on error and warnings
3702 * @arg: a user argument to pass to the callback function
3703 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003704 * Register a callback function that will be called on error and warnings.
3705 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003706 * If @f is NULL, the default error and warning handlers are restored.
3707 */
3708void
3709xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3710 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003711 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003712 if (f != NULL) {
3713 reader->ctxt->sax->error = xmlTextReaderError;
3714 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3715 reader->ctxt->sax->warning = xmlTextReaderWarning;
3716 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3717 reader->errorFunc = f;
3718 reader->errorFuncArg = arg;
3719 }
3720 else {
3721 /* restore defaults */
3722 reader->ctxt->sax->error = xmlParserError;
3723 reader->ctxt->vctxt.error = xmlParserValidityError;
3724 reader->ctxt->sax->warning = xmlParserWarning;
3725 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3726 reader->errorFunc = NULL;
3727 reader->errorFuncArg = NULL;
3728 }
3729}
3730
Daniel Veillard417be3a2003-01-20 21:26:34 +00003731/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003732 * xmlTextReaderIsValid:
3733 * @reader: the xmlTextReaderPtr used
3734 *
3735 * Retrieve the validity status from the parser context
3736 *
3737 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3738 */
3739int
3740xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003741 if (reader == NULL) return(-1);
3742#ifdef LIBXML_SCHEMAS_ENABLED
3743 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3744 return(reader->rngValidErrors == 0);
3745#endif
3746 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3747 (reader->ctxt != NULL))
3748 return(reader->ctxt->valid);
3749 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003750}
3751
3752/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003753 * xmlTextReaderGetErrorHandler:
3754 * @reader: the xmlTextReaderPtr used
3755 * @f: the callback function or NULL is no callback has been registered
3756 * @arg: a user argument
3757 *
3758 * Retrieve the error callback function and user argument.
3759 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003760void
3761xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3762 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003763 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003764 *f = reader->errorFunc;
3765 *arg = reader->errorFuncArg;
3766}
3767
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003768
3769/************************************************************************
3770 * *
3771 * New set (2.6.0) of simpler and more flexible APIs *
3772 * *
3773 ************************************************************************/
3774
3775/**
3776 * xmlTextReaderSetup:
3777 * @reader: an XML reader
3778 * @URL: the base URL to use for the document
3779 * @encoding: the document encoding, or NULL
3780 * @options: a combination of xmlParserOption(s)
3781 * @reuse: keep the context for reuse
3782 *
3783 * Setup an XML reader with new options
3784 *
3785 * Returns 0 in case of success and -1 in case of error.
3786 */
3787static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003788xmlTextReaderSetup(xmlTextReaderPtr reader,
3789 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003790 const char *encoding, int options)
3791{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003792 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003793 return (-1);
3794
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003795 reader->doc = NULL;
3796 reader->entNr = 0;
3797 if ((input != NULL) && (reader->input != NULL) &&
3798 (reader->allocs & XML_TEXTREADER_INPUT)) {
3799 xmlFreeParserInputBuffer(reader->input);
3800 reader->input = NULL;
3801 reader->allocs -= XML_TEXTREADER_INPUT;
3802 }
3803 if (input != NULL) {
3804 reader->input = input;
3805 reader->allocs |= XML_TEXTREADER_INPUT;
3806 }
3807 if (reader->buffer == NULL)
3808 reader->buffer = xmlBufferCreateSize(100);
3809 if (reader->buffer == NULL) {
3810 xmlGenericError(xmlGenericErrorContext,
3811 "xmlTextReaderSetup : malloc failed\n");
3812 return (-1);
3813 }
3814 if (reader->sax == NULL)
3815 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
3816 if (reader->sax == NULL) {
3817 xmlGenericError(xmlGenericErrorContext,
3818 "xmlTextReaderSetup : malloc failed\n");
3819 return (-1);
3820 }
3821 xmlSAXVersion(reader->sax, 2);
3822 reader->startElement = reader->sax->startElement;
3823 reader->sax->startElement = xmlTextReaderStartElement;
3824 reader->endElement = reader->sax->endElement;
3825 reader->sax->endElement = xmlTextReaderEndElement;
3826#ifdef LIBXML_SAX1_ENABLED
3827 if (reader->sax->initialized == XML_SAX2_MAGIC) {
3828#endif /* LIBXML_SAX1_ENABLED */
3829 reader->startElementNs = reader->sax->startElementNs;
3830 reader->sax->startElementNs = xmlTextReaderStartElementNs;
3831 reader->endElementNs = reader->sax->endElementNs;
3832 reader->sax->endElementNs = xmlTextReaderEndElementNs;
3833#ifdef LIBXML_SAX1_ENABLED
3834 } else {
3835 reader->startElementNs = NULL;
3836 reader->endElementNs = NULL;
3837 }
3838#endif /* LIBXML_SAX1_ENABLED */
3839 reader->characters = reader->sax->characters;
3840 reader->sax->characters = xmlTextReaderCharacters;
3841 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
3842 reader->cdataBlock = reader->sax->cdataBlock;
3843 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
3844
3845 reader->mode = XML_TEXTREADER_MODE_INITIAL;
3846 reader->node = NULL;
3847 reader->curnode = NULL;
3848 if (input != NULL) {
3849 if (reader->input->buffer->use < 4) {
3850 xmlParserInputBufferRead(input, 4);
3851 }
3852 if (reader->ctxt == NULL) {
3853 if (reader->input->buffer->use >= 4) {
3854 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
3855 (const char *) reader->input->buffer->content, 4, URL);
3856 reader->base = 0;
3857 reader->cur = 4;
3858 } else {
3859 reader->ctxt =
3860 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
3861 reader->base = 0;
3862 reader->cur = 0;
3863 }
3864 } else {
3865 xmlParserInputPtr inputStream;
3866 xmlParserInputBufferPtr buf;
3867 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
3868
3869 if (reader->ctxt->myDoc != NULL)
3870 xmlDictReference(reader->ctxt->myDoc->dict);
3871 xmlCtxtReset(reader->ctxt);
3872 buf = xmlAllocParserInputBuffer(enc);
3873 if (buf == NULL) return(-1);
3874 inputStream = xmlNewInputStream(reader->ctxt);
3875 if (inputStream == NULL) {
3876 xmlFreeParserInputBuffer(buf);
3877 return(-1);
3878 }
3879
3880 if (URL == NULL)
3881 inputStream->filename = NULL;
3882 else
3883 inputStream->filename = (char *)
3884 xmlCanonicPath((const xmlChar *) URL);
3885 inputStream->buf = buf;
3886 inputStream->base = inputStream->buf->buffer->content;
3887 inputStream->cur = inputStream->buf->buffer->content;
3888 inputStream->end =
3889 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
3890
3891 inputPush(reader->ctxt, inputStream);
3892 reader->cur = 0;
3893 }
3894 if (reader->ctxt == NULL) {
3895 xmlGenericError(xmlGenericErrorContext,
3896 "xmlTextReaderSetup : malloc failed\n");
3897 return (-1);
3898 }
3899 }
3900 if (reader->dict != NULL) {
3901 if (reader->ctxt->dict != NULL) {
3902 if (reader->dict != reader->ctxt->dict) {
3903 xmlDictFree(reader->dict);
3904 reader->dict = reader->ctxt->dict;
3905 }
3906 } else {
3907 reader->ctxt->dict = reader->dict;
3908 }
3909 } else {
3910 if (reader->ctxt->dict == NULL)
3911 reader->ctxt->dict = xmlDictCreate();
3912 reader->dict = reader->ctxt->dict;
3913 }
3914 reader->ctxt->_private = reader;
3915 reader->ctxt->linenumbers = 1;
3916 reader->ctxt->dictNames = 1;
3917 /*
3918 * use the parser dictionnary to allocate all elements and attributes names
3919 */
3920 reader->ctxt->docdict = 1;
3921
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003922 xmlCtxtUseOptions(reader->ctxt, options);
3923 if (encoding != NULL) {
3924 xmlCharEncodingHandlerPtr hdlr;
3925
3926 hdlr = xmlFindCharEncodingHandler(encoding);
3927 if (hdlr != NULL)
3928 xmlSwitchToEncoding(reader->ctxt, hdlr);
3929 }
3930 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
3931 (reader->ctxt->input->filename == NULL))
3932 reader->ctxt->input->filename = (char *)
3933 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003934
3935 reader->doc = NULL;
3936
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003937 return (0);
3938}
3939
3940/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003941 * xmlReaderWalker:
3942 * @doc: a preparsed document
3943 *
3944 * Create an xmltextReader for a preparsed document.
3945 *
3946 * Returns the new reader or NULL in case of error.
3947 */
3948xmlTextReaderPtr
3949xmlReaderWalker(xmlDocPtr doc)
3950{
3951 xmlTextReaderPtr ret;
3952
3953 if (doc == NULL)
3954 return(NULL);
3955
3956 ret = xmlMalloc(sizeof(xmlTextReader));
3957 if (ret == NULL) {
3958 xmlGenericError(xmlGenericErrorContext,
3959 "xmlNewTextReader : malloc failed\n");
3960 return(NULL);
3961 }
3962 memset(ret, 0, sizeof(xmlTextReader));
3963 ret->entNr = 0;
3964 ret->input = NULL;
3965 ret->mode = XML_TEXTREADER_MODE_INITIAL;
3966 ret->node = NULL;
3967 ret->curnode = NULL;
3968 ret->base = 0;
3969 ret->cur = 0;
3970 ret->allocs = XML_TEXTREADER_CTXT;
3971 ret->doc = doc;
3972 ret->state = XML_TEXTREADER_START;
3973 ret->dict = xmlDictCreate();
3974 return(ret);
3975}
3976
3977/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003978 * xmlReaderForDoc:
3979 * @cur: a pointer to a zero terminated string
3980 * @URL: the base URL to use for the document
3981 * @encoding: the document encoding, or NULL
3982 * @options: a combination of xmlParserOption(s)
3983 *
3984 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003985 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003986 *
3987 * Returns the new reader or NULL in case of error.
3988 */
3989xmlTextReaderPtr
3990xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
3991 int options)
3992{
3993 int len;
3994
3995 if (cur == NULL)
3996 return (NULL);
3997 len = xmlStrlen(cur);
3998
3999 return (xmlReaderForMemory
4000 ((const char *) cur, len, URL, encoding, options));
4001}
4002
4003/**
4004 * xmlReaderForFile:
4005 * @filename: a file or URL
4006 * @encoding: the document encoding, or NULL
4007 * @options: a combination of xmlParserOption(s)
4008 *
4009 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004010 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004011 *
4012 * Returns the new reader or NULL in case of error.
4013 */
4014xmlTextReaderPtr
4015xmlReaderForFile(const char *filename, const char *encoding, int options)
4016{
4017 xmlTextReaderPtr reader;
4018
4019 reader = xmlNewTextReaderFilename(filename);
4020 if (reader == NULL)
4021 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004022 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004023 return (reader);
4024}
4025
4026/**
4027 * xmlReaderForMemory:
4028 * @buffer: a pointer to a char array
4029 * @size: the size of the array
4030 * @URL: the base URL to use for the document
4031 * @encoding: the document encoding, or NULL
4032 * @options: a combination of xmlParserOption(s)
4033 *
4034 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004035 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004036 *
4037 * Returns the new reader or NULL in case of error.
4038 */
4039xmlTextReaderPtr
4040xmlReaderForMemory(const char *buffer, int size, const char *URL,
4041 const char *encoding, int options)
4042{
4043 xmlTextReaderPtr reader;
4044 xmlParserInputBufferPtr buf;
4045
4046 buf =
4047 xmlParserInputBufferCreateMem(buffer, size,
4048 XML_CHAR_ENCODING_NONE);
4049 if (buf == NULL) {
4050 return (NULL);
4051 }
4052 reader = xmlNewTextReader(buf, URL);
4053 if (reader == NULL) {
4054 xmlFreeParserInputBuffer(buf);
4055 return (NULL);
4056 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004057 reader->allocs |= XML_TEXTREADER_INPUT;
4058 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004059 return (reader);
4060}
4061
4062/**
4063 * xmlReaderForFd:
4064 * @fd: an open file descriptor
4065 * @URL: the base URL to use for the document
4066 * @encoding: the document encoding, or NULL
4067 * @options: a combination of xmlParserOption(s)
4068 *
4069 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004070 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004071 *
4072 * Returns the new reader or NULL in case of error.
4073 */
4074xmlTextReaderPtr
4075xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4076{
4077 xmlTextReaderPtr reader;
4078 xmlParserInputBufferPtr input;
4079
4080 if (fd < 0)
4081 return (NULL);
4082
4083 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4084 if (input == NULL)
4085 return (NULL);
4086 reader = xmlNewTextReader(input, URL);
4087 if (reader == NULL) {
4088 xmlFreeParserInputBuffer(input);
4089 return (NULL);
4090 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004091 reader->allocs |= XML_TEXTREADER_INPUT;
4092 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004093 return (reader);
4094}
4095
4096/**
4097 * xmlReaderForIO:
4098 * @ioread: an I/O read function
4099 * @ioclose: an I/O close function
4100 * @ioctx: an I/O handler
4101 * @URL: the base URL to use for the document
4102 * @encoding: the document encoding, or NULL
4103 * @options: a combination of xmlParserOption(s)
4104 *
4105 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004106 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004107 *
4108 * Returns the new reader or NULL in case of error.
4109 */
4110xmlTextReaderPtr
4111xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4112 void *ioctx, const char *URL, const char *encoding,
4113 int options)
4114{
4115 xmlTextReaderPtr reader;
4116 xmlParserInputBufferPtr input;
4117
4118 if (ioread == NULL)
4119 return (NULL);
4120
4121 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4122 XML_CHAR_ENCODING_NONE);
4123 if (input == NULL)
4124 return (NULL);
4125 reader = xmlNewTextReader(input, URL);
4126 if (reader == NULL) {
4127 xmlFreeParserInputBuffer(input);
4128 return (NULL);
4129 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004130 reader->allocs |= XML_TEXTREADER_INPUT;
4131 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004132 return (reader);
4133}
4134
4135/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004136 * xmlReaderNewWalker:
4137 * @reader: an XML reader
4138 * @doc: a preparsed document
4139 *
4140 * Setup an xmltextReader to parse a preparsed XML document.
4141 * This reuses the existing @reader xmlTextReader.
4142 *
4143 * Returns 0 in case of success and -1 in case of error
4144 */
4145int
4146xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4147{
4148 if (doc == NULL)
4149 return (-1);
4150 if (reader == NULL)
4151 return (-1);
4152
4153 if (reader->ctxt != NULL) {
4154 xmlCtxtReset(reader->ctxt);
4155 }
4156
4157 reader->entNr = 0;
4158 reader->input = NULL;
4159 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4160 reader->node = NULL;
4161 reader->curnode = NULL;
4162 reader->base = 0;
4163 reader->cur = 0;
4164 reader->allocs = XML_TEXTREADER_CTXT;
4165 reader->doc = doc;
4166 reader->state = XML_TEXTREADER_START;
4167 if (reader->dict == NULL) {
4168 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4169 reader->dict = reader->ctxt->dict;
4170 else
4171 reader->dict = xmlDictCreate();
4172 }
4173 return(0);
4174}
4175
4176/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004177 * xmlReaderNewDoc:
4178 * @reader: an XML reader
4179 * @cur: a pointer to a zero terminated string
4180 * @URL: the base URL to use for the document
4181 * @encoding: the document encoding, or NULL
4182 * @options: a combination of xmlParserOption(s)
4183 *
4184 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004185 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004186 * This reuses the existing @reader xmlTextReader.
4187 *
4188 * Returns 0 in case of success and -1 in case of error
4189 */
4190int
4191xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4192 const char *URL, const char *encoding, int options)
4193{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004194
4195 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004196
4197 if (cur == NULL)
4198 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004199 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004200 return (-1);
4201
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004202 len = xmlStrlen(cur);
4203 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4204 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004205}
4206
4207/**
4208 * xmlReaderNewFile:
4209 * @reader: an XML reader
4210 * @filename: a file or URL
4211 * @encoding: the document encoding, or NULL
4212 * @options: a combination of xmlParserOption(s)
4213 *
4214 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004215 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004216 * This reuses the existing @reader xmlTextReader.
4217 *
4218 * Returns 0 in case of success and -1 in case of error
4219 */
4220int
4221xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4222 const char *encoding, int options)
4223{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004224 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004225
4226 if (filename == NULL)
4227 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004228 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004229 return (-1);
4230
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004231 input =
4232 xmlParserInputBufferCreateFilename(filename,
4233 XML_CHAR_ENCODING_NONE);
4234 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004235 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004236 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004237}
4238
4239/**
4240 * xmlReaderNewMemory:
4241 * @reader: an XML reader
4242 * @buffer: a pointer to a char array
4243 * @size: the size of the array
4244 * @URL: the base URL to use for the document
4245 * @encoding: the document encoding, or NULL
4246 * @options: a combination of xmlParserOption(s)
4247 *
4248 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004249 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004250 * This reuses the existing @reader xmlTextReader.
4251 *
4252 * Returns 0 in case of success and -1 in case of error
4253 */
4254int
4255xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4256 const char *URL, const char *encoding, int options)
4257{
4258 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004259
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004260 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004261 return (-1);
4262 if (buffer == NULL)
4263 return (-1);
4264
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004265 input = xmlParserInputBufferCreateMem(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004266 XML_CHAR_ENCODING_NONE);
4267 if (input == NULL) {
4268 return (-1);
4269 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004270 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004271}
4272
4273/**
4274 * xmlReaderNewFd:
4275 * @reader: an XML reader
4276 * @fd: an open file descriptor
4277 * @URL: the base URL to use for the document
4278 * @encoding: the document encoding, or NULL
4279 * @options: a combination of xmlParserOption(s)
4280 *
4281 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004282 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004283 * This reuses the existing @reader xmlTextReader.
4284 *
4285 * Returns 0 in case of success and -1 in case of error
4286 */
4287int
4288xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4289 const char *URL, const char *encoding, int options)
4290{
4291 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004292
4293 if (fd < 0)
4294 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004295 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004296 return (-1);
4297
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004298 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4299 if (input == NULL)
4300 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004301 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004302}
4303
4304/**
4305 * xmlReaderNewIO:
4306 * @reader: an XML reader
4307 * @ioread: an I/O read function
4308 * @ioclose: an I/O close function
4309 * @ioctx: an I/O handler
4310 * @URL: the base URL to use for the document
4311 * @encoding: the document encoding, or NULL
4312 * @options: a combination of xmlParserOption(s)
4313 *
4314 * Setup an xmltextReader to parse an XML document from I/O functions
4315 * and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004316 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004317 * This reuses the existing @reader xmlTextReader.
4318 *
4319 * Returns 0 in case of success and -1 in case of error
4320 */
4321int
4322xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4323 xmlInputCloseCallback ioclose, void *ioctx,
4324 const char *URL, const char *encoding, int options)
4325{
4326 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004327
4328 if (ioread == NULL)
4329 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004330 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004331 return (-1);
4332
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004333 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4334 XML_CHAR_ENCODING_NONE);
4335 if (input == NULL)
4336 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004337 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004338}
Daniel Veillard26f70262003-01-16 22:45:08 +00004339/************************************************************************
4340 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004341 * Utilities *
4342 * *
4343 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004344#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004345/**
4346 * xmlBase64Decode:
4347 * @in: the input buffer
4348 * @inlen: the size of the input (in), the size read from it (out)
4349 * @to: the output buffer
4350 * @tolen: the size of the output (in), the size written to (out)
4351 *
4352 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004353 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004354 *
4355 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4356 * 2 if there wasn't enough space on the output or -1 in case of error.
4357 */
4358static int
4359xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4360 unsigned char *to, unsigned long *tolen) {
4361 unsigned long incur; /* current index in in[] */
4362 unsigned long inblk; /* last block index in in[] */
4363 unsigned long outcur; /* current index in out[] */
4364 unsigned long inmax; /* size of in[] */
4365 unsigned long outmax; /* size of out[] */
4366 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004367 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004368 int nbintmp; /* number of byte in intmp[] */
4369 int is_ignore; /* cur should be ignored */
4370 int is_end = 0; /* the end of the base64 was found */
4371 int retval = 1;
4372 int i;
4373
4374 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4375 return(-1);
4376
4377 incur = 0;
4378 inblk = 0;
4379 outcur = 0;
4380 inmax = *inlen;
4381 outmax = *tolen;
4382 nbintmp = 0;
4383
4384 while (1) {
4385 if (incur >= inmax)
4386 break;
4387 cur = in[incur++];
4388 is_ignore = 0;
4389 if ((cur >= 'A') && (cur <= 'Z'))
4390 cur = cur - 'A';
4391 else if ((cur >= 'a') && (cur <= 'z'))
4392 cur = cur - 'a' + 26;
4393 else if ((cur >= '0') && (cur <= '9'))
4394 cur = cur - '0' + 52;
4395 else if (cur == '+')
4396 cur = 62;
4397 else if (cur == '/')
4398 cur = 63;
4399 else if (cur == '.')
4400 cur = 0;
4401 else if (cur == '=') /*no op , end of the base64 stream */
4402 is_end = 1;
4403 else {
4404 is_ignore = 1;
4405 if (nbintmp == 0)
4406 inblk = incur;
4407 }
4408
4409 if (!is_ignore) {
4410 int nbouttmp = 3;
4411 int is_break = 0;
4412
4413 if (is_end) {
4414 if (nbintmp == 0)
4415 break;
4416 if ((nbintmp == 1) || (nbintmp == 2))
4417 nbouttmp = 1;
4418 else
4419 nbouttmp = 2;
4420 nbintmp = 3;
4421 is_break = 1;
4422 }
4423 intmp[nbintmp++] = cur;
4424 /*
4425 * if intmp is full, push the 4byte sequence as a 3 byte
4426 * sequence out
4427 */
4428 if (nbintmp == 4) {
4429 nbintmp = 0;
4430 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4431 outtmp[1] =
4432 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4433 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4434 if (outcur + 3 >= outmax) {
4435 retval = 2;
4436 break;
4437 }
4438
4439 for (i = 0; i < nbouttmp; i++)
4440 to[outcur++] = outtmp[i];
4441 inblk = incur;
4442 }
4443
4444 if (is_break) {
4445 retval = 0;
4446 break;
4447 }
4448 }
4449 }
4450
4451 *tolen = outcur;
4452 *inlen = inblk;
4453 return (retval);
4454}
4455
4456/*
4457 * Test routine for the xmlBase64Decode function
4458 */
4459#if 0
4460int main(int argc, char **argv) {
4461 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4462 char output[100];
4463 char output2[100];
4464 char output3[100];
4465 unsigned long inlen = strlen(input);
4466 unsigned long outlen = 100;
4467 int ret;
4468 unsigned long cons, tmp, tmp2, prod;
4469
4470 /*
4471 * Direct
4472 */
4473 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4474
4475 output[outlen] = 0;
4476 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4477
4478 /*
4479 * output chunking
4480 */
4481 cons = 0;
4482 prod = 0;
4483 while (cons < inlen) {
4484 tmp = 5;
4485 tmp2 = inlen - cons;
4486
4487 printf("%ld %ld\n", cons, prod);
4488 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4489 cons += tmp2;
4490 prod += tmp;
4491 printf("%ld %ld\n", cons, prod);
4492 }
4493 output2[outlen] = 0;
4494 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4495
4496 /*
4497 * input chunking
4498 */
4499 cons = 0;
4500 prod = 0;
4501 while (cons < inlen) {
4502 tmp = 100 - prod;
4503 tmp2 = inlen - cons;
4504 if (tmp2 > 5)
4505 tmp2 = 5;
4506
4507 printf("%ld %ld\n", cons, prod);
4508 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4509 cons += tmp2;
4510 prod += tmp;
4511 printf("%ld %ld\n", cons, prod);
4512 }
4513 output3[outlen] = 0;
4514 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4515 return(0);
4516
4517}
4518#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004519#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004520#endif /* LIBXML_READER_ENABLED */