blob: 60b73f586ba96e150cbe135a7b1c80e7e4875ba2 [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 Veillarde8039df2003-10-27 11:25:13 +0000142#define NODE_IS_EMPTY 0x1
143#define NODE_IS_PRESERVED 0x2
Daniel Veillard067bae52003-01-05 01:27:54 +0000144
Daniel Veillarde72c5082003-09-19 12:44:05 +0000145/**
146 * CONSTSTR:
147 *
148 * Macro used to return an interned string
149 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000150#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
151#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
152
153static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
154static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000155
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000156/************************************************************************
157 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000158 * Our own version of the freeing routines as we recycle nodes *
159 * *
160 ************************************************************************/
161/**
162 * DICT_FREE:
163 * @str: a string
164 *
165 * Free a string if it is not owned by the "dict" dictionnary in the
166 * current scope
167 */
168#define DICT_FREE(str) \
169 if ((str) && ((!dict) || \
170 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
171 xmlFree((char *)(str));
172
173static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
174static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
175
176/**
177 * xmlTextReaderFreeProp:
178 * @reader: the xmlTextReaderPtr used
179 * @cur: the node
180 *
181 * Free a node.
182 */
183static void
184xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
185 xmlDictPtr dict;
186
187 dict = reader->ctxt->dict;
188 if (cur == NULL) return;
189
190 /* Check for ID removal -> leading to invalid references ! */
191 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
192 ((cur->parent->doc->intSubset != NULL) ||
193 (cur->parent->doc->extSubset != NULL))) {
194 if (xmlIsID(cur->parent->doc, cur->parent, cur))
195 xmlRemoveID(cur->parent->doc, cur);
196 }
197 if (cur->children != NULL)
198 xmlTextReaderFreeNodeList(reader, cur->children);
199
200 DICT_FREE(cur->name);
201 if ((reader != NULL) && (reader->ctxt != NULL) &&
202 (reader->ctxt->freeAttrsNr < 100)) {
203 cur->next = reader->ctxt->freeAttrs;
204 reader->ctxt->freeAttrs = cur;
205 reader->ctxt->freeAttrsNr++;
206 } else {
207 xmlFree(cur);
208 }
209}
210
211/**
212 * xmlTextReaderFreePropList:
213 * @reader: the xmlTextReaderPtr used
214 * @cur: the first property in the list
215 *
216 * Free a property and all its siblings, all the children are freed too.
217 */
218static void
219xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
220 xmlAttrPtr next;
221 if (cur == NULL) return;
222 while (cur != NULL) {
223 next = cur->next;
224 xmlTextReaderFreeProp(reader, cur);
225 cur = next;
226 }
227}
228
229/**
230 * xmlTextReaderFreeNodeList:
231 * @reader: the xmlTextReaderPtr used
232 * @cur: the first node in the list
233 *
234 * Free a node and all its siblings, this is a recursive behaviour, all
235 * the children are freed too.
236 */
237static void
238xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
239 xmlNodePtr next;
240 xmlDictPtr dict;
241
242 dict = reader->ctxt->dict;
243 if (cur == NULL) return;
244 if (cur->type == XML_NAMESPACE_DECL) {
245 xmlFreeNsList((xmlNsPtr) cur);
246 return;
247 }
248 if ((cur->type == XML_DOCUMENT_NODE) ||
249 (cur->type == XML_HTML_DOCUMENT_NODE)) {
250 xmlFreeDoc((xmlDocPtr) cur);
251 return;
252 }
253 while (cur != NULL) {
254 next = cur->next;
255 /* unroll to speed up freeing the document */
256 if (cur->type != XML_DTD_NODE) {
257
258 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000259 (cur->type != XML_ENTITY_REF_NODE)) {
260 if (cur->children->parent == cur)
261 xmlTextReaderFreeNodeList(reader, cur->children);
262 cur->children = NULL;
263 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000264 if (((cur->type == XML_ELEMENT_NODE) ||
265 (cur->type == XML_XINCLUDE_START) ||
266 (cur->type == XML_XINCLUDE_END)) &&
267 (cur->properties != NULL))
268 xmlTextReaderFreePropList(reader, cur->properties);
269 if ((cur->type != XML_ELEMENT_NODE) &&
270 (cur->type != XML_XINCLUDE_START) &&
271 (cur->type != XML_XINCLUDE_END) &&
272 (cur->type != XML_ENTITY_REF_NODE)) {
273 DICT_FREE(cur->content);
274 }
275 if (((cur->type == XML_ELEMENT_NODE) ||
276 (cur->type == XML_XINCLUDE_START) ||
277 (cur->type == XML_XINCLUDE_END)) &&
278 (cur->nsDef != NULL))
279 xmlFreeNsList(cur->nsDef);
280
281 /*
282 * we don't free element names here they are interned now
283 */
284 if ((cur->type != XML_TEXT_NODE) &&
285 (cur->type != XML_COMMENT_NODE))
286 DICT_FREE(cur->name);
287 if (((cur->type == XML_ELEMENT_NODE) ||
288 (cur->type == XML_TEXT_NODE)) &&
289 (reader != NULL) && (reader->ctxt != NULL) &&
290 (reader->ctxt->freeElemsNr < 100)) {
291 cur->next = reader->ctxt->freeElems;
292 reader->ctxt->freeElems = cur;
293 reader->ctxt->freeElemsNr++;
294 } else {
295 xmlFree(cur);
296 }
297 }
298 cur = next;
299 }
300}
301
302/**
303 * xmlTextReaderFreeNode:
304 * @reader: the xmlTextReaderPtr used
305 * @cur: the node
306 *
307 * Free a node, this is a recursive behaviour, all the children are freed too.
308 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
309 */
310static void
311xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
312 xmlDictPtr dict;
313
314 dict = reader->ctxt->dict;
315 if (cur->type == XML_DTD_NODE) {
316 xmlFreeDtd((xmlDtdPtr) cur);
317 return;
318 }
319 if (cur->type == XML_NAMESPACE_DECL) {
320 xmlFreeNs((xmlNsPtr) cur);
321 return;
322 }
323 if (cur->type == XML_ATTRIBUTE_NODE) {
324 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
325 return;
326 }
327
328 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000329 (cur->type != XML_ENTITY_REF_NODE)) {
330 if (cur->children->parent == cur)
331 xmlTextReaderFreeNodeList(reader, cur->children);
332 cur->children = NULL;
333 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000334 if (((cur->type == XML_ELEMENT_NODE) ||
335 (cur->type == XML_XINCLUDE_START) ||
336 (cur->type == XML_XINCLUDE_END)) &&
337 (cur->properties != NULL))
338 xmlTextReaderFreePropList(reader, cur->properties);
339 if ((cur->type != XML_ELEMENT_NODE) &&
340 (cur->type != XML_XINCLUDE_START) &&
341 (cur->type != XML_XINCLUDE_END) &&
342 (cur->type != XML_ENTITY_REF_NODE)) {
343 DICT_FREE(cur->content);
344 }
345 if (((cur->type == XML_ELEMENT_NODE) ||
346 (cur->type == XML_XINCLUDE_START) ||
347 (cur->type == XML_XINCLUDE_END)) &&
348 (cur->nsDef != NULL))
349 xmlFreeNsList(cur->nsDef);
350
351 /*
352 * we don't free names here they are interned now
353 */
354 if ((cur->type != XML_TEXT_NODE) &&
355 (cur->type != XML_COMMENT_NODE))
356 DICT_FREE(cur->name);
357 if (((cur->type == XML_ELEMENT_NODE) ||
358 (cur->type == XML_TEXT_NODE)) &&
359 (reader != NULL) && (reader->ctxt != NULL) &&
360 (reader->ctxt->freeElemsNr < 100)) {
361 cur->next = reader->ctxt->freeElems;
362 reader->ctxt->freeElems = cur;
363 reader->ctxt->freeElemsNr++;
364 } else {
365 xmlFree(cur);
366 }
367}
368
369/**
370 * xmlTextReaderFreeDoc:
371 * @reader: the xmlTextReaderPtr used
372 * @cur: pointer to the document
373 *
374 * Free up all the structures used by a document, tree included.
375 */
376static void
377xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
378 xmlDtdPtr extSubset, intSubset;
379
380 if (cur == NULL) return;
381
382 /*
383 * Do this before freeing the children list to avoid ID lookups
384 */
385 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
386 cur->ids = NULL;
387 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
388 cur->refs = NULL;
389 extSubset = cur->extSubset;
390 intSubset = cur->intSubset;
391 if (intSubset == extSubset)
392 extSubset = NULL;
393 if (extSubset != NULL) {
394 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
395 cur->extSubset = NULL;
396 xmlFreeDtd(extSubset);
397 }
398 if (intSubset != NULL) {
399 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
400 cur->intSubset = NULL;
401 xmlFreeDtd(intSubset);
402 }
403
404 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
405
406 if (cur->version != NULL) xmlFree((char *) cur->version);
407 if (cur->name != NULL) xmlFree((char *) cur->name);
408 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
409 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
410 if (cur->URL != NULL) xmlFree((char *) cur->URL);
411 xmlFree(cur);
412}
413
414/************************************************************************
415 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000416 * The reader core parser *
417 * *
418 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000419#ifdef DEBUG_READER
420static void
421xmlTextReaderDebug(xmlTextReaderPtr reader) {
422 if ((reader == NULL) || (reader->ctxt == NULL)) {
423 fprintf(stderr, "xmlTextReader NULL\n");
424 return;
425 }
426 fprintf(stderr, "xmlTextReader: state %d depth %d ",
427 reader->state, reader->depth);
428 if (reader->node == NULL) {
429 fprintf(stderr, "node = NULL\n");
430 } else {
431 fprintf(stderr, "node %s\n", reader->node->name);
432 }
433 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
434 reader->base, reader->cur, reader->ctxt->nodeNr);
435 if (reader->input->buffer == NULL) {
436 fprintf(stderr, "buffer is NULL\n");
437 } else {
438#ifdef LIBXML_DEBUG_ENABLED
439 xmlDebugDumpString(stderr,
440 &reader->input->buffer->content[reader->cur]);
441#endif
442 fprintf(stderr, "\n");
443 }
444}
445#endif
446
447/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000448 * xmlTextReaderEntPush:
449 * @reader: the xmlTextReaderPtr used
450 * @value: the entity reference node
451 *
452 * Pushes a new entity reference node on top of the entities stack
453 *
454 * Returns 0 in case of error, the index in the stack otherwise
455 */
456static int
457xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
458{
459 if (reader->entMax <= 0) {
460 reader->entMax = 10;
461 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
462 sizeof(reader->entTab[0]));
463 if (reader->entTab == NULL) {
464 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
465 return (0);
466 }
467 }
468 if (reader->entNr >= reader->entMax) {
469 reader->entMax *= 2;
470 reader->entTab =
471 (xmlNodePtr *) xmlRealloc(reader->entTab,
472 reader->entMax *
473 sizeof(reader->entTab[0]));
474 if (reader->entTab == NULL) {
475 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
476 return (0);
477 }
478 }
479 reader->entTab[reader->entNr] = value;
480 reader->ent = value;
481 return (reader->entNr++);
482}
483
484/**
485 * xmlTextReaderEntPop:
486 * @reader: the xmlTextReaderPtr used
487 *
488 * Pops the top element entity from the entities stack
489 *
490 * Returns the entity just removed
491 */
492static xmlNodePtr
493xmlTextReaderEntPop(xmlTextReaderPtr reader)
494{
495 xmlNodePtr ret;
496
497 if (reader->entNr <= 0)
498 return (0);
499 reader->entNr--;
500 if (reader->entNr > 0)
501 reader->ent = reader->entTab[reader->entNr - 1];
502 else
503 reader->ent = NULL;
504 ret = reader->entTab[reader->entNr];
505 reader->entTab[reader->entNr] = 0;
506 return (ret);
507}
508
509/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000510 * xmlTextReaderStartElement:
511 * @ctx: the user data (XML parser context)
512 * @fullname: The element name, including namespace prefix
513 * @atts: An array of name/value attributes pairs, NULL terminated
514 *
515 * called when an opening tag has been processed.
516 */
517static void
518xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
519 const xmlChar **atts) {
520 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
521 xmlTextReaderPtr reader = ctxt->_private;
522
523#ifdef DEBUG_CALLBACKS
524 printf("xmlTextReaderStartElement(%s)\n", fullname);
525#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000526 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000527 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000528 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
529 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
530 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000531 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000532 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000533 if (reader != NULL)
534 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000535}
536
537/**
538 * xmlTextReaderEndElement:
539 * @ctx: the user data (XML parser context)
540 * @fullname: The element name, including namespace prefix
541 *
542 * called when an ending tag has been processed.
543 */
544static void
545xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
546 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
547 xmlTextReaderPtr reader = ctxt->_private;
548
549#ifdef DEBUG_CALLBACKS
550 printf("xmlTextReaderEndElement(%s)\n", fullname);
551#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000552 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000553 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000554 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000555}
556
557/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000558 * xmlTextReaderStartElementNs:
559 * @ctx: the user data (XML parser context)
560 * @localname: the local name of the element
561 * @prefix: the element namespace prefix if available
562 * @URI: the element namespace name if available
563 * @nb_namespaces: number of namespace definitions on that node
564 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
565 * @nb_attributes: the number of attributes on that node
566 * nb_defaulted: the number of defaulted attributes.
567 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
568 * attribute values.
569 *
570 * called when an opening tag has been processed.
571 */
572static void
573xmlTextReaderStartElementNs(void *ctx,
574 const xmlChar *localname,
575 const xmlChar *prefix,
576 const xmlChar *URI,
577 int nb_namespaces,
578 const xmlChar **namespaces,
579 int nb_attributes,
580 int nb_defaulted,
581 const xmlChar **attributes)
582{
583 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
584 xmlTextReaderPtr reader = ctxt->_private;
585
586#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000587 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000588#endif
589 if ((reader != NULL) && (reader->startElementNs != NULL)) {
590 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
591 namespaces, nb_attributes, nb_defaulted,
592 attributes);
593 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
594 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
595 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000596 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000597 }
598 if (reader != NULL)
599 reader->state = XML_TEXTREADER_ELEMENT;
600}
601
602/**
603 * xmlTextReaderEndElementNs:
604 * @ctx: the user data (XML parser context)
605 * @localname: the local name of the element
606 * @prefix: the element namespace prefix if available
607 * @URI: the element namespace name if available
608 *
609 * called when an ending tag has been processed.
610 */
611static void
612xmlTextReaderEndElementNs(void *ctx,
613 const xmlChar * localname,
614 const xmlChar * prefix,
615 const xmlChar * URI)
616{
617 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
618 xmlTextReaderPtr reader = ctxt->_private;
619
620#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000621 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000622#endif
623 if ((reader != NULL) && (reader->endElementNs != NULL)) {
624 reader->endElementNs(ctx, localname, prefix, URI);
625 }
626}
627
628
629/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000630 * xmlTextReaderCharacters:
631 * @ctx: the user data (XML parser context)
632 * @ch: a xmlChar string
633 * @len: the number of xmlChar
634 *
635 * receiving some chars from the parser.
636 */
637static void
638xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
639{
640 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
641 xmlTextReaderPtr reader = ctxt->_private;
642
643#ifdef DEBUG_CALLBACKS
644 printf("xmlTextReaderCharacters()\n");
645#endif
646 if ((reader != NULL) && (reader->characters != NULL)) {
647 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000648 }
649}
650
651/**
652 * xmlTextReaderCDataBlock:
653 * @ctx: the user data (XML parser context)
654 * @value: The pcdata content
655 * @len: the block length
656 *
657 * called when a pcdata block has been parsed
658 */
659static void
660xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
661{
662 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
663 xmlTextReaderPtr reader = ctxt->_private;
664
665#ifdef DEBUG_CALLBACKS
666 printf("xmlTextReaderCDataBlock()\n");
667#endif
668 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
669 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000670 }
671}
672
673/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000674 * xmlTextReaderPushData:
675 * @reader: the xmlTextReaderPtr used
676 *
677 * Push data down the progressive parser until a significant callback
678 * got raised.
679 *
680 * Returns -1 in case of failure, 0 otherwise
681 */
682static int
683xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000684 xmlBufferPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000685 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000686 xmlTextReaderState oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000687
688 if ((reader->input == NULL) || (reader->input->buffer == NULL))
689 return(-1);
690
Daniel Veillardea7751d2002-12-20 00:16:24 +0000691 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000692 reader->state = XML_TEXTREADER_NONE;
693 inbuf = reader->input->buffer;
Daniel Veillarda880b122003-04-21 21:36:41 +0000694
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000695 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000696 if (inbuf->use < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000697 /*
698 * Refill the buffer unless we are at the end of the stream
699 */
700 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
701 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000702 if ((val == 0) &&
703 (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
704 if (inbuf->use == reader->cur) {
705 reader->mode = XML_TEXTREADER_MODE_EOF;
706 reader->state = oldstate;
707 if ((oldstate != XML_TEXTREADER_START) ||
708 (reader->ctxt->myDoc != NULL))
709 return(val);
710 }
711 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000712 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000713 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000714 if ((oldstate != XML_TEXTREADER_START) ||
715 (reader->ctxt->myDoc != NULL))
716 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000717 } else if (val == 0) {
718 /* mark the end of the stream and process the remains */
719 reader->mode = XML_TEXTREADER_MODE_EOF;
720 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000721 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000722
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000723 } else
724 break;
725 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000726 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000727 * parse by block of CHUNK_SIZE bytes, various tests show that
728 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000729 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000730 if (inbuf->use >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000731 val = xmlParseChunk(reader->ctxt,
732 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000733 CHUNK_SIZE, 0);
734 reader->cur += CHUNK_SIZE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000735 if (val != 0)
736 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000737 } else {
Daniel Veillarda880b122003-04-21 21:36:41 +0000738 s = inbuf->use - reader->cur;
739 val = xmlParseChunk(reader->ctxt,
740 (const char *) &inbuf->content[reader->cur],
741 s, 0);
742 reader->cur += s;
743 if (val != 0)
744 return(-1);
745 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000746 }
747 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000748
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000749 /*
750 * Discard the consumed input when needed and possible
751 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000752 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillardf6bc7c22003-09-17 22:33:22 +0000753 if ((reader->cur >= 4096) &&
754 (inbuf->use - reader->cur <= CHUNK_SIZE)) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000755 val = xmlBufferShrink(inbuf, reader->cur);
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000756 if (val >= 0) {
757 reader->cur -= val;
758 }
759 }
760 }
761
762 /*
763 * At the end of the stream signal that the work is done to the Push
764 * parser.
765 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000766 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +0000767 if (reader->mode != XML_TEXTREADER_DONE) {
Daniel Veillarda880b122003-04-21 21:36:41 +0000768 s = inbuf->use - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000769 val = xmlParseChunk(reader->ctxt,
Daniel Veillard067bae52003-01-05 01:27:54 +0000770 (const char *) &inbuf->content[reader->cur],
Daniel Veillarda880b122003-04-21 21:36:41 +0000771 s, 1);
772 reader->cur = inbuf->use;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000773 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000774 if (val != 0) return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000775 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000776 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000777 reader->state = oldstate;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000778 return(0);
779}
780
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000781#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000782/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000783 * xmlTextReaderValidatePush:
784 * @reader: the xmlTextReaderPtr used
785 *
786 * Push the current node for validation
787 */
788static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000789xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000790 xmlNodePtr node = reader->node;
791
Daniel Veillardf4e55762003-04-15 23:32:22 +0000792 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
793 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
794 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
795 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
796 reader->ctxt->myDoc, node, node->name);
797 } else {
798 /* TODO use the BuildQName interface */
799 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000800
Daniel Veillardf4e55762003-04-15 23:32:22 +0000801 qname = xmlStrdup(node->ns->prefix);
802 qname = xmlStrcat(qname, BAD_CAST ":");
803 qname = xmlStrcat(qname, node->name);
804 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
805 reader->ctxt->myDoc, node, qname);
806 if (qname != NULL)
807 xmlFree(qname);
808 }
809#ifdef LIBXML_SCHEMAS_ENABLED
810 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
811 (reader->rngValidCtxt != NULL)) {
812 int ret;
813
814 if (reader->rngFullNode != NULL) return;
815 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
816 reader->ctxt->myDoc,
817 node);
818 if (ret == 0) {
819 /*
820 * this element requires a full tree
821 */
822 node = xmlTextReaderExpand(reader);
823 if (node == NULL) {
824printf("Expand failed !\n");
825 ret = -1;
826 } else {
827 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
828 reader->ctxt->myDoc,
829 node);
830 reader->rngFullNode = node;
831 }
832 }
833 if (ret != 1)
834 reader->rngValidErrors++;
835#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000836 }
837}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000838
839/**
840 * xmlTextReaderValidateCData:
841 * @reader: the xmlTextReaderPtr used
842 * @data: pointer to the CData
843 * @len: lenght of the CData block in bytes.
844 *
845 * Push some CData for validation
846 */
847static void
848xmlTextReaderValidateCData(xmlTextReaderPtr reader,
849 const xmlChar *data, int len) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000850 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
851 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
852 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
853 data, len);
854#ifdef LIBXML_SCHEMAS_ENABLED
855 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
856 (reader->rngValidCtxt != NULL)) {
857 int ret;
858
859 if (reader->rngFullNode != NULL) return;
860 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
861 if (ret != 1)
862 reader->rngValidErrors++;
863#endif
864 }
Daniel Veillardf4e55762003-04-15 23:32:22 +0000865}
866
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000867/**
868 * xmlTextReaderValidatePop:
869 * @reader: the xmlTextReaderPtr used
870 *
871 * Pop the current node from validation
872 */
873static void
874xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
875 xmlNodePtr node = reader->node;
876
Daniel Veillardf4e55762003-04-15 23:32:22 +0000877 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
878 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
879 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
880 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
881 reader->ctxt->myDoc, node, node->name);
882 } else {
883 /* TODO use the BuildQName interface */
884 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000885
Daniel Veillardf4e55762003-04-15 23:32:22 +0000886 qname = xmlStrdup(node->ns->prefix);
887 qname = xmlStrcat(qname, BAD_CAST ":");
888 qname = xmlStrcat(qname, node->name);
889 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
890 reader->ctxt->myDoc, node, qname);
891 if (qname != NULL)
892 xmlFree(qname);
893 }
894#ifdef LIBXML_SCHEMAS_ENABLED
895 } else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
896 (reader->rngValidCtxt != NULL)) {
897 int ret;
898
899 if (reader->rngFullNode != NULL) {
900 if (node == reader->rngFullNode)
901 reader->rngFullNode = NULL;
902 return;
903 }
904 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
905 reader->ctxt->myDoc,
906 node);
907 if (ret != 1)
908 reader->rngValidErrors++;
909#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000910 }
911}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000912
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000913/**
914 * xmlTextReaderValidateEntity:
915 * @reader: the xmlTextReaderPtr used
916 *
917 * Handle the validation when an entity reference is encountered and
918 * entity substitution is not activated. As a result the parser interface
919 * must walk through the entity and do the validation calls
920 */
921static void
922xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
923 xmlNodePtr oldnode = reader->node;
924 xmlNodePtr node = reader->node;
925 xmlParserCtxtPtr ctxt = reader->ctxt;
926
927 do {
928 if (node->type == XML_ENTITY_REF_NODE) {
929 /*
930 * Case where the underlying tree is not availble, lookup the entity
931 * and walk it.
932 */
933 if ((node->children == NULL) && (ctxt->sax != NULL) &&
934 (ctxt->sax->getEntity != NULL)) {
935 node->children = (xmlNodePtr)
936 ctxt->sax->getEntity(ctxt, node->name);
937 }
938
939 if ((node->children != NULL) &&
940 (node->children->type == XML_ENTITY_DECL) &&
941 (node->children->children != NULL)) {
942 xmlTextReaderEntPush(reader, node);
943 node = node->children->children;
944 continue;
945 } else {
946 /*
947 * The error has probably be raised already.
948 */
949 if (node == oldnode)
950 break;
951 node = node->next;
952 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000953#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000954 } else if (node->type == XML_ELEMENT_NODE) {
955 reader->node = node;
956 xmlTextReaderValidatePush(reader);
957 } else if ((node->type == XML_TEXT_NODE) ||
958 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +0000959 xmlTextReaderValidateCData(reader, node->content,
960 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000961#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000962 }
963
964 /*
965 * go to next node
966 */
967 if (node->children != NULL) {
968 node = node->children;
969 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +0000970 } else if (node->type == XML_ELEMENT_NODE) {
971 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000972 }
973 if (node->next != NULL) {
974 node = node->next;
975 continue;
976 }
977 do {
978 node = node->parent;
979 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000980 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +0000981 if (reader->entNr == 0) {
982 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +0000983 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +0000984 xmlUnlinkNode(tmp);
985 xmlTextReaderFreeNode(reader, tmp);
986 } else
987 break;
988 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000989 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +0000990 reader->node = node;
991 xmlTextReaderValidatePop(reader);
992 }
993 if ((node->type == XML_ENTITY_DECL) &&
994 (reader->ent != NULL) && (reader->ent->children == node)) {
995 node = xmlTextReaderEntPop(reader);
996 }
997 if (node == oldnode)
998 break;
999 if (node->next != NULL) {
1000 node = node->next;
1001 break;
1002 }
1003 } while ((node != NULL) && (node != oldnode));
1004 } while ((node != NULL) && (node != oldnode));
1005 reader->node = oldnode;
1006}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001007#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001008
1009
1010/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001011 * xmlTextReaderGetSuccessor:
1012 * @cur: the current node
1013 *
1014 * Get the successor of a node if available.
1015 *
1016 * Returns the successor node or NULL
1017 */
1018static xmlNodePtr
1019xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1020 if (cur == NULL) return(NULL) ; /* ERROR */
1021 if (cur->next != NULL) return(cur->next) ;
1022 do {
1023 cur = cur->parent;
1024 if (cur == NULL) return(NULL);
1025 if (cur->next != NULL) return(cur->next);
1026 } while (cur != NULL);
1027 return(cur);
1028}
1029
1030/**
1031 * xmlTextReaderDoExpand:
1032 * @reader: the xmlTextReaderPtr used
1033 *
1034 * Makes sure that the current node is fully read as well as all its
1035 * descendant. It means the full DOM subtree must be available at the
1036 * end of the call.
1037 *
1038 * Returns 1 if the node was expanded successfully, 0 if there is no more
1039 * nodes to read, or -1 in case of error
1040 */
1041static int
1042xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1043 int val;
1044
1045 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1046 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001047 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001048 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1049
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001050 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1051 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001052 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001053 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001054 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1055 return(1);
1056 val = xmlTextReaderPushData(reader);
1057 if (val < 0)
1058 return(-1);
1059 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1060 return(1);
1061}
1062
1063/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001064 * xmlTextReaderRead:
1065 * @reader: the xmlTextReaderPtr used
1066 *
1067 * Moves the position of the current instance to the next node in
1068 * the stream, exposing its properties.
1069 *
1070 * Returns 1 if the node was read successfully, 0 if there is no more
1071 * nodes to read, or -1 in case of error
1072 */
1073int
1074xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001075 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001076 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001077 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001078
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001079
1080 if (reader == NULL)
1081 return(-1);
1082 if (reader->doc != NULL)
1083 return(xmlTextReaderReadTree(reader));
1084 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001085 return(-1);
1086 if (reader->ctxt->wellFormed != 1)
1087 return(-1);
1088
1089#ifdef DEBUG_READER
1090 fprintf(stderr, "\nREAD ");
1091 DUMP_READER
1092#endif
Daniel Veillard29b3e282002-12-29 11:14:41 +00001093 reader->curnode = NULL;
Daniel Veillard67df8092002-12-16 22:04:11 +00001094 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1095 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001096 /*
1097 * Initial state
1098 */
1099 do {
1100 val = xmlTextReaderPushData(reader);
1101 if (val < 0)
1102 return(-1);
1103 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001104 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1105 (reader->mode != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001106 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001107 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001108 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001109 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001110 if (reader->node == NULL)
1111 return(-1);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001112 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001113 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001114 if (reader->ctxt->myDoc != NULL) {
1115 reader->node = reader->ctxt->myDoc->children;
1116 }
1117 if (reader->node == NULL)
1118 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001119 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001120 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001121 reader->depth = 0;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001122 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001123 }
1124 oldstate = reader->state;
1125 olddepth = reader->ctxt->nodeNr;
1126 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001127
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001128get_next_node:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001129 /*
1130 * If we are not backtracking on ancestors or examined nodes,
1131 * that the parser didn't finished or that we arent at the end
1132 * of stream, continue processing.
1133 */
Daniel Veillarda880b122003-04-21 21:36:41 +00001134 while ((reader->node->next == NULL) &&
1135 (reader->ctxt->nodeNr == olddepth) &&
1136 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001137 (reader->node->children == NULL) ||
1138 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001139 ((reader->node->children != NULL) &&
1140 (reader->node->children->type == XML_TEXT_NODE) &&
1141 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001142 (reader->node->type == XML_DTD_NODE) ||
1143 (reader->node->type == XML_DOCUMENT_NODE) ||
1144 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001145 ((reader->ctxt->node == NULL) ||
1146 (reader->ctxt->node == reader->node) ||
1147 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001148 (reader->ctxt->instate != XML_PARSER_EOF)) {
1149 val = xmlTextReaderPushData(reader);
1150 if (val < 0)
1151 return(-1);
1152 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001153 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001154 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001155 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001156 if ((reader->node->children != NULL) &&
1157 (reader->node->type != XML_ENTITY_REF_NODE) &&
1158 (reader->node->type != XML_DTD_NODE)) {
1159 reader->node = reader->node->children;
1160 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001161 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001162 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001163 }
1164 }
1165 if (reader->node->next != NULL) {
1166 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001167 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001168 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001169 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001170 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001171 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001172 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001173#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001174 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001175 (reader->node->type == XML_ELEMENT_NODE))
1176 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001177#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001178 reader->node = reader->node->next;
1179 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001180
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001181 /*
1182 * Cleanup of the old node
1183 */
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001184 if ((reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001185 (reader->node->prev->type != XML_DTD_NODE) &&
1186 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001187 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001188 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001189 xmlUnlinkNode(tmp);
1190 xmlTextReaderFreeNode(reader, tmp);
1191 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001192 }
1193
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001194 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001195 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001196 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001197 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001198 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001199 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001200 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001201 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001202 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001203#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001204 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001205 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001206#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001207 reader->node = reader->node->parent;
1208 if ((reader->node == NULL) ||
1209 (reader->node->type == XML_DOCUMENT_NODE) ||
1210#ifdef LIBXML_DOCB_ENABLED
1211 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1212#endif
1213 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001214 if (reader->mode != XML_TEXTREADER_DONE) {
1215 val = xmlParseChunk(reader->ctxt, "", 0, 1);
1216 reader->mode = XML_TEXTREADER_DONE;
1217 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001218 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001219 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001220
1221 /*
1222 * Cleanup of the old node
1223 */
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001224 if ((oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001225 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001226 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001227 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001228 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001229 }
1230
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001231 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001232 }
1233 reader->depth--;
1234 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001235
1236node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001237 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001238
1239 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001240 * If we are in the middle of a piece of CDATA make sure it's finished
1241 */
1242 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001243 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001244 ((reader->node->type == XML_TEXT_NODE) ||
1245 (reader->node->type == XML_CDATA_SECTION_NODE))) {
1246 xmlTextReaderExpand(reader);
1247 }
1248
1249 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001250 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001251 */
1252 if ((reader->node != NULL) &&
1253 (reader->node->type == XML_ENTITY_REF_NODE) &&
1254 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1255 /*
1256 * Case where the underlying tree is not availble, lookup the entity
1257 * and walk it.
1258 */
1259 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1260 (reader->ctxt->sax->getEntity != NULL)) {
1261 reader->node->children = (xmlNodePtr)
1262 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1263 }
1264
1265 if ((reader->node->children != NULL) &&
1266 (reader->node->children->type == XML_ENTITY_DECL) &&
1267 (reader->node->children->children != NULL)) {
1268 xmlTextReaderEntPush(reader, reader->node);
1269 reader->node = reader->node->children->children;
1270 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001271#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001272 } else if ((reader->node != NULL) &&
1273 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001274 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001275 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001276#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001277 }
1278 if ((reader->node != NULL) &&
1279 (reader->node->type == XML_ENTITY_DECL) &&
1280 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1281 reader->node = xmlTextReaderEntPop(reader);
1282 reader->depth++;
1283 goto get_next_node;
1284 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001285#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001286 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001287 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001288
1289 if ((node->type == XML_ELEMENT_NODE) &&
1290 ((reader->state != XML_TEXTREADER_END) &&
1291 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1292 xmlTextReaderValidatePush(reader);
1293 } else if ((node->type == XML_TEXT_NODE) ||
1294 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001295 xmlTextReaderValidateCData(reader, node->content,
1296 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001297 }
1298 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001299#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001300 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001301node_end:
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001302 reader->mode = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001303 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001304}
1305
Daniel Veillard67df8092002-12-16 22:04:11 +00001306/**
1307 * xmlTextReaderReadState:
1308 * @reader: the xmlTextReaderPtr used
1309 *
1310 * Gets the read state of the reader.
1311 *
1312 * Returns the state value, or -1 in case of error
1313 */
1314int
1315xmlTextReaderReadState(xmlTextReaderPtr reader) {
1316 if (reader == NULL)
1317 return(-1);
1318 return(reader->mode);
1319}
1320
1321/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001322 * xmlTextReaderExpand:
1323 * @reader: the xmlTextReaderPtr used
1324 *
1325 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001326 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001327 *
1328 * Returns a node pointer valid until the next xmlTextReaderRead() call
1329 * or NULL in case of error.
1330 */
1331xmlNodePtr
1332xmlTextReaderExpand(xmlTextReaderPtr reader) {
1333 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1334 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001335 if (reader->doc != NULL)
1336 return(reader->node);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001337 if (xmlTextReaderDoExpand(reader) < 0)
1338 return(NULL);
1339 return(reader->node);
1340}
1341
1342/**
1343 * xmlTextReaderNext:
1344 * @reader: the xmlTextReaderPtr used
1345 *
1346 * Skip to the node following the current one in document order while
1347 * avoiding the subtree if any.
1348 *
1349 * Returns 1 if the node was read successfully, 0 if there is no more
1350 * nodes to read, or -1 in case of error
1351 */
1352int
1353xmlTextReaderNext(xmlTextReaderPtr reader) {
1354 int ret;
1355 xmlNodePtr cur;
1356
1357 if (reader == NULL)
1358 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001359 if (reader->doc != NULL)
1360 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001361 cur = reader->node;
1362 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1363 return(xmlTextReaderRead(reader));
1364 if (reader->state == XML_TEXTREADER_END)
1365 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001366 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001367 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001368 do {
1369 ret = xmlTextReaderRead(reader);
1370 if (ret != 1)
1371 return(ret);
1372 } while (reader->node != cur);
1373 return(xmlTextReaderRead(reader));
1374}
1375
1376/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001377 * xmlTextReaderReadInnerXml:
1378 * @reader: the xmlTextReaderPtr used
1379 *
1380 * Reads the contents of the current node, including child nodes and markup.
1381 *
1382 * Returns a string containing the XML content, or NULL if the current node
1383 * is neither an element nor attribute, or has no child nodes. The
1384 * string must be deallocated by the caller.
1385 */
1386xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001387xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001388 TODO
1389 return(NULL);
1390}
1391
1392/**
1393 * xmlTextReaderReadOuterXml:
1394 * @reader: the xmlTextReaderPtr used
1395 *
1396 * Reads the contents of the current node, including child nodes and markup.
1397 *
1398 * Returns a string containing the XML content, or NULL if the current node
1399 * is neither an element nor attribute, or has no child nodes. The
1400 * string must be deallocated by the caller.
1401 */
1402xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001403xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001404 TODO
1405 return(NULL);
1406}
1407
1408/**
1409 * xmlTextReaderReadString:
1410 * @reader: the xmlTextReaderPtr used
1411 *
1412 * Reads the contents of an element or a text node as a string.
1413 *
1414 * Returns a string containing the contents of the Element or Text node,
1415 * or NULL if the reader is positioned on any other type of node.
1416 * The string must be deallocated by the caller.
1417 */
1418xmlChar *
Daniel Veillard33300b42003-04-17 09:09:19 +00001419xmlTextReaderReadString(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard67df8092002-12-16 22:04:11 +00001420 TODO
1421 return(NULL);
1422}
1423
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001424#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001425/**
1426 * xmlTextReaderReadBase64:
1427 * @reader: the xmlTextReaderPtr used
1428 * @array: a byte array to store the content.
1429 * @offset: the zero-based index into array where the method should
1430 * begin to write.
1431 * @len: the number of bytes to write.
1432 *
1433 * Reads and decodes the Base64 encoded contents of an element and
1434 * stores the result in a byte buffer.
1435 *
1436 * Returns the number of bytes written to array, or zero if the current
1437 * instance is not positioned on an element or -1 in case of error.
1438 */
1439int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001440xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1441 unsigned char *array ATTRIBUTE_UNUSED,
1442 int offset ATTRIBUTE_UNUSED,
1443 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001444 if ((reader == NULL) || (reader->ctxt == NULL))
1445 return(-1);
1446 if (reader->ctxt->wellFormed != 1)
1447 return(-1);
1448
1449 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1450 return(0);
1451 TODO
1452 return(0);
1453}
1454
1455/**
1456 * xmlTextReaderReadBinHex:
1457 * @reader: the xmlTextReaderPtr used
1458 * @array: a byte array to store the content.
1459 * @offset: the zero-based index into array where the method should
1460 * begin to write.
1461 * @len: the number of bytes to write.
1462 *
1463 * Reads and decodes the BinHex encoded contents of an element and
1464 * stores the result in a byte buffer.
1465 *
1466 * Returns the number of bytes written to array, or zero if the current
1467 * instance is not positioned on an element or -1 in case of error.
1468 */
1469int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001470xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1471 unsigned char *array ATTRIBUTE_UNUSED,
1472 int offset ATTRIBUTE_UNUSED,
1473 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001474 if ((reader == NULL) || (reader->ctxt == NULL))
1475 return(-1);
1476 if (reader->ctxt->wellFormed != 1)
1477 return(-1);
1478
1479 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1480 return(0);
1481 TODO
1482 return(0);
1483}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001484#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001485
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001486/************************************************************************
1487 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001488 * Operating on a preparsed tree *
1489 * *
1490 ************************************************************************/
1491static int
1492xmlTextReaderNextTree(xmlTextReaderPtr reader)
1493{
1494 if (reader == 0)
1495 return(-1);
1496
1497 if (reader->state == XML_TEXTREADER_END)
1498 return(0);
1499
1500 if (reader->node == 0) {
1501 if (reader->doc->children == 0) {
1502 reader->state = XML_TEXTREADER_END;
1503 return(0);
1504 }
1505
1506 reader->node = reader->doc->children;
1507 reader->state = XML_TEXTREADER_START;
1508 return(1);
1509 }
1510
1511 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1512 if (reader->node->children != 0) {
1513 reader->node = reader->node->children;
1514 reader->depth++;
1515 reader->state = XML_TEXTREADER_START;
1516 return(1);
1517 }
1518
1519 if ((reader->node->type == XML_ELEMENT_NODE) ||
1520 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1521 reader->state = XML_TEXTREADER_BACKTRACK;
1522 return(1);
1523 }
1524 }
1525
1526 if (reader->node->next != 0) {
1527 reader->node = reader->node->next;
1528 reader->state = XML_TEXTREADER_START;
1529 return(1);
1530 }
1531
1532 if (reader->node->parent != 0) {
1533 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1534 reader->state = XML_TEXTREADER_END;
1535 return(0);
1536 }
1537
1538 reader->node = reader->node->parent;
1539 reader->depth--;
1540 reader->state = XML_TEXTREADER_BACKTRACK;
1541 return(1);
1542 }
1543
1544 reader->state = XML_TEXTREADER_END;
1545
1546 return(1);
1547}
1548
1549/**
1550 * xmlTextReaderReadTree:
1551 * @reader: the xmlTextReaderPtr used
1552 *
1553 * Moves the position of the current instance to the next node in
1554 * the stream, exposing its properties.
1555 *
1556 * Returns 1 if the node was read successfully, 0 if there is no more
1557 * nodes to read, or -1 in case of error
1558 */
1559static int
1560xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1561 if (reader->state == XML_TEXTREADER_END)
1562 return(0);
1563
1564 if (reader->node == NULL) {
1565 if (reader->doc->children == NULL) {
1566 reader->state = XML_TEXTREADER_END;
1567 return(0);
1568 }
1569
1570 reader->node = reader->doc->children;
1571 reader->state = XML_TEXTREADER_START;
1572 return(1);
1573 }
1574
1575 if (reader->state != XML_TEXTREADER_BACKTRACK) {
1576 if (reader->node->children != 0) {
1577 reader->node = reader->node->children;
1578 reader->depth++;
1579 reader->state = XML_TEXTREADER_START;
1580 return(1);
1581 }
1582
1583 if ((reader->node->type == XML_ELEMENT_NODE) ||
1584 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1585 reader->state = XML_TEXTREADER_BACKTRACK;
1586 return(1);
1587 }
1588 }
1589
1590 if (reader->node->next != 0) {
1591 reader->node = reader->node->next;
1592 reader->state = XML_TEXTREADER_START;
1593 return(1);
1594 }
1595
1596 if (reader->node->parent != 0) {
1597 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1598 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1599 reader->state = XML_TEXTREADER_END;
1600 return(0);
1601 }
1602
1603 reader->node = reader->node->parent;
1604 reader->depth--;
1605 reader->state = XML_TEXTREADER_BACKTRACK;
1606 return(1);
1607 }
1608
1609 reader->state = XML_TEXTREADER_END;
1610
1611 return(1);
1612}
1613
1614/**
1615 * xmlTextReaderNextTree:
1616 * @reader: the xmlTextReaderPtr used
1617 *
1618 * Skip to the node following the current one in document order while
1619 * avoiding the subtree if any.
1620 * Currently implemented only for Readers built on a document
1621 *
1622 * Returns 1 if the node was read successfully, 0 if there is no more
1623 * nodes to read, or -1 in case of error
1624 */
1625int
1626xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
1627 if (reader == NULL)
1628 return(-1);
1629 if (reader->doc == NULL) {
1630 TODO
1631 return(-1);
1632 }
1633
1634 if (reader->state == XML_TEXTREADER_END)
1635 return(0);
1636
1637 if (reader->node == 0)
1638 return(xmlTextReaderNextTree(reader));
1639
1640 if (reader->node->next != 0) {
1641 reader->node = reader->node->next;
1642 reader->state = XML_TEXTREADER_START;
1643 return(1);
1644 }
1645
1646 return(0);
1647}
1648
1649/************************************************************************
1650 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001651 * Constructor and destructors *
1652 * *
1653 ************************************************************************/
1654/**
1655 * xmlNewTextReader:
1656 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00001657 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001658 *
1659 * Create an xmlTextReader structure fed with @input
1660 *
1661 * Returns the new xmlTextReaderPtr or NULL in case of error
1662 */
1663xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00001664xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001665 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001666
1667 if (input == NULL)
1668 return(NULL);
1669 ret = xmlMalloc(sizeof(xmlTextReader));
1670 if (ret == NULL) {
1671 xmlGenericError(xmlGenericErrorContext,
1672 "xmlNewTextReader : malloc failed\n");
1673 return(NULL);
1674 }
1675 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001676 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001677 ret->entTab = NULL;
1678 ret->entMax = 0;
1679 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001680 ret->input = input;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001681 ret->buffer = xmlBufferCreateSize(100);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001682 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1683 if (ret->sax == NULL) {
1684 xmlFree(ret);
1685 xmlGenericError(xmlGenericErrorContext,
1686 "xmlNewTextReader : malloc failed\n");
1687 return(NULL);
1688 }
Daniel Veillard81273902003-09-30 00:43:48 +00001689 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001690 ret->startElement = ret->sax->startElement;
1691 ret->sax->startElement = xmlTextReaderStartElement;
1692 ret->endElement = ret->sax->endElement;
1693 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00001694#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001695 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00001696#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00001697 ret->startElementNs = ret->sax->startElementNs;
1698 ret->sax->startElementNs = xmlTextReaderStartElementNs;
1699 ret->endElementNs = ret->sax->endElementNs;
1700 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00001701#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00001702 } else {
1703 ret->startElementNs = NULL;
1704 ret->endElementNs = NULL;
1705 }
Daniel Veillard81273902003-09-30 00:43:48 +00001706#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00001707 ret->characters = ret->sax->characters;
1708 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001709 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001710 ret->cdataBlock = ret->sax->cdataBlock;
1711 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001712
Daniel Veillard67df8092002-12-16 22:04:11 +00001713 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001714 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001715 ret->curnode = NULL;
Daniel Veillard53350552003-09-18 13:35:51 +00001716 if (ret->input->buffer->use < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00001717 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00001718 }
1719 if (ret->input->buffer->use >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001720 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillardea7751d2002-12-20 00:16:24 +00001721 (const char *) ret->input->buffer->content, 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001722 ret->base = 0;
1723 ret->cur = 4;
1724 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001725 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001726 ret->base = 0;
1727 ret->cur = 0;
1728 }
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00001729 if (ret->ctxt == NULL) {
1730 xmlGenericError(xmlGenericErrorContext,
1731 "xmlNewTextReader : malloc failed\n");
1732 xmlFree(ret->sax);
1733 xmlFree(ret);
1734 return(NULL);
1735 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001736 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001737 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001738 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001739 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00001740 /*
1741 * use the parser dictionnary to allocate all elements and attributes names
1742 */
1743 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001744 ret->dict = ret->ctxt->dict;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001745 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001746}
1747
1748/**
1749 * xmlNewTextReaderFilename:
1750 * @URI: the URI of the resource to process
1751 *
1752 * Create an xmlTextReader structure fed with the resource at @URI
1753 *
1754 * Returns the new xmlTextReaderPtr or NULL in case of error
1755 */
1756xmlTextReaderPtr
1757xmlNewTextReaderFilename(const char *URI) {
1758 xmlParserInputBufferPtr input;
1759 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001760 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001761
1762 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
1763 if (input == NULL)
1764 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001765 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001766 if (ret == NULL) {
1767 xmlFreeParserInputBuffer(input);
1768 return(NULL);
1769 }
1770 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001771 if (ret->ctxt->directory == NULL)
1772 directory = xmlParserGetDirectory(URI);
1773 if ((ret->ctxt->directory == NULL) && (directory != NULL))
1774 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
1775 if (directory != NULL)
1776 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001777 return(ret);
1778}
1779
1780/**
1781 * xmlFreeTextReader:
1782 * @reader: the xmlTextReaderPtr
1783 *
1784 * Deallocate all the resources associated to the reader
1785 */
1786void
1787xmlFreeTextReader(xmlTextReaderPtr reader) {
1788 if (reader == NULL)
1789 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001790#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001791 if (reader->rngSchemas != NULL) {
1792 xmlRelaxNGFree(reader->rngSchemas);
1793 reader->rngSchemas = NULL;
1794 }
1795 if (reader->rngValidCtxt != NULL) {
1796 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
1797 reader->rngValidCtxt = NULL;
1798 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00001799#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001800 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001801 if (reader->dict == reader->ctxt->dict)
1802 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001803 if (reader->ctxt->myDoc != NULL) {
1804 if (reader->preserve == 0)
1805 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
1806 reader->ctxt->myDoc = NULL;
1807 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00001808 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
1809 (reader->ctxt->vctxt.vstateMax > 0)){
1810 xmlFree(reader->ctxt->vctxt.vstateTab);
1811 reader->ctxt->vctxt.vstateTab = 0;
1812 reader->ctxt->vctxt.vstateMax = 0;
1813 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001814 if (reader->allocs & XML_TEXTREADER_CTXT)
1815 xmlFreeParserCtxt(reader->ctxt);
1816 }
1817 if (reader->sax != NULL)
1818 xmlFree(reader->sax);
1819 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
1820 xmlFreeParserInputBuffer(reader->input);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001821 if (reader->faketext != NULL) {
1822 xmlFreeNode(reader->faketext);
1823 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001824 if (reader->buffer != NULL)
1825 xmlBufferFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001826 if (reader->entTab != NULL)
1827 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001828 if (reader->dict != NULL)
1829 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001830 xmlFree(reader);
1831}
1832
1833/************************************************************************
1834 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001835 * Methods for XmlTextReader *
1836 * *
1837 ************************************************************************/
1838/**
1839 * xmlTextReaderClose:
1840 * @reader: the xmlTextReaderPtr used
1841 *
1842 * This method releases any resources allocated by the current instance
1843 * changes the state to Closed and close any underlying input.
1844 *
1845 * Returns 0 or -1 in case of error
1846 */
1847int
1848xmlTextReaderClose(xmlTextReaderPtr reader) {
1849 if (reader == NULL)
1850 return(-1);
1851 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001852 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001853 reader->mode = XML_TEXTREADER_MODE_CLOSED;
1854 if (reader->ctxt != NULL) {
1855 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001856 if (reader->preserve == 0)
1857 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001858 reader->ctxt->myDoc = NULL;
1859 }
1860 if (reader->allocs & XML_TEXTREADER_CTXT) {
1861 xmlFreeParserCtxt(reader->ctxt);
1862 reader->allocs -= XML_TEXTREADER_CTXT;
1863 }
1864 }
1865 if (reader->sax != NULL) {
1866 xmlFree(reader->sax);
1867 reader->sax = NULL;
1868 }
1869 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
1870 xmlFreeParserInputBuffer(reader->input);
1871 reader->allocs -= XML_TEXTREADER_INPUT;
1872 }
1873 return(0);
1874}
1875
1876/**
1877 * xmlTextReaderGetAttributeNo:
1878 * @reader: the xmlTextReaderPtr used
1879 * @no: the zero-based index of the attribute relative to the containing element
1880 *
1881 * Provides the value of the attribute with the specified index relative
1882 * to the containing element.
1883 *
1884 * Returns a string containing the value of the specified attribute, or NULL
1885 * in case of error. The string must be deallocated by the caller.
1886 */
1887xmlChar *
1888xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
1889 xmlChar *ret;
1890 int i;
1891 xmlAttrPtr cur;
1892 xmlNsPtr ns;
1893
1894 if (reader == NULL)
1895 return(NULL);
1896 if (reader->node == NULL)
1897 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001898 if (reader->curnode != NULL)
1899 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001900 /* TODO: handle the xmlDecl */
1901 if (reader->node->type != XML_ELEMENT_NODE)
1902 return(NULL);
1903
1904 ns = reader->node->nsDef;
1905 for (i = 0;(i < no) && (ns != NULL);i++) {
1906 ns = ns->next;
1907 }
1908 if (ns != NULL)
1909 return(xmlStrdup(ns->href));
1910
1911 cur = reader->node->properties;
1912 if (cur == NULL)
1913 return(NULL);
1914 for (;i < no;i++) {
1915 cur = cur->next;
1916 if (cur == NULL)
1917 return(NULL);
1918 }
1919 /* TODO walk the DTD if present */
1920
1921 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
1922 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1923 return(ret);
1924}
1925
1926/**
1927 * xmlTextReaderGetAttribute:
1928 * @reader: the xmlTextReaderPtr used
1929 * @name: the qualified name of the attribute.
1930 *
1931 * Provides the value of the attribute with the specified qualified name.
1932 *
1933 * Returns a string containing the value of the specified attribute, or NULL
1934 * in case of error. The string must be deallocated by the caller.
1935 */
1936xmlChar *
1937xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
1938 xmlChar *prefix = NULL;
1939 xmlChar *localname;
1940 xmlNsPtr ns;
1941 xmlChar *ret = NULL;
1942
1943 if ((reader == NULL) || (name == NULL))
1944 return(NULL);
1945 if (reader->node == NULL)
1946 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001947 if (reader->curnode != NULL)
1948 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001949
1950 /* TODO: handle the xmlDecl */
1951 if (reader->node->type != XML_ELEMENT_NODE)
1952 return(NULL);
1953
1954 localname = xmlSplitQName2(name, &prefix);
1955 if (localname == NULL)
1956 return(xmlGetProp(reader->node, name));
1957
1958 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
1959 if (ns != NULL)
1960 ret = xmlGetNsProp(reader->node, localname, ns->href);
1961
1962 if (localname != NULL)
1963 xmlFree(localname);
1964 if (prefix != NULL)
1965 xmlFree(prefix);
1966 return(ret);
1967}
1968
1969
1970/**
1971 * xmlTextReaderGetAttributeNs:
1972 * @reader: the xmlTextReaderPtr used
1973 * @localName: the local name of the attribute.
1974 * @namespaceURI: the namespace URI of the attribute.
1975 *
1976 * Provides the value of the specified attribute
1977 *
1978 * Returns a string containing the value of the specified attribute, or NULL
1979 * in case of error. The string must be deallocated by the caller.
1980 */
1981xmlChar *
1982xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
1983 const xmlChar *namespaceURI) {
1984 if ((reader == NULL) || (localName == NULL))
1985 return(NULL);
1986 if (reader->node == NULL)
1987 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001988 if (reader->curnode != NULL)
1989 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00001990
1991 /* TODO: handle the xmlDecl */
1992 if (reader->node->type != XML_ELEMENT_NODE)
1993 return(NULL);
1994
1995 return(xmlGetNsProp(reader->node, localName, namespaceURI));
1996}
1997
Daniel Veillardda46d2d2002-12-15 23:36:49 +00001998/**
1999 * xmlTextReaderGetRemainder:
2000 * @reader: the xmlTextReaderPtr used
2001 *
2002 * Method to get the remainder of the buffered XML. this method stops the
2003 * parser, set its state to End Of File and return the input stream with
2004 * what is left that the parser did not use.
2005 *
2006 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2007 * in case of error.
2008 */
2009xmlParserInputBufferPtr
2010xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2011 xmlParserInputBufferPtr ret = NULL;
2012
2013 if (reader == NULL)
2014 return(NULL);
2015 if (reader->node == NULL)
2016 return(NULL);
2017
2018 reader->node = NULL;
2019 reader->curnode = NULL;
2020 reader->mode = XML_TEXTREADER_MODE_EOF;
2021 if (reader->ctxt != NULL) {
2022 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002023 if (reader->preserve == 0)
2024 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002025 reader->ctxt->myDoc = NULL;
2026 }
2027 if (reader->allocs & XML_TEXTREADER_CTXT) {
2028 xmlFreeParserCtxt(reader->ctxt);
2029 reader->allocs -= XML_TEXTREADER_CTXT;
2030 }
2031 }
2032 if (reader->sax != NULL) {
2033 xmlFree(reader->sax);
2034 reader->sax = NULL;
2035 }
2036 if (reader->allocs & XML_TEXTREADER_INPUT) {
2037 ret = reader->input;
2038 reader->allocs -= XML_TEXTREADER_INPUT;
2039 } else {
2040 /*
2041 * Hum, one may need to duplicate the data structure because
2042 * without reference counting the input may be freed twice:
2043 * - by the layer which allocated it.
2044 * - by the layer to which would have been returned to.
2045 */
2046 TODO
2047 return(NULL);
2048 }
2049 return(ret);
2050}
2051
2052/**
2053 * xmlTextReaderLookupNamespace:
2054 * @reader: the xmlTextReaderPtr used
2055 * @prefix: the prefix whose namespace URI is to be resolved. To return
2056 * the default namespace, specify NULL
2057 *
2058 * Resolves a namespace prefix in the scope of the current element.
2059 *
2060 * Returns a string containing the namespace URI to which the prefix maps
2061 * or NULL in case of error. The string must be deallocated by the caller.
2062 */
2063xmlChar *
2064xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2065 xmlNsPtr ns;
2066
2067 if (reader == NULL)
2068 return(NULL);
2069 if (reader->node == NULL)
2070 return(NULL);
2071
2072 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2073 if (ns == NULL)
2074 return(NULL);
2075 return(xmlStrdup(ns->href));
2076}
2077
2078/**
2079 * xmlTextReaderMoveToAttributeNo:
2080 * @reader: the xmlTextReaderPtr used
2081 * @no: the zero-based index of the attribute relative to the containing
2082 * element.
2083 *
2084 * Moves the position of the current instance to the attribute with
2085 * the specified index relative to the containing element.
2086 *
2087 * Returns 1 in case of success, -1 in case of error, 0 if not found
2088 */
2089int
2090xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2091 int i;
2092 xmlAttrPtr cur;
2093 xmlNsPtr ns;
2094
2095 if (reader == NULL)
2096 return(-1);
2097 if (reader->node == NULL)
2098 return(-1);
2099 /* TODO: handle the xmlDecl */
2100 if (reader->node->type != XML_ELEMENT_NODE)
2101 return(-1);
2102
2103 reader->curnode = NULL;
2104
2105 ns = reader->node->nsDef;
2106 for (i = 0;(i < no) && (ns != NULL);i++) {
2107 ns = ns->next;
2108 }
2109 if (ns != NULL) {
2110 reader->curnode = (xmlNodePtr) ns;
2111 return(1);
2112 }
2113
2114 cur = reader->node->properties;
2115 if (cur == NULL)
2116 return(0);
2117 for (;i < no;i++) {
2118 cur = cur->next;
2119 if (cur == NULL)
2120 return(0);
2121 }
2122 /* TODO walk the DTD if present */
2123
2124 reader->curnode = (xmlNodePtr) cur;
2125 return(1);
2126}
2127
2128/**
2129 * xmlTextReaderMoveToAttribute:
2130 * @reader: the xmlTextReaderPtr used
2131 * @name: the qualified name of the attribute.
2132 *
2133 * Moves the position of the current instance to the attribute with
2134 * the specified qualified name.
2135 *
2136 * Returns 1 in case of success, -1 in case of error, 0 if not found
2137 */
2138int
2139xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2140 xmlChar *prefix = NULL;
2141 xmlChar *localname;
2142 xmlNsPtr ns;
2143 xmlAttrPtr prop;
2144
2145 if ((reader == NULL) || (name == NULL))
2146 return(-1);
2147 if (reader->node == NULL)
2148 return(-1);
2149
2150 /* TODO: handle the xmlDecl */
2151 if (reader->node->type != XML_ELEMENT_NODE)
2152 return(0);
2153
2154 localname = xmlSplitQName2(name, &prefix);
2155 if (localname == NULL) {
2156 /*
2157 * Namespace default decl
2158 */
2159 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2160 ns = reader->node->nsDef;
2161 while (ns != NULL) {
2162 if (ns->prefix == NULL) {
2163 reader->curnode = (xmlNodePtr) ns;
2164 return(1);
2165 }
2166 ns = ns->next;
2167 }
2168 return(0);
2169 }
2170
2171 prop = reader->node->properties;
2172 while (prop != NULL) {
2173 /*
2174 * One need to have
2175 * - same attribute names
2176 * - and the attribute carrying that namespace
2177 */
2178 if ((xmlStrEqual(prop->name, name)) &&
2179 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2180 reader->curnode = (xmlNodePtr) prop;
2181 return(1);
2182 }
2183 prop = prop->next;
2184 }
2185 return(0);
2186 }
2187
2188 /*
2189 * Namespace default decl
2190 */
2191 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2192 ns = reader->node->nsDef;
2193 while (ns != NULL) {
2194 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2195 reader->curnode = (xmlNodePtr) ns;
2196 goto found;
2197 }
2198 ns = ns->next;
2199 }
2200 goto not_found;
2201 }
2202 prop = reader->node->properties;
2203 while (prop != NULL) {
2204 /*
2205 * One need to have
2206 * - same attribute names
2207 * - and the attribute carrying that namespace
2208 */
2209 if ((xmlStrEqual(prop->name, localname)) &&
2210 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2211 reader->curnode = (xmlNodePtr) prop;
2212 goto found;
2213 }
2214 prop = prop->next;
2215 }
2216not_found:
2217 if (localname != NULL)
2218 xmlFree(localname);
2219 if (prefix != NULL)
2220 xmlFree(prefix);
2221 return(0);
2222
2223found:
2224 if (localname != NULL)
2225 xmlFree(localname);
2226 if (prefix != NULL)
2227 xmlFree(prefix);
2228 return(1);
2229}
2230
2231/**
2232 * xmlTextReaderMoveToAttributeNs:
2233 * @reader: the xmlTextReaderPtr used
2234 * @localName: the local name of the attribute.
2235 * @namespaceURI: the namespace URI of the attribute.
2236 *
2237 * Moves the position of the current instance to the attribute with the
2238 * specified local name and namespace URI.
2239 *
2240 * Returns 1 in case of success, -1 in case of error, 0 if not found
2241 */
2242int
2243xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2244 const xmlChar *localName, const xmlChar *namespaceURI) {
2245 xmlAttrPtr prop;
2246 xmlNodePtr node;
2247
2248 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2249 return(-1);
2250 if (reader->node == NULL)
2251 return(-1);
2252 if (reader->node->type != XML_ELEMENT_NODE)
2253 return(0);
2254 node = reader->node;
2255
2256 /*
2257 * A priori reading http://www.w3.org/TR/REC-xml-names/ there is no
2258 * namespace name associated to "xmlns"
2259 */
2260 prop = node->properties;
2261 while (prop != NULL) {
2262 /*
2263 * One need to have
2264 * - same attribute names
2265 * - and the attribute carrying that namespace
2266 */
2267 if (xmlStrEqual(prop->name, localName) &&
2268 ((prop->ns != NULL) &&
2269 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2270 reader->curnode = (xmlNodePtr) prop;
2271 return(1);
2272 }
2273 prop = prop->next;
2274 }
2275 return(0);
2276}
2277
2278/**
2279 * xmlTextReaderMoveToFirstAttribute:
2280 * @reader: the xmlTextReaderPtr used
2281 *
2282 * Moves the position of the current instance to the first attribute
2283 * associated with the current node.
2284 *
2285 * Returns 1 in case of success, -1 in case of error, 0 if not found
2286 */
2287int
2288xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2289 if (reader == NULL)
2290 return(-1);
2291 if (reader->node == NULL)
2292 return(-1);
2293 if (reader->node->type != XML_ELEMENT_NODE)
2294 return(0);
2295
2296 if (reader->node->nsDef != NULL) {
2297 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2298 return(1);
2299 }
2300 if (reader->node->properties != NULL) {
2301 reader->curnode = (xmlNodePtr) reader->node->properties;
2302 return(1);
2303 }
2304 return(0);
2305}
2306
2307/**
2308 * xmlTextReaderMoveToNextAttribute:
2309 * @reader: the xmlTextReaderPtr used
2310 *
2311 * Moves the position of the current instance to the next attribute
2312 * associated with the current node.
2313 *
2314 * Returns 1 in case of success, -1 in case of error, 0 if not found
2315 */
2316int
2317xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2318 if (reader == NULL)
2319 return(-1);
2320 if (reader->node == NULL)
2321 return(-1);
2322 if (reader->node->type != XML_ELEMENT_NODE)
2323 return(0);
2324 if (reader->curnode == NULL)
2325 return(xmlTextReaderMoveToFirstAttribute(reader));
2326
2327 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2328 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2329 if (ns->next != NULL) {
2330 reader->curnode = (xmlNodePtr) ns->next;
2331 return(1);
2332 }
2333 if (reader->node->properties != NULL) {
2334 reader->curnode = (xmlNodePtr) reader->node->properties;
2335 return(1);
2336 }
2337 return(0);
2338 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2339 (reader->curnode->next != NULL)) {
2340 reader->curnode = reader->curnode->next;
2341 return(1);
2342 }
2343 return(0);
2344}
2345
2346/**
2347 * xmlTextReaderMoveToElement:
2348 * @reader: the xmlTextReaderPtr used
2349 *
2350 * Moves the position of the current instance to the node that
2351 * contains the current Attribute node.
2352 *
2353 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2354 */
2355int
2356xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2357 if (reader == NULL)
2358 return(-1);
2359 if (reader->node == NULL)
2360 return(-1);
2361 if (reader->node->type != XML_ELEMENT_NODE)
2362 return(0);
2363 if (reader->curnode != NULL) {
2364 reader->curnode = NULL;
2365 return(1);
2366 }
2367 return(0);
2368}
2369
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002370/**
2371 * xmlTextReaderReadAttributeValue:
2372 * @reader: the xmlTextReaderPtr used
2373 *
2374 * Parses an attribute value into one or more Text and EntityReference nodes.
2375 *
2376 * Returns 1 in case of success, 0 if the reader was not positionned on an
2377 * ttribute node or all the attribute values have been read, or -1
2378 * in case of error.
2379 */
2380int
2381xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2382 if (reader == NULL)
2383 return(-1);
2384 if (reader->node == NULL)
2385 return(-1);
2386 if (reader->curnode == NULL)
2387 return(0);
2388 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2389 if (reader->curnode->children == NULL)
2390 return(0);
2391 reader->curnode = reader->curnode->children;
2392 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2393 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2394
2395 if (reader->faketext == NULL) {
2396 reader->faketext = xmlNewDocText(reader->node->doc,
2397 ns->href);
2398 } else {
2399 if (reader->faketext->content != NULL)
2400 xmlFree(reader->faketext->content);
2401 reader->faketext->content = xmlStrdup(ns->href);
2402 }
2403 reader->curnode = reader->faketext;
2404 } else {
2405 if (reader->curnode->next == NULL)
2406 return(0);
2407 reader->curnode = reader->curnode->next;
2408 }
2409 return(1);
2410}
2411
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002412/************************************************************************
2413 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002414 * Acces API to the current node *
2415 * *
2416 ************************************************************************/
2417/**
2418 * xmlTextReaderAttributeCount:
2419 * @reader: the xmlTextReaderPtr used
2420 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002421 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002422 *
2423 * Returns 0 i no attributes, -1 in case of error or the attribute count
2424 */
2425int
2426xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2427 int ret;
2428 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002429 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002430 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002431
2432 if (reader == NULL)
2433 return(-1);
2434 if (reader->node == NULL)
2435 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002436
2437 if (reader->curnode != NULL)
2438 node = reader->curnode;
2439 else
2440 node = reader->node;
2441
2442 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002443 return(0);
2444 if ((reader->state == XML_TEXTREADER_END) ||
2445 (reader->state == XML_TEXTREADER_BACKTRACK))
2446 return(0);
2447 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002448 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002449 while (attr != NULL) {
2450 ret++;
2451 attr = attr->next;
2452 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002453 ns = node->nsDef;
2454 while (ns != NULL) {
2455 ret++;
2456 ns = ns->next;
2457 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002458 return(ret);
2459}
2460
2461/**
2462 * xmlTextReaderNodeType:
2463 * @reader: the xmlTextReaderPtr used
2464 *
2465 * Get the node type of the current node
2466 * Reference:
2467 * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html
2468 *
2469 * Returns the xmlNodeType of the current node or -1 in case of error
2470 */
2471int
2472xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002473 xmlNodePtr node;
Daniel Veillardd6038e02003-07-30 16:37:18 +00002474
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002475 if (reader == NULL)
2476 return(-1);
2477 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002478 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002479 if (reader->curnode != NULL)
2480 node = reader->curnode;
2481 else
2482 node = reader->node;
2483 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002484 case XML_ELEMENT_NODE:
2485 if ((reader->state == XML_TEXTREADER_END) ||
2486 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00002487 return(XML_READER_TYPE_END_ELEMENT);
2488 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00002489 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002490 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002491 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002492 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002493 if (xmlIsBlankNode(reader->node)) {
2494 if (xmlNodeGetSpacePreserve(reader->node))
2495 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
2496 else
2497 return(XML_READER_TYPE_WHITESPACE);
2498 } else {
2499 return(XML_READER_TYPE_TEXT);
2500 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002501 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002502 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002503 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002504 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002505 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002506 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002507 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002508 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002509 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002510 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002511 case XML_DOCUMENT_NODE:
2512 case XML_HTML_DOCUMENT_NODE:
2513#ifdef LIBXML_DOCB_ENABLED
2514 case XML_DOCB_DOCUMENT_NODE:
2515#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00002516 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002517 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002518 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002519 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002520 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002521 case XML_DOCUMENT_TYPE_NODE:
2522 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002523 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002524
2525 case XML_ELEMENT_DECL:
2526 case XML_ATTRIBUTE_DECL:
2527 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002528 case XML_XINCLUDE_START:
2529 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00002530 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002531 }
2532 return(-1);
2533}
2534
2535/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00002536 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002537 * @reader: the xmlTextReaderPtr used
2538 *
2539 * Check if the current node is empty
2540 *
2541 * Returns 1 if empty, 0 if not and -1 in case of error
2542 */
2543int
2544xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
2545 if ((reader == NULL) || (reader->node == NULL))
2546 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00002547 if (reader->node->type != XML_ELEMENT_NODE)
2548 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00002549 if (reader->curnode != NULL)
2550 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002551 if (reader->node->children != NULL)
2552 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00002553 if (reader->state == XML_TEXTREADER_END)
2554 return(0);
Daniel Veillarde8039df2003-10-27 11:25:13 +00002555 return((reader->node->extra & NODE_IS_EMPTY) != 0);
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);
Daniel Veillarde8039df2003-10-27 11:25:13 +00003354 cur->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003355
3356 parent = cur->parent;;
3357 while (parent != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00003358 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003359 parent = parent->parent;
3360 }
3361 return(cur);
3362}
3363
3364/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003365 * xmlTextReaderCurrentDoc:
3366 * @reader: the xmlTextReaderPtr used
3367 *
3368 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003369 * current document being accessed by the xmlTextReader.
3370 * NOTE: as a result of this call, the reader will not destroy the
3371 * associated XML document and calling xmlFreeDoc() on the result
3372 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00003373 *
3374 * Returns the xmlDocPtr or NULL in case of error.
3375 */
3376xmlDocPtr
3377xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003378 if (reader == NULL)
3379 return(NULL);
3380 if (reader->doc != NULL)
3381 return(reader->doc);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003382 if ((reader == NULL) || (reader->ctxt == NULL) ||
3383 (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00003384 return(NULL);
3385
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003386 reader->preserve = 1;
3387 if ((reader->ctxt->myDoc->dict != NULL) &&
3388 (reader->ctxt->myDoc->dict == reader->ctxt->dict))
3389 xmlDictReference(reader->ctxt->dict);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003390 return(reader->ctxt->myDoc);
3391}
3392
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003393#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00003394/**
Daniel Veillard33300b42003-04-17 09:09:19 +00003395 * xmlTextReaderRelaxNGSetSchema:
3396 * @reader: the xmlTextReaderPtr used
3397 * @schema: a precompiled RelaxNG schema
3398 *
3399 * Use RelaxNG to validate the document as it is processed.
3400 * Activation is only possible before the first Read().
3401 * if @schema is NULL, then RelaxNG validation is desactivated.
3402 @ The @schema should not be freed until the reader is deallocated
3403 * or its use has been deactivated.
3404 *
3405 * Returns 0 in case the RelaxNG validation could be (des)activated and
3406 * -1 in case of error.
3407 */
3408int
3409xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
3410 if (schema == NULL) {
3411 if (reader->rngSchemas != NULL) {
3412 xmlRelaxNGFree(reader->rngSchemas);
3413 reader->rngSchemas = NULL;
3414 }
3415 if (reader->rngValidCtxt != NULL) {
3416 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3417 reader->rngValidCtxt = NULL;
3418 }
3419 return(0);
3420 }
3421 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3422 return(-1);
3423 if (reader->rngSchemas != NULL) {
3424 xmlRelaxNGFree(reader->rngSchemas);
3425 reader->rngSchemas = NULL;
3426 }
3427 if (reader->rngValidCtxt != NULL) {
3428 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3429 reader->rngValidCtxt = NULL;
3430 }
3431 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
3432 if (reader->rngValidCtxt == NULL)
3433 return(-1);
3434 if (reader->errorFunc != NULL) {
3435 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3436 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3437 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3438 reader->errorFuncArg);
3439 }
3440 reader->rngValidErrors = 0;
3441 reader->rngFullNode = NULL;
3442 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3443 return(0);
3444}
3445
3446/**
Daniel Veillardf4e55762003-04-15 23:32:22 +00003447 * xmlTextReaderRelaxNGValidate:
3448 * @reader: the xmlTextReaderPtr used
3449 * @rng: the path to a RelaxNG schema or NULL
3450 *
3451 * Use RelaxNG to validate the document as it is processed.
3452 * Activation is only possible before the first Read().
3453 * if @rng is NULL, then RelaxNG validation is desactivated.
3454 *
3455 * Returns 0 in case the RelaxNG validation could be (des)activated and
3456 * -1 in case of error.
3457 */
3458int
3459xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
3460 xmlRelaxNGParserCtxtPtr ctxt;
3461
3462 if (reader == NULL)
3463 return(-1);
3464
3465 if (rng == NULL) {
3466 if (reader->rngSchemas != NULL) {
3467 xmlRelaxNGFree(reader->rngSchemas);
3468 reader->rngSchemas = NULL;
3469 }
3470 if (reader->rngValidCtxt != NULL) {
3471 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3472 reader->rngValidCtxt = NULL;
3473 }
3474 return(0);
3475 }
3476 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3477 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00003478 if (reader->rngSchemas != NULL) {
3479 xmlRelaxNGFree(reader->rngSchemas);
3480 reader->rngSchemas = NULL;
3481 }
3482 if (reader->rngValidCtxt != NULL) {
3483 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
3484 reader->rngValidCtxt = NULL;
3485 }
Daniel Veillardf4e55762003-04-15 23:32:22 +00003486 ctxt = xmlRelaxNGNewParserCtxt(rng);
3487 if (reader->errorFunc != NULL) {
3488 xmlRelaxNGSetParserErrors(ctxt,
3489 (xmlRelaxNGValidityErrorFunc) reader->errorFunc,
3490 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3491 reader->errorFuncArg);
3492 }
3493 reader->rngSchemas = xmlRelaxNGParse(ctxt);
3494 xmlRelaxNGFreeParserCtxt(ctxt);
3495 if (reader->rngSchemas == NULL)
3496 return(-1);
3497 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
3498 if (reader->rngValidCtxt == NULL)
3499 return(-1);
3500 if (reader->errorFunc != NULL) {
3501 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
3502 (xmlRelaxNGValidityErrorFunc)reader->errorFunc,
3503 (xmlRelaxNGValidityWarningFunc) reader->errorFunc,
3504 reader->errorFuncArg);
3505 }
3506 reader->rngValidErrors = 0;
3507 reader->rngFullNode = NULL;
3508 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
3509 return(0);
3510}
Daniel Veillard37fc84d2003-05-09 19:38:15 +00003511#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00003512
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003513/************************************************************************
3514 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00003515 * Error Handling Extensions *
3516 * *
3517 ************************************************************************/
3518
3519/* helper to build a xmlMalloc'ed string from a format and va_list */
3520static char *
3521xmlTextReaderBuildMessage(const char *msg, va_list ap) {
3522 int size;
3523 int chars;
3524 char *larger;
3525 char *str;
3526
Daniel Veillard3c908dc2003-04-19 00:07:51 +00003527 str = (char *) xmlMallocAtomic(150);
Daniel Veillard26f70262003-01-16 22:45:08 +00003528 if (str == NULL) {
3529 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3530 return NULL;
3531 }
3532
3533 size = 150;
3534
3535 while (1) {
3536 chars = vsnprintf(str, size, msg, ap);
3537 if ((chars > -1) && (chars < size))
3538 break;
3539 if (chars > -1)
3540 size += chars + 1;
3541 else
3542 size += 100;
3543 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
3544 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3545 xmlFree(str);
3546 return NULL;
3547 }
3548 str = larger;
3549 }
3550
3551 return str;
3552}
3553
Daniel Veillard417be3a2003-01-20 21:26:34 +00003554/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003555 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003556 * @locator: the xmlTextReaderLocatorPtr used
3557 *
3558 * Obtain the line number for the given locator.
3559 *
3560 * Returns the line number or -1 in case of error.
3561 */
3562int
3563xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
3564 /* we know that locator is a xmlParserCtxtPtr */
3565 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3566 int ret = -1;
3567
3568 if (ctx->node != NULL) {
3569 ret = xmlGetLineNo(ctx->node);
3570 }
3571 else {
3572 /* inspired from error.c */
3573 xmlParserInputPtr input;
3574 input = ctx->input;
3575 if ((input->filename == NULL) && (ctx->inputNr > 1))
3576 input = ctx->inputTab[ctx->inputNr - 2];
3577 if (input != NULL) {
3578 ret = input->line;
3579 }
3580 else {
3581 ret = -1;
3582 }
3583 }
3584
3585 return ret;
3586}
3587
3588/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00003589 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00003590 * @locator: the xmlTextReaderLocatorPtr used
3591 *
3592 * Obtain the base URI for the given locator.
3593 *
3594 * Returns the base URI or NULL in case of error.
3595 */
3596xmlChar *
3597xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
3598 /* we know that locator is a xmlParserCtxtPtr */
3599 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
3600 xmlChar *ret = NULL;
3601
3602 if (ctx->node != NULL) {
3603 ret = xmlNodeGetBase(NULL,ctx->node);
3604 }
3605 else {
3606 /* inspired from error.c */
3607 xmlParserInputPtr input;
3608 input = ctx->input;
3609 if ((input->filename == NULL) && (ctx->inputNr > 1))
3610 input = ctx->inputTab[ctx->inputNr - 2];
3611 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00003612 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillard417be3a2003-01-20 21:26:34 +00003613 }
3614 else {
3615 ret = NULL;
3616 }
3617 }
3618
3619 return ret;
3620}
3621
Daniel Veillard26f70262003-01-16 22:45:08 +00003622static void
William M. Brack899e64a2003-09-26 18:03:42 +00003623xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003624 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
3625 xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
3626
3627 if (str != NULL) {
3628 reader->errorFunc(reader->errorFuncArg,
3629 str,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003630 severity,
3631 (xmlTextReaderLocatorPtr)ctx);
Daniel Veillard26f70262003-01-16 22:45:08 +00003632 xmlFree(str);
3633 }
3634}
3635
3636static void
3637xmlTextReaderError(void *ctxt, const char *msg, ...) {
3638 va_list ap;
3639
3640 va_start(ap,msg);
3641 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003642 XML_PARSER_SEVERITY_ERROR,
Daniel Veillard26f70262003-01-16 22:45:08 +00003643 xmlTextReaderBuildMessage(msg,ap));
3644 va_end(ap);
3645
3646}
3647
3648static void
3649xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
3650 va_list ap;
3651
3652 va_start(ap,msg);
3653 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003654 XML_PARSER_SEVERITY_WARNING,
Daniel Veillard26f70262003-01-16 22:45:08 +00003655 xmlTextReaderBuildMessage(msg,ap));
3656 va_end(ap);
3657}
3658
3659static void
3660xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
3661 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003662 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003663
Daniel Veillard417be3a2003-01-20 21:26:34 +00003664 if ((len > 1) && (msg[len - 2] != ':')) {
3665 /*
3666 * some callbacks only report locator information:
3667 * skip them (mimicking behaviour in error.c)
3668 */
3669 va_start(ap,msg);
3670 xmlTextReaderGenericError(ctxt,
3671 XML_PARSER_SEVERITY_VALIDITY_ERROR,
3672 xmlTextReaderBuildMessage(msg,ap));
3673 va_end(ap);
3674 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003675}
3676
3677static void
3678xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
3679 va_list ap;
Daniel Veillard417be3a2003-01-20 21:26:34 +00003680 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00003681
Daniel Veillard417be3a2003-01-20 21:26:34 +00003682 if ((len != 0) && (msg[len - 1] != ':')) {
3683 /*
3684 * some callbacks only report locator information:
3685 * skip them (mimicking behaviour in error.c)
3686 */
3687 va_start(ap,msg);
3688 xmlTextReaderGenericError(ctxt,
3689 XML_PARSER_SEVERITY_VALIDITY_WARNING,
3690 xmlTextReaderBuildMessage(msg,ap));
3691 va_end(ap);
3692 }
Daniel Veillard26f70262003-01-16 22:45:08 +00003693}
3694
3695/**
3696 * xmlTextReaderSetErrorHandler:
3697 * @reader: the xmlTextReaderPtr used
3698 * @f: the callback function to call on error and warnings
3699 * @arg: a user argument to pass to the callback function
3700 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00003701 * Register a callback function that will be called on error and warnings.
3702 *
Daniel Veillard26f70262003-01-16 22:45:08 +00003703 * If @f is NULL, the default error and warning handlers are restored.
3704 */
3705void
3706xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
3707 xmlTextReaderErrorFunc f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003708 void *arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003709 if (f != NULL) {
3710 reader->ctxt->sax->error = xmlTextReaderError;
3711 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
3712 reader->ctxt->sax->warning = xmlTextReaderWarning;
3713 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
3714 reader->errorFunc = f;
3715 reader->errorFuncArg = arg;
3716 }
3717 else {
3718 /* restore defaults */
3719 reader->ctxt->sax->error = xmlParserError;
3720 reader->ctxt->vctxt.error = xmlParserValidityError;
3721 reader->ctxt->sax->warning = xmlParserWarning;
3722 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
3723 reader->errorFunc = NULL;
3724 reader->errorFuncArg = NULL;
3725 }
3726}
3727
Daniel Veillard417be3a2003-01-20 21:26:34 +00003728/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00003729 * xmlTextReaderIsValid:
3730 * @reader: the xmlTextReaderPtr used
3731 *
3732 * Retrieve the validity status from the parser context
3733 *
3734 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
3735 */
3736int
3737xmlTextReaderIsValid(xmlTextReaderPtr reader) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00003738 if (reader == NULL) return(-1);
3739#ifdef LIBXML_SCHEMAS_ENABLED
3740 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
3741 return(reader->rngValidErrors == 0);
3742#endif
3743 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
3744 (reader->ctxt != NULL))
3745 return(reader->ctxt->valid);
3746 return(0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00003747}
3748
3749/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00003750 * xmlTextReaderGetErrorHandler:
3751 * @reader: the xmlTextReaderPtr used
3752 * @f: the callback function or NULL is no callback has been registered
3753 * @arg: a user argument
3754 *
3755 * Retrieve the error callback function and user argument.
3756 */
Daniel Veillard26f70262003-01-16 22:45:08 +00003757void
3758xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
3759 xmlTextReaderErrorFunc *f,
Daniel Veillard417be3a2003-01-20 21:26:34 +00003760 void **arg) {
Daniel Veillard26f70262003-01-16 22:45:08 +00003761 *f = reader->errorFunc;
3762 *arg = reader->errorFuncArg;
3763}
3764
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003765
3766/************************************************************************
3767 * *
3768 * New set (2.6.0) of simpler and more flexible APIs *
3769 * *
3770 ************************************************************************/
3771
3772/**
3773 * xmlTextReaderSetup:
3774 * @reader: an XML reader
3775 * @URL: the base URL to use for the document
3776 * @encoding: the document encoding, or NULL
3777 * @options: a combination of xmlParserOption(s)
3778 * @reuse: keep the context for reuse
3779 *
3780 * Setup an XML reader with new options
3781 *
3782 * Returns 0 in case of success and -1 in case of error.
3783 */
3784static int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003785xmlTextReaderSetup(xmlTextReaderPtr reader,
3786 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003787 const char *encoding, int options)
3788{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003789 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003790 return (-1);
3791
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003792 reader->doc = NULL;
3793 reader->entNr = 0;
3794 if ((input != NULL) && (reader->input != NULL) &&
3795 (reader->allocs & XML_TEXTREADER_INPUT)) {
3796 xmlFreeParserInputBuffer(reader->input);
3797 reader->input = NULL;
3798 reader->allocs -= XML_TEXTREADER_INPUT;
3799 }
3800 if (input != NULL) {
3801 reader->input = input;
3802 reader->allocs |= XML_TEXTREADER_INPUT;
3803 }
3804 if (reader->buffer == NULL)
3805 reader->buffer = xmlBufferCreateSize(100);
3806 if (reader->buffer == NULL) {
3807 xmlGenericError(xmlGenericErrorContext,
3808 "xmlTextReaderSetup : malloc failed\n");
3809 return (-1);
3810 }
3811 if (reader->sax == NULL)
3812 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
3813 if (reader->sax == NULL) {
3814 xmlGenericError(xmlGenericErrorContext,
3815 "xmlTextReaderSetup : malloc failed\n");
3816 return (-1);
3817 }
3818 xmlSAXVersion(reader->sax, 2);
3819 reader->startElement = reader->sax->startElement;
3820 reader->sax->startElement = xmlTextReaderStartElement;
3821 reader->endElement = reader->sax->endElement;
3822 reader->sax->endElement = xmlTextReaderEndElement;
3823#ifdef LIBXML_SAX1_ENABLED
3824 if (reader->sax->initialized == XML_SAX2_MAGIC) {
3825#endif /* LIBXML_SAX1_ENABLED */
3826 reader->startElementNs = reader->sax->startElementNs;
3827 reader->sax->startElementNs = xmlTextReaderStartElementNs;
3828 reader->endElementNs = reader->sax->endElementNs;
3829 reader->sax->endElementNs = xmlTextReaderEndElementNs;
3830#ifdef LIBXML_SAX1_ENABLED
3831 } else {
3832 reader->startElementNs = NULL;
3833 reader->endElementNs = NULL;
3834 }
3835#endif /* LIBXML_SAX1_ENABLED */
3836 reader->characters = reader->sax->characters;
3837 reader->sax->characters = xmlTextReaderCharacters;
3838 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
3839 reader->cdataBlock = reader->sax->cdataBlock;
3840 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
3841
3842 reader->mode = XML_TEXTREADER_MODE_INITIAL;
3843 reader->node = NULL;
3844 reader->curnode = NULL;
3845 if (input != NULL) {
3846 if (reader->input->buffer->use < 4) {
3847 xmlParserInputBufferRead(input, 4);
3848 }
3849 if (reader->ctxt == NULL) {
3850 if (reader->input->buffer->use >= 4) {
3851 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
3852 (const char *) reader->input->buffer->content, 4, URL);
3853 reader->base = 0;
3854 reader->cur = 4;
3855 } else {
3856 reader->ctxt =
3857 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
3858 reader->base = 0;
3859 reader->cur = 0;
3860 }
3861 } else {
3862 xmlParserInputPtr inputStream;
3863 xmlParserInputBufferPtr buf;
3864 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
3865
3866 if (reader->ctxt->myDoc != NULL)
3867 xmlDictReference(reader->ctxt->myDoc->dict);
3868 xmlCtxtReset(reader->ctxt);
3869 buf = xmlAllocParserInputBuffer(enc);
3870 if (buf == NULL) return(-1);
3871 inputStream = xmlNewInputStream(reader->ctxt);
3872 if (inputStream == NULL) {
3873 xmlFreeParserInputBuffer(buf);
3874 return(-1);
3875 }
3876
3877 if (URL == NULL)
3878 inputStream->filename = NULL;
3879 else
3880 inputStream->filename = (char *)
3881 xmlCanonicPath((const xmlChar *) URL);
3882 inputStream->buf = buf;
3883 inputStream->base = inputStream->buf->buffer->content;
3884 inputStream->cur = inputStream->buf->buffer->content;
3885 inputStream->end =
3886 &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
3887
3888 inputPush(reader->ctxt, inputStream);
3889 reader->cur = 0;
3890 }
3891 if (reader->ctxt == NULL) {
3892 xmlGenericError(xmlGenericErrorContext,
3893 "xmlTextReaderSetup : malloc failed\n");
3894 return (-1);
3895 }
3896 }
3897 if (reader->dict != NULL) {
3898 if (reader->ctxt->dict != NULL) {
3899 if (reader->dict != reader->ctxt->dict) {
3900 xmlDictFree(reader->dict);
3901 reader->dict = reader->ctxt->dict;
3902 }
3903 } else {
3904 reader->ctxt->dict = reader->dict;
3905 }
3906 } else {
3907 if (reader->ctxt->dict == NULL)
3908 reader->ctxt->dict = xmlDictCreate();
3909 reader->dict = reader->ctxt->dict;
3910 }
3911 reader->ctxt->_private = reader;
3912 reader->ctxt->linenumbers = 1;
3913 reader->ctxt->dictNames = 1;
3914 /*
3915 * use the parser dictionnary to allocate all elements and attributes names
3916 */
3917 reader->ctxt->docdict = 1;
3918
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003919 xmlCtxtUseOptions(reader->ctxt, options);
3920 if (encoding != NULL) {
3921 xmlCharEncodingHandlerPtr hdlr;
3922
3923 hdlr = xmlFindCharEncodingHandler(encoding);
3924 if (hdlr != NULL)
3925 xmlSwitchToEncoding(reader->ctxt, hdlr);
3926 }
3927 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
3928 (reader->ctxt->input->filename == NULL))
3929 reader->ctxt->input->filename = (char *)
3930 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003931
3932 reader->doc = NULL;
3933
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003934 return (0);
3935}
3936
3937/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003938 * xmlReaderWalker:
3939 * @doc: a preparsed document
3940 *
3941 * Create an xmltextReader for a preparsed document.
3942 *
3943 * Returns the new reader or NULL in case of error.
3944 */
3945xmlTextReaderPtr
3946xmlReaderWalker(xmlDocPtr doc)
3947{
3948 xmlTextReaderPtr ret;
3949
3950 if (doc == NULL)
3951 return(NULL);
3952
3953 ret = xmlMalloc(sizeof(xmlTextReader));
3954 if (ret == NULL) {
3955 xmlGenericError(xmlGenericErrorContext,
3956 "xmlNewTextReader : malloc failed\n");
3957 return(NULL);
3958 }
3959 memset(ret, 0, sizeof(xmlTextReader));
3960 ret->entNr = 0;
3961 ret->input = NULL;
3962 ret->mode = XML_TEXTREADER_MODE_INITIAL;
3963 ret->node = NULL;
3964 ret->curnode = NULL;
3965 ret->base = 0;
3966 ret->cur = 0;
3967 ret->allocs = XML_TEXTREADER_CTXT;
3968 ret->doc = doc;
3969 ret->state = XML_TEXTREADER_START;
3970 ret->dict = xmlDictCreate();
3971 return(ret);
3972}
3973
3974/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003975 * xmlReaderForDoc:
3976 * @cur: a pointer to a zero terminated string
3977 * @URL: the base URL to use for the document
3978 * @encoding: the document encoding, or NULL
3979 * @options: a combination of xmlParserOption(s)
3980 *
3981 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003982 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00003983 *
3984 * Returns the new reader or NULL in case of error.
3985 */
3986xmlTextReaderPtr
3987xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
3988 int options)
3989{
3990 int len;
3991
3992 if (cur == NULL)
3993 return (NULL);
3994 len = xmlStrlen(cur);
3995
3996 return (xmlReaderForMemory
3997 ((const char *) cur, len, URL, encoding, options));
3998}
3999
4000/**
4001 * xmlReaderForFile:
4002 * @filename: a file or URL
4003 * @encoding: the document encoding, or NULL
4004 * @options: a combination of xmlParserOption(s)
4005 *
4006 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004007 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004008 *
4009 * Returns the new reader or NULL in case of error.
4010 */
4011xmlTextReaderPtr
4012xmlReaderForFile(const char *filename, const char *encoding, int options)
4013{
4014 xmlTextReaderPtr reader;
4015
4016 reader = xmlNewTextReaderFilename(filename);
4017 if (reader == NULL)
4018 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004019 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004020 return (reader);
4021}
4022
4023/**
4024 * xmlReaderForMemory:
4025 * @buffer: a pointer to a char array
4026 * @size: the size of the array
4027 * @URL: the base URL to use for the document
4028 * @encoding: the document encoding, or NULL
4029 * @options: a combination of xmlParserOption(s)
4030 *
4031 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004032 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004033 *
4034 * Returns the new reader or NULL in case of error.
4035 */
4036xmlTextReaderPtr
4037xmlReaderForMemory(const char *buffer, int size, const char *URL,
4038 const char *encoding, int options)
4039{
4040 xmlTextReaderPtr reader;
4041 xmlParserInputBufferPtr buf;
4042
4043 buf =
4044 xmlParserInputBufferCreateMem(buffer, size,
4045 XML_CHAR_ENCODING_NONE);
4046 if (buf == NULL) {
4047 return (NULL);
4048 }
4049 reader = xmlNewTextReader(buf, URL);
4050 if (reader == NULL) {
4051 xmlFreeParserInputBuffer(buf);
4052 return (NULL);
4053 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004054 reader->allocs |= XML_TEXTREADER_INPUT;
4055 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004056 return (reader);
4057}
4058
4059/**
4060 * xmlReaderForFd:
4061 * @fd: an open file descriptor
4062 * @URL: the base URL to use for the document
4063 * @encoding: the document encoding, or NULL
4064 * @options: a combination of xmlParserOption(s)
4065 *
4066 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004067 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004068 *
4069 * Returns the new reader or NULL in case of error.
4070 */
4071xmlTextReaderPtr
4072xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
4073{
4074 xmlTextReaderPtr reader;
4075 xmlParserInputBufferPtr input;
4076
4077 if (fd < 0)
4078 return (NULL);
4079
4080 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4081 if (input == NULL)
4082 return (NULL);
4083 reader = xmlNewTextReader(input, URL);
4084 if (reader == NULL) {
4085 xmlFreeParserInputBuffer(input);
4086 return (NULL);
4087 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004088 reader->allocs |= XML_TEXTREADER_INPUT;
4089 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004090 return (reader);
4091}
4092
4093/**
4094 * xmlReaderForIO:
4095 * @ioread: an I/O read function
4096 * @ioclose: an I/O close function
4097 * @ioctx: an I/O handler
4098 * @URL: the base URL to use for the document
4099 * @encoding: the document encoding, or NULL
4100 * @options: a combination of xmlParserOption(s)
4101 *
4102 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004103 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004104 *
4105 * Returns the new reader or NULL in case of error.
4106 */
4107xmlTextReaderPtr
4108xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
4109 void *ioctx, const char *URL, const char *encoding,
4110 int options)
4111{
4112 xmlTextReaderPtr reader;
4113 xmlParserInputBufferPtr input;
4114
4115 if (ioread == NULL)
4116 return (NULL);
4117
4118 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4119 XML_CHAR_ENCODING_NONE);
4120 if (input == NULL)
4121 return (NULL);
4122 reader = xmlNewTextReader(input, URL);
4123 if (reader == NULL) {
4124 xmlFreeParserInputBuffer(input);
4125 return (NULL);
4126 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004127 reader->allocs |= XML_TEXTREADER_INPUT;
4128 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004129 return (reader);
4130}
4131
4132/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004133 * xmlReaderNewWalker:
4134 * @reader: an XML reader
4135 * @doc: a preparsed document
4136 *
4137 * Setup an xmltextReader to parse a preparsed XML document.
4138 * This reuses the existing @reader xmlTextReader.
4139 *
4140 * Returns 0 in case of success and -1 in case of error
4141 */
4142int
4143xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
4144{
4145 if (doc == NULL)
4146 return (-1);
4147 if (reader == NULL)
4148 return (-1);
4149
4150 if (reader->ctxt != NULL) {
4151 xmlCtxtReset(reader->ctxt);
4152 }
4153
4154 reader->entNr = 0;
4155 reader->input = NULL;
4156 reader->mode = XML_TEXTREADER_MODE_INITIAL;
4157 reader->node = NULL;
4158 reader->curnode = NULL;
4159 reader->base = 0;
4160 reader->cur = 0;
4161 reader->allocs = XML_TEXTREADER_CTXT;
4162 reader->doc = doc;
4163 reader->state = XML_TEXTREADER_START;
4164 if (reader->dict == NULL) {
4165 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
4166 reader->dict = reader->ctxt->dict;
4167 else
4168 reader->dict = xmlDictCreate();
4169 }
4170 return(0);
4171}
4172
4173/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004174 * xmlReaderNewDoc:
4175 * @reader: an XML reader
4176 * @cur: a pointer to a zero terminated string
4177 * @URL: the base URL to use for the document
4178 * @encoding: the document encoding, or NULL
4179 * @options: a combination of xmlParserOption(s)
4180 *
4181 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004182 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004183 * This reuses the existing @reader xmlTextReader.
4184 *
4185 * Returns 0 in case of success and -1 in case of error
4186 */
4187int
4188xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
4189 const char *URL, const char *encoding, int options)
4190{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004191
4192 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004193
4194 if (cur == NULL)
4195 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004196 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004197 return (-1);
4198
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004199 len = xmlStrlen(cur);
4200 return (xmlReaderNewMemory(reader, (const char *)cur, len,
4201 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004202}
4203
4204/**
4205 * xmlReaderNewFile:
4206 * @reader: an XML reader
4207 * @filename: a file or URL
4208 * @encoding: the document encoding, or NULL
4209 * @options: a combination of xmlParserOption(s)
4210 *
4211 * parse an XML file from the filesystem or the network.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004212 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004213 * This reuses the existing @reader xmlTextReader.
4214 *
4215 * Returns 0 in case of success and -1 in case of error
4216 */
4217int
4218xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
4219 const char *encoding, int options)
4220{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004221 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004222
4223 if (filename == NULL)
4224 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004225 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004226 return (-1);
4227
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004228 input =
4229 xmlParserInputBufferCreateFilename(filename,
4230 XML_CHAR_ENCODING_NONE);
4231 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004232 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004233 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004234}
4235
4236/**
4237 * xmlReaderNewMemory:
4238 * @reader: an XML reader
4239 * @buffer: a pointer to a char array
4240 * @size: the size of the array
4241 * @URL: the base URL to use for the document
4242 * @encoding: the document encoding, or NULL
4243 * @options: a combination of xmlParserOption(s)
4244 *
4245 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004246 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004247 * This reuses the existing @reader xmlTextReader.
4248 *
4249 * Returns 0 in case of success and -1 in case of error
4250 */
4251int
4252xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
4253 const char *URL, const char *encoding, int options)
4254{
4255 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004256
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004257 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004258 return (-1);
4259 if (buffer == NULL)
4260 return (-1);
4261
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004262 input = xmlParserInputBufferCreateMem(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004263 XML_CHAR_ENCODING_NONE);
4264 if (input == NULL) {
4265 return (-1);
4266 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004267 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004268}
4269
4270/**
4271 * xmlReaderNewFd:
4272 * @reader: an XML reader
4273 * @fd: an open file descriptor
4274 * @URL: the base URL to use for the document
4275 * @encoding: the document encoding, or NULL
4276 * @options: a combination of xmlParserOption(s)
4277 *
4278 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004279 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004280 * This reuses the existing @reader xmlTextReader.
4281 *
4282 * Returns 0 in case of success and -1 in case of error
4283 */
4284int
4285xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
4286 const char *URL, const char *encoding, int options)
4287{
4288 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004289
4290 if (fd < 0)
4291 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004292 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004293 return (-1);
4294
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004295 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
4296 if (input == NULL)
4297 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004298 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004299}
4300
4301/**
4302 * xmlReaderNewIO:
4303 * @reader: an XML reader
4304 * @ioread: an I/O read function
4305 * @ioclose: an I/O close function
4306 * @ioctx: an I/O handler
4307 * @URL: the base URL to use for the document
4308 * @encoding: the document encoding, or NULL
4309 * @options: a combination of xmlParserOption(s)
4310 *
4311 * Setup an xmltextReader to parse an XML document from I/O functions
4312 * and source.
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004313 * The parsing flags @options are a combination of xmlParserOption(s).
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004314 * This reuses the existing @reader xmlTextReader.
4315 *
4316 * Returns 0 in case of success and -1 in case of error
4317 */
4318int
4319xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
4320 xmlInputCloseCallback ioclose, void *ioctx,
4321 const char *URL, const char *encoding, int options)
4322{
4323 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004324
4325 if (ioread == NULL)
4326 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004327 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004328 return (-1);
4329
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004330 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
4331 XML_CHAR_ENCODING_NONE);
4332 if (input == NULL)
4333 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004334 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00004335}
Daniel Veillard26f70262003-01-16 22:45:08 +00004336/************************************************************************
4337 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004338 * Utilities *
4339 * *
4340 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004341#ifdef NOT_USED_YET
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004342/**
4343 * xmlBase64Decode:
4344 * @in: the input buffer
4345 * @inlen: the size of the input (in), the size read from it (out)
4346 * @to: the output buffer
4347 * @tolen: the size of the output (in), the size written to (out)
4348 *
4349 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00004350 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004351 *
4352 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
4353 * 2 if there wasn't enough space on the output or -1 in case of error.
4354 */
4355static int
4356xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
4357 unsigned char *to, unsigned long *tolen) {
4358 unsigned long incur; /* current index in in[] */
4359 unsigned long inblk; /* last block index in in[] */
4360 unsigned long outcur; /* current index in out[] */
4361 unsigned long inmax; /* size of in[] */
4362 unsigned long outmax; /* size of out[] */
4363 unsigned char cur; /* the current value read from in[] */
Daniel Veillardc127adc2003-07-23 15:07:08 +00004364 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004365 int nbintmp; /* number of byte in intmp[] */
4366 int is_ignore; /* cur should be ignored */
4367 int is_end = 0; /* the end of the base64 was found */
4368 int retval = 1;
4369 int i;
4370
4371 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
4372 return(-1);
4373
4374 incur = 0;
4375 inblk = 0;
4376 outcur = 0;
4377 inmax = *inlen;
4378 outmax = *tolen;
4379 nbintmp = 0;
4380
4381 while (1) {
4382 if (incur >= inmax)
4383 break;
4384 cur = in[incur++];
4385 is_ignore = 0;
4386 if ((cur >= 'A') && (cur <= 'Z'))
4387 cur = cur - 'A';
4388 else if ((cur >= 'a') && (cur <= 'z'))
4389 cur = cur - 'a' + 26;
4390 else if ((cur >= '0') && (cur <= '9'))
4391 cur = cur - '0' + 52;
4392 else if (cur == '+')
4393 cur = 62;
4394 else if (cur == '/')
4395 cur = 63;
4396 else if (cur == '.')
4397 cur = 0;
4398 else if (cur == '=') /*no op , end of the base64 stream */
4399 is_end = 1;
4400 else {
4401 is_ignore = 1;
4402 if (nbintmp == 0)
4403 inblk = incur;
4404 }
4405
4406 if (!is_ignore) {
4407 int nbouttmp = 3;
4408 int is_break = 0;
4409
4410 if (is_end) {
4411 if (nbintmp == 0)
4412 break;
4413 if ((nbintmp == 1) || (nbintmp == 2))
4414 nbouttmp = 1;
4415 else
4416 nbouttmp = 2;
4417 nbintmp = 3;
4418 is_break = 1;
4419 }
4420 intmp[nbintmp++] = cur;
4421 /*
4422 * if intmp is full, push the 4byte sequence as a 3 byte
4423 * sequence out
4424 */
4425 if (nbintmp == 4) {
4426 nbintmp = 0;
4427 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
4428 outtmp[1] =
4429 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
4430 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
4431 if (outcur + 3 >= outmax) {
4432 retval = 2;
4433 break;
4434 }
4435
4436 for (i = 0; i < nbouttmp; i++)
4437 to[outcur++] = outtmp[i];
4438 inblk = incur;
4439 }
4440
4441 if (is_break) {
4442 retval = 0;
4443 break;
4444 }
4445 }
4446 }
4447
4448 *tolen = outcur;
4449 *inlen = inblk;
4450 return (retval);
4451}
4452
4453/*
4454 * Test routine for the xmlBase64Decode function
4455 */
4456#if 0
4457int main(int argc, char **argv) {
4458 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
4459 char output[100];
4460 char output2[100];
4461 char output3[100];
4462 unsigned long inlen = strlen(input);
4463 unsigned long outlen = 100;
4464 int ret;
4465 unsigned long cons, tmp, tmp2, prod;
4466
4467 /*
4468 * Direct
4469 */
4470 ret = xmlBase64Decode(input, &inlen, output, &outlen);
4471
4472 output[outlen] = 0;
4473 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
4474
4475 /*
4476 * output chunking
4477 */
4478 cons = 0;
4479 prod = 0;
4480 while (cons < inlen) {
4481 tmp = 5;
4482 tmp2 = inlen - cons;
4483
4484 printf("%ld %ld\n", cons, prod);
4485 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
4486 cons += tmp2;
4487 prod += tmp;
4488 printf("%ld %ld\n", cons, prod);
4489 }
4490 output2[outlen] = 0;
4491 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
4492
4493 /*
4494 * input chunking
4495 */
4496 cons = 0;
4497 prod = 0;
4498 while (cons < inlen) {
4499 tmp = 100 - prod;
4500 tmp2 = inlen - cons;
4501 if (tmp2 > 5)
4502 tmp2 = 5;
4503
4504 printf("%ld %ld\n", cons, prod);
4505 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
4506 cons += tmp2;
4507 prod += tmp;
4508 printf("%ld %ld\n", cons, prod);
4509 }
4510 output3[outlen] = 0;
4511 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
4512 return(0);
4513
4514}
4515#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00004516#endif /* NOT_USED_YET */
Daniel Veillard81273902003-09-30 00:43:48 +00004517#endif /* LIBXML_READER_ENABLED */