blob: f9c7fa172734d1b1fb23ca06674080607d414313 [file] [log] [blame]
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001/*
2 * xmlreader.c: implements the xmlTextReader streaming node API
3 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004 * NOTE:
Daniel Veillard67df8092002-12-16 22:04:11 +00005 * 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 Veillard067bae52003-01-05 01:27:54 +000015 * - XML Schemas validation
Daniel Veillard7704fb12003-01-03 16:19:51 +000016 */
Daniel Veillarde1ca5032002-12-09 14:13:43 +000017#define IN_LIBXML
18#include "libxml.h"
19
Daniel Veillard81273902003-09-30 00:43:48 +000020#ifdef LIBXML_READER_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +000021#include <string.h> /* for memset() only ! */
Daniel Veillard26f70262003-01-16 22:45:08 +000022#include <stdarg.h>
Daniel Veillarde1ca5032002-12-09 14:13:43 +000023
24#ifdef HAVE_CTYPE_H
25#include <ctype.h>
26#endif
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#include <libxml/xmlmemory.h>
32#include <libxml/xmlIO.h>
33#include <libxml/xmlreader.h>
Daniel Veillardfc8dc352003-10-18 09:07:46 +000034#include <libxml/parserInternals.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000035#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +000036#include <libxml/relaxng.h>
Daniel Veillardf10ae122005-07-10 19:03:16 +000037#include <libxml/xmlschemas.h>
38#endif
Daniel Veillard198c1bf2003-10-20 17:07:41 +000039#include <libxml/uri.h>
Daniel Veillard7899c5c2003-11-03 12:31:38 +000040#ifdef LIBXML_XINCLUDE_ENABLED
41#include <libxml/xinclude.h>
42#endif
Daniel Veillard1e906612003-12-05 14:57:46 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +000046
Daniel Veillard8aebce32012-07-16 14:42:31 +080047#include "buf.h"
48
Daniel Veillard7e65fad2008-09-25 14:55:21 +000049#define MAX_ERR_MSG_SIZE 64000
50
51/*
52 * The following VA_COPY was coded following an example in
53 * the Samba project. It may not be sufficient for some
54 * esoteric implementations of va_list (i.e. it may need
55 * something involving a memcpy) but (hopefully) will be
56 * sufficient for libxml2.
57 */
58#ifndef VA_COPY
59 #ifdef HAVE_VA_COPY
60 #define VA_COPY(dest, src) va_copy(dest, src)
61 #else
62 #ifdef HAVE___VA_COPY
63 #define VA_COPY(dest,src) __va_copy(dest, src)
64 #else
65 #define VA_COPY(dest,src) (dest) = (src)
66 #endif
67 #endif
68#endif
69
Daniel Veillarde1ca5032002-12-09 14:13:43 +000070/* #define DEBUG_CALLBACKS */
71/* #define DEBUG_READER */
72
73/**
74 * TODO:
75 *
76 * macro to flag unimplemented blocks
77 */
Daniel Veillardaacc2a22009-08-11 18:31:42 +020078#define TODO \
Daniel Veillarde1ca5032002-12-09 14:13:43 +000079 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
83#ifdef DEBUG_READER
84#define DUMP_READER xmlTextReaderDebug(reader);
85#else
86#define DUMP_READER
87#endif
88
Daniel Veillarda880b122003-04-21 21:36:41 +000089#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000090/************************************************************************
91 * *
92 * The parser: maps the Text Reader API on top of the existing *
93 * parsing routines building a tree *
94 * *
95 ************************************************************************/
96
97#define XML_TEXTREADER_INPUT 1
98#define XML_TEXTREADER_CTXT 2
99
100typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000101 XML_TEXTREADER_NONE = -1,
102 XML_TEXTREADER_START= 0,
103 XML_TEXTREADER_ELEMENT= 1,
104 XML_TEXTREADER_END= 2,
105 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +0000106 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000107 XML_TEXTREADER_DONE= 5,
108 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000109} xmlTextReaderState;
110
Daniel Veillardf4e55762003-04-15 23:32:22 +0000111typedef enum {
112 XML_TEXTREADER_NOT_VALIDATE = 0,
113 XML_TEXTREADER_VALIDATE_DTD = 1,
Daniel Veillardf10ae122005-07-10 19:03:16 +0000114 XML_TEXTREADER_VALIDATE_RNG = 2,
115 XML_TEXTREADER_VALIDATE_XSD = 4
Daniel Veillardf4e55762003-04-15 23:32:22 +0000116} xmlTextReaderValidate;
117
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000118struct _xmlTextReader {
119 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000120 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000121 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000122 int allocs; /* what structure were deallocated */
123 xmlTextReaderState state;
124 xmlParserCtxtPtr ctxt; /* the parser context */
125 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
126 xmlParserInputBufferPtr input; /* the input */
127 startElementSAXFunc startElement;/* initial SAX callbacks */
128 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000129 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000130 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000131 charactersSAXFunc characters;
132 cdataBlockSAXFunc cdataBlock;
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200133 unsigned int base; /* base of the segment in the input */
134 unsigned int cur; /* current position in the input */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000135 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000136 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000137 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000138 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000139 int preserve;/* preserve the resulting document */
Daniel Veillard8aebce32012-07-16 14:42:31 +0800140 xmlBufPtr buffer; /* used to return const xmlChar * */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000141 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000142
143 /* entity stack when traversing entities content */
144 xmlNodePtr ent; /* Current Entity Ref Node */
145 int entNr; /* Depth of the entities stack */
146 int entMax; /* Max depth of the entities stack */
147 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000148
149 /* error handling */
150 xmlTextReaderErrorFunc errorFunc; /* callback function */
151 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000152
153#ifdef LIBXML_SCHEMAS_ENABLED
154 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000155 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
156 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
Noam Postavsky15794992012-03-19 16:08:16 +0800157 int rngPreserveCtxt; /* 1 if the context was provided by the user */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000158 int rngValidErrors;/* The number of errors detected */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000159 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000160 /* Handling of Schemas validation */
161 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
162 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000163 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
164 int xsdValidErrors;/* The number of errors detected */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000165 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000166#endif
167#ifdef LIBXML_XINCLUDE_ENABLED
168 /* Handling of XInclude processing */
169 int xinclude; /* is xinclude asked for */
170 const xmlChar * xinclude_name; /* the xinclude name from dict */
171 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
172 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000173#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000174#ifdef LIBXML_PATTERN_ENABLED
175 int patternNr; /* number of preserve patterns */
176 int patternMax; /* max preserve patterns */
177 xmlPatternPtr *patternTab; /* array of preserve patterns */
178#endif
179 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000180 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000181 /* Structured error handling */
182 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000183};
184
Daniel Veillarde8039df2003-10-27 11:25:13 +0000185#define NODE_IS_EMPTY 0x1
186#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000187#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000188
Daniel Veillarde72c5082003-09-19 12:44:05 +0000189/**
190 * CONSTSTR:
191 *
192 * Macro used to return an interned string
193 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000194#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
195#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
196
197static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
198static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000199
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000200/************************************************************************
201 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000202 * Our own version of the freeing routines as we recycle nodes *
203 * *
204 ************************************************************************/
205/**
206 * DICT_FREE:
207 * @str: a string
208 *
209 * Free a string if it is not owned by the "dict" dictionnary in the
210 * current scope
211 */
212#define DICT_FREE(str) \
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200213 if ((str) && ((!dict) || \
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000214 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
215 xmlFree((char *)(str));
216
217static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
218static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
219
220/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000221 * xmlFreeID:
222 * @not: A id
223 *
224 * Deallocate the memory used by an id definition
225 */
226static void
227xmlFreeID(xmlIDPtr id) {
228 xmlDictPtr dict = NULL;
229
230 if (id == NULL) return;
231
232 if (id->doc != NULL)
233 dict = id->doc->dict;
234
235 if (id->value != NULL)
236 DICT_FREE(id->value)
237 xmlFree(id);
238}
239
240/**
241 * xmlTextReaderRemoveID:
242 * @doc: the document
243 * @attr: the attribute
244 *
245 * Remove the given attribute from the ID table maintained internally.
246 *
247 * Returns -1 if the lookup failed and 0 otherwise
248 */
249static int
250xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
251 xmlIDTablePtr table;
252 xmlIDPtr id;
253 xmlChar *ID;
254
255 if (doc == NULL) return(-1);
256 if (attr == NULL) return(-1);
257 table = (xmlIDTablePtr) doc->ids;
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200258 if (table == NULL)
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000259 return(-1);
260
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000261 ID = xmlNodeListGetString(doc, attr->children, 1);
262 if (ID == NULL)
263 return(-1);
264 id = xmlHashLookup(table, ID);
265 xmlFree(ID);
266 if (id == NULL || id->attr != attr) {
267 return(-1);
268 }
269 id->name = attr->name;
270 id->attr = NULL;
271 return(0);
272}
273
274/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000275 * xmlTextReaderFreeProp:
276 * @reader: the xmlTextReaderPtr used
277 * @cur: the node
278 *
279 * Free a node.
280 */
281static void
282xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
283 xmlDictPtr dict;
284
285 dict = reader->ctxt->dict;
286 if (cur == NULL) return;
287
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000288 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
289 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
290
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000291 /* Check for ID removal -> leading to invalid references ! */
292 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
293 ((cur->parent->doc->intSubset != NULL) ||
294 (cur->parent->doc->extSubset != NULL))) {
295 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000296 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000297 }
298 if (cur->children != NULL)
299 xmlTextReaderFreeNodeList(reader, cur->children);
300
301 DICT_FREE(cur->name);
302 if ((reader != NULL) && (reader->ctxt != NULL) &&
303 (reader->ctxt->freeAttrsNr < 100)) {
304 cur->next = reader->ctxt->freeAttrs;
305 reader->ctxt->freeAttrs = cur;
306 reader->ctxt->freeAttrsNr++;
307 } else {
308 xmlFree(cur);
309 }
310}
311
312/**
313 * xmlTextReaderFreePropList:
314 * @reader: the xmlTextReaderPtr used
315 * @cur: the first property in the list
316 *
317 * Free a property and all its siblings, all the children are freed too.
318 */
319static void
320xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
321 xmlAttrPtr next;
322 if (cur == NULL) return;
323 while (cur != NULL) {
324 next = cur->next;
325 xmlTextReaderFreeProp(reader, cur);
326 cur = next;
327 }
328}
329
330/**
331 * xmlTextReaderFreeNodeList:
332 * @reader: the xmlTextReaderPtr used
333 * @cur: the first node in the list
334 *
335 * Free a node and all its siblings, this is a recursive behaviour, all
336 * the children are freed too.
337 */
338static void
339xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
340 xmlNodePtr next;
341 xmlDictPtr dict;
342
343 dict = reader->ctxt->dict;
344 if (cur == NULL) return;
345 if (cur->type == XML_NAMESPACE_DECL) {
346 xmlFreeNsList((xmlNsPtr) cur);
347 return;
348 }
349 if ((cur->type == XML_DOCUMENT_NODE) ||
350 (cur->type == XML_HTML_DOCUMENT_NODE)) {
351 xmlFreeDoc((xmlDocPtr) cur);
352 return;
353 }
354 while (cur != NULL) {
355 next = cur->next;
356 /* unroll to speed up freeing the document */
357 if (cur->type != XML_DTD_NODE) {
358
359 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000360 (cur->type != XML_ENTITY_REF_NODE)) {
361 if (cur->children->parent == cur)
362 xmlTextReaderFreeNodeList(reader, cur->children);
363 cur->children = NULL;
364 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000365
366 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
367 xmlDeregisterNodeDefaultValue(cur);
368
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000369 if (((cur->type == XML_ELEMENT_NODE) ||
370 (cur->type == XML_XINCLUDE_START) ||
371 (cur->type == XML_XINCLUDE_END)) &&
372 (cur->properties != NULL))
373 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000374 if ((cur->content != (xmlChar *) &(cur->properties)) &&
375 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000376 (cur->type != XML_XINCLUDE_START) &&
377 (cur->type != XML_XINCLUDE_END) &&
378 (cur->type != XML_ENTITY_REF_NODE)) {
379 DICT_FREE(cur->content);
380 }
381 if (((cur->type == XML_ELEMENT_NODE) ||
382 (cur->type == XML_XINCLUDE_START) ||
383 (cur->type == XML_XINCLUDE_END)) &&
384 (cur->nsDef != NULL))
385 xmlFreeNsList(cur->nsDef);
386
387 /*
388 * we don't free element names here they are interned now
389 */
390 if ((cur->type != XML_TEXT_NODE) &&
391 (cur->type != XML_COMMENT_NODE))
392 DICT_FREE(cur->name);
393 if (((cur->type == XML_ELEMENT_NODE) ||
394 (cur->type == XML_TEXT_NODE)) &&
395 (reader != NULL) && (reader->ctxt != NULL) &&
396 (reader->ctxt->freeElemsNr < 100)) {
397 cur->next = reader->ctxt->freeElems;
398 reader->ctxt->freeElems = cur;
399 reader->ctxt->freeElemsNr++;
400 } else {
401 xmlFree(cur);
402 }
403 }
404 cur = next;
405 }
406}
407
408/**
409 * xmlTextReaderFreeNode:
410 * @reader: the xmlTextReaderPtr used
411 * @cur: the node
412 *
413 * Free a node, this is a recursive behaviour, all the children are freed too.
414 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
415 */
416static void
417xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
418 xmlDictPtr dict;
419
420 dict = reader->ctxt->dict;
421 if (cur->type == XML_DTD_NODE) {
422 xmlFreeDtd((xmlDtdPtr) cur);
423 return;
424 }
425 if (cur->type == XML_NAMESPACE_DECL) {
426 xmlFreeNs((xmlNsPtr) cur);
427 return;
428 }
429 if (cur->type == XML_ATTRIBUTE_NODE) {
430 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
431 return;
432 }
433
434 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000435 (cur->type != XML_ENTITY_REF_NODE)) {
436 if (cur->children->parent == cur)
437 xmlTextReaderFreeNodeList(reader, cur->children);
438 cur->children = NULL;
439 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000440
441 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
442 xmlDeregisterNodeDefaultValue(cur);
443
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000444 if (((cur->type == XML_ELEMENT_NODE) ||
445 (cur->type == XML_XINCLUDE_START) ||
446 (cur->type == XML_XINCLUDE_END)) &&
447 (cur->properties != NULL))
448 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000449 if ((cur->content != (xmlChar *) &(cur->properties)) &&
450 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000451 (cur->type != XML_XINCLUDE_START) &&
452 (cur->type != XML_XINCLUDE_END) &&
453 (cur->type != XML_ENTITY_REF_NODE)) {
454 DICT_FREE(cur->content);
455 }
456 if (((cur->type == XML_ELEMENT_NODE) ||
457 (cur->type == XML_XINCLUDE_START) ||
458 (cur->type == XML_XINCLUDE_END)) &&
459 (cur->nsDef != NULL))
460 xmlFreeNsList(cur->nsDef);
461
462 /*
463 * we don't free names here they are interned now
464 */
465 if ((cur->type != XML_TEXT_NODE) &&
466 (cur->type != XML_COMMENT_NODE))
467 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000468
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000469 if (((cur->type == XML_ELEMENT_NODE) ||
470 (cur->type == XML_TEXT_NODE)) &&
471 (reader != NULL) && (reader->ctxt != NULL) &&
472 (reader->ctxt->freeElemsNr < 100)) {
473 cur->next = reader->ctxt->freeElems;
474 reader->ctxt->freeElems = cur;
475 reader->ctxt->freeElemsNr++;
476 } else {
477 xmlFree(cur);
478 }
479}
480
481/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000482 * xmlTextReaderFreeIDTable:
483 * @table: An id table
484 *
485 * Deallocate the memory used by an ID hash table.
486 */
William M. Brack60f394e2003-11-16 06:25:42 +0000487static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000488xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
489 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
490}
491
492/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000493 * xmlTextReaderFreeDoc:
494 * @reader: the xmlTextReaderPtr used
495 * @cur: pointer to the document
496 *
497 * Free up all the structures used by a document, tree included.
498 */
499static void
500xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
501 xmlDtdPtr extSubset, intSubset;
502
503 if (cur == NULL) return;
504
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000505 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
506 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
507
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000508 /*
509 * Do this before freeing the children list to avoid ID lookups
510 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000511 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000512 cur->ids = NULL;
513 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
514 cur->refs = NULL;
515 extSubset = cur->extSubset;
516 intSubset = cur->intSubset;
517 if (intSubset == extSubset)
518 extSubset = NULL;
519 if (extSubset != NULL) {
520 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
521 cur->extSubset = NULL;
522 xmlFreeDtd(extSubset);
523 }
524 if (intSubset != NULL) {
525 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
526 cur->intSubset = NULL;
527 xmlFreeDtd(intSubset);
528 }
529
530 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
531
532 if (cur->version != NULL) xmlFree((char *) cur->version);
533 if (cur->name != NULL) xmlFree((char *) cur->name);
534 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
535 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
536 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000537 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000538
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000539 xmlFree(cur);
540}
541
542/************************************************************************
543 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000544 * The reader core parser *
545 * *
546 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000547#ifdef DEBUG_READER
548static void
549xmlTextReaderDebug(xmlTextReaderPtr reader) {
550 if ((reader == NULL) || (reader->ctxt == NULL)) {
551 fprintf(stderr, "xmlTextReader NULL\n");
552 return;
553 }
554 fprintf(stderr, "xmlTextReader: state %d depth %d ",
555 reader->state, reader->depth);
556 if (reader->node == NULL) {
557 fprintf(stderr, "node = NULL\n");
558 } else {
559 fprintf(stderr, "node %s\n", reader->node->name);
560 }
561 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
562 reader->base, reader->cur, reader->ctxt->nodeNr);
563 if (reader->input->buffer == NULL) {
564 fprintf(stderr, "buffer is NULL\n");
565 } else {
566#ifdef LIBXML_DEBUG_ENABLED
567 xmlDebugDumpString(stderr,
568 &reader->input->buffer->content[reader->cur]);
569#endif
570 fprintf(stderr, "\n");
571 }
572}
573#endif
574
575/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000576 * xmlTextReaderEntPush:
577 * @reader: the xmlTextReaderPtr used
578 * @value: the entity reference node
579 *
580 * Pushes a new entity reference node on top of the entities stack
581 *
582 * Returns 0 in case of error, the index in the stack otherwise
583 */
584static int
585xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
586{
587 if (reader->entMax <= 0) {
588 reader->entMax = 10;
589 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
590 sizeof(reader->entTab[0]));
591 if (reader->entTab == NULL) {
592 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
593 return (0);
594 }
595 }
596 if (reader->entNr >= reader->entMax) {
597 reader->entMax *= 2;
598 reader->entTab =
599 (xmlNodePtr *) xmlRealloc(reader->entTab,
600 reader->entMax *
601 sizeof(reader->entTab[0]));
602 if (reader->entTab == NULL) {
603 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
604 return (0);
605 }
606 }
607 reader->entTab[reader->entNr] = value;
608 reader->ent = value;
609 return (reader->entNr++);
610}
611
612/**
613 * xmlTextReaderEntPop:
614 * @reader: the xmlTextReaderPtr used
615 *
616 * Pops the top element entity from the entities stack
617 *
618 * Returns the entity just removed
619 */
620static xmlNodePtr
621xmlTextReaderEntPop(xmlTextReaderPtr reader)
622{
623 xmlNodePtr ret;
624
625 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000626 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000627 reader->entNr--;
628 if (reader->entNr > 0)
629 reader->ent = reader->entTab[reader->entNr - 1];
630 else
631 reader->ent = NULL;
632 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000633 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000634 return (ret);
635}
636
637/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000638 * xmlTextReaderStartElement:
639 * @ctx: the user data (XML parser context)
640 * @fullname: The element name, including namespace prefix
641 * @atts: An array of name/value attributes pairs, NULL terminated
642 *
643 * called when an opening tag has been processed.
644 */
645static void
646xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
647 const xmlChar **atts) {
648 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
649 xmlTextReaderPtr reader = ctxt->_private;
650
651#ifdef DEBUG_CALLBACKS
652 printf("xmlTextReaderStartElement(%s)\n", fullname);
653#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000654 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000655 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000656 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
657 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
658 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000659 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000660 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000661 if (reader != NULL)
662 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000663}
664
665/**
666 * xmlTextReaderEndElement:
667 * @ctx: the user data (XML parser context)
668 * @fullname: The element name, including namespace prefix
669 *
670 * called when an ending tag has been processed.
671 */
672static void
673xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
674 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
675 xmlTextReaderPtr reader = ctxt->_private;
676
677#ifdef DEBUG_CALLBACKS
678 printf("xmlTextReaderEndElement(%s)\n", fullname);
679#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000680 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000681 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000682 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000683}
684
685/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000686 * xmlTextReaderStartElementNs:
687 * @ctx: the user data (XML parser context)
688 * @localname: the local name of the element
689 * @prefix: the element namespace prefix if available
690 * @URI: the element namespace name if available
691 * @nb_namespaces: number of namespace definitions on that node
692 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
693 * @nb_attributes: the number of attributes on that node
694 * nb_defaulted: the number of defaulted attributes.
695 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
696 * attribute values.
697 *
698 * called when an opening tag has been processed.
699 */
700static void
701xmlTextReaderStartElementNs(void *ctx,
702 const xmlChar *localname,
703 const xmlChar *prefix,
704 const xmlChar *URI,
705 int nb_namespaces,
706 const xmlChar **namespaces,
707 int nb_attributes,
708 int nb_defaulted,
709 const xmlChar **attributes)
710{
711 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
712 xmlTextReaderPtr reader = ctxt->_private;
713
714#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000715 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000716#endif
717 if ((reader != NULL) && (reader->startElementNs != NULL)) {
718 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
719 namespaces, nb_attributes, nb_defaulted,
720 attributes);
721 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
722 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
723 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000724 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000725 }
726 if (reader != NULL)
727 reader->state = XML_TEXTREADER_ELEMENT;
728}
729
730/**
731 * xmlTextReaderEndElementNs:
732 * @ctx: the user data (XML parser context)
733 * @localname: the local name of the element
734 * @prefix: the element namespace prefix if available
735 * @URI: the element namespace name if available
736 *
737 * called when an ending tag has been processed.
738 */
739static void
740xmlTextReaderEndElementNs(void *ctx,
741 const xmlChar * localname,
742 const xmlChar * prefix,
743 const xmlChar * URI)
744{
745 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
746 xmlTextReaderPtr reader = ctxt->_private;
747
748#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000749 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000750#endif
751 if ((reader != NULL) && (reader->endElementNs != NULL)) {
752 reader->endElementNs(ctx, localname, prefix, URI);
753 }
754}
755
756
757/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000758 * xmlTextReaderCharacters:
759 * @ctx: the user data (XML parser context)
760 * @ch: a xmlChar string
761 * @len: the number of xmlChar
762 *
763 * receiving some chars from the parser.
764 */
765static void
766xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
767{
768 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
769 xmlTextReaderPtr reader = ctxt->_private;
770
771#ifdef DEBUG_CALLBACKS
772 printf("xmlTextReaderCharacters()\n");
773#endif
774 if ((reader != NULL) && (reader->characters != NULL)) {
775 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000776 }
777}
778
779/**
780 * xmlTextReaderCDataBlock:
781 * @ctx: the user data (XML parser context)
782 * @value: The pcdata content
783 * @len: the block length
784 *
785 * called when a pcdata block has been parsed
786 */
787static void
788xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
789{
790 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
791 xmlTextReaderPtr reader = ctxt->_private;
792
793#ifdef DEBUG_CALLBACKS
794 printf("xmlTextReaderCDataBlock()\n");
795#endif
796 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
797 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000798 }
799}
800
801/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000802 * xmlTextReaderPushData:
803 * @reader: the xmlTextReaderPtr used
804 *
805 * Push data down the progressive parser until a significant callback
806 * got raised.
807 *
808 * Returns -1 in case of failure, 0 otherwise
809 */
810static int
811xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800812 xmlBufPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000813 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000814 xmlTextReaderState oldstate;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800815 int alloc;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000816
817 if ((reader->input == NULL) || (reader->input->buffer == NULL))
818 return(-1);
819
Daniel Veillardea7751d2002-12-20 00:16:24 +0000820 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000821 reader->state = XML_TEXTREADER_NONE;
822 inbuf = reader->input->buffer;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800823 alloc = xmlBufGetAllocationScheme(inbuf);
Daniel Veillarda880b122003-04-21 21:36:41 +0000824
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000825 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800826 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000827 /*
828 * Refill the buffer unless we are at the end of the stream
829 */
830 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
831 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000832 if ((val == 0) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800833 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
834 if (xmlBufUse(inbuf) == reader->cur) {
Daniel Veillard53350552003-09-18 13:35:51 +0000835 reader->mode = XML_TEXTREADER_MODE_EOF;
836 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000837 }
838 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000839 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000840 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000841 if ((oldstate != XML_TEXTREADER_START) ||
842 (reader->ctxt->myDoc != NULL))
843 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000844 } else if (val == 0) {
845 /* mark the end of the stream and process the remains */
846 reader->mode = XML_TEXTREADER_MODE_EOF;
847 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000848 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000849
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200850 } else
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000851 break;
852 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000853 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000854 * parse by block of CHUNK_SIZE bytes, various tests show that
855 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000856 */
Daniel Veillard8aebce32012-07-16 14:42:31 +0800857 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000858 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800859 (const char *) xmlBufContent(inbuf) + reader->cur,
860 CHUNK_SIZE, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000861 reader->cur += CHUNK_SIZE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800862 if (val != 0)
863 reader->ctxt->wellFormed = 0;
864 if (reader->ctxt->wellFormed == 0)
865 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000866 } else {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800867 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillarda880b122003-04-21 21:36:41 +0000868 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800869 (const char *) xmlBufContent(inbuf) + reader->cur,
870 s, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000871 reader->cur += s;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800872 if (val != 0)
873 reader->ctxt->wellFormed = 0;
Daniel Veillarda880b122003-04-21 21:36:41 +0000874 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000875 }
876 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000877
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000878 /*
879 * Discard the consumed input when needed and possible
880 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000881 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800882 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000883 if ((reader->cur >= 4096) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800884 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
885 val = xmlBufShrink(inbuf, reader->cur);
Daniel Veillard21924522004-02-19 16:37:07 +0000886 if (val >= 0) {
887 reader->cur -= val;
888 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000889 }
890 }
891 }
892
893 /*
894 * At the end of the stream signal that the work is done to the Push
895 * parser.
896 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000897 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillarda9c56772007-03-09 16:59:05 +0000898 if (reader->state != XML_TEXTREADER_DONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800899 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000900 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800901 (const char *) xmlBufContent(inbuf) + reader->cur,
902 s, 1);
903 reader->cur = xmlBufUse(inbuf);
Daniel Veillarda9c56772007-03-09 16:59:05 +0000904 reader->state = XML_TEXTREADER_DONE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800905 if (val != 0) {
906 if (reader->ctxt->wellFormed)
907 reader->ctxt->wellFormed = 0;
908 else
909 return(-1);
910 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000911 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000912 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000913 reader->state = oldstate;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800914 if (reader->ctxt->wellFormed == 0) {
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800915 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800916 return(-1);
917 }
918
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000919 return(0);
920}
921
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000922#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000923/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000924 * xmlTextReaderValidatePush:
925 * @reader: the xmlTextReaderPtr used
926 *
927 * Push the current node for validation
928 */
929static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000930xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000931 xmlNodePtr node = reader->node;
932
Daniel Veillardf54cd532004-02-25 11:52:31 +0000933#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000934 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
935 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
936 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
937 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
938 reader->ctxt->myDoc, node, node->name);
939 } else {
940 /* TODO use the BuildQName interface */
941 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000942
Daniel Veillardf4e55762003-04-15 23:32:22 +0000943 qname = xmlStrdup(node->ns->prefix);
944 qname = xmlStrcat(qname, BAD_CAST ":");
945 qname = xmlStrcat(qname, node->name);
946 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
947 reader->ctxt->myDoc, node, qname);
948 if (qname != NULL)
949 xmlFree(qname);
950 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000951 }
952#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000953#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000954 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000955 (reader->rngValidCtxt != NULL)) {
956 int ret;
957
958 if (reader->rngFullNode != NULL) return;
959 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
960 reader->ctxt->myDoc,
961 node);
962 if (ret == 0) {
963 /*
964 * this element requires a full tree
965 */
966 node = xmlTextReaderExpand(reader);
967 if (node == NULL) {
968printf("Expand failed !\n");
969 ret = -1;
970 } else {
971 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
972 reader->ctxt->myDoc,
973 node);
974 reader->rngFullNode = node;
975 }
976 }
977 if (ret != 1)
978 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000979 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000980#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000981}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000982
983/**
984 * xmlTextReaderValidateCData:
985 * @reader: the xmlTextReaderPtr used
986 * @data: pointer to the CData
987 * @len: lenght of the CData block in bytes.
988 *
989 * Push some CData for validation
990 */
991static void
992xmlTextReaderValidateCData(xmlTextReaderPtr reader,
993 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000994#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000995 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
996 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
997 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
998 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +0000999 }
1000#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001001#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001002 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001003 (reader->rngValidCtxt != NULL)) {
1004 int ret;
1005
1006 if (reader->rngFullNode != NULL) return;
1007 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1008 if (ret != 1)
1009 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +00001010 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001011#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00001012}
1013
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001014/**
1015 * xmlTextReaderValidatePop:
1016 * @reader: the xmlTextReaderPtr used
1017 *
1018 * Pop the current node from validation
1019 */
1020static void
1021xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1022 xmlNodePtr node = reader->node;
1023
Daniel Veillardf54cd532004-02-25 11:52:31 +00001024#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001025 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1026 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1027 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1028 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1029 reader->ctxt->myDoc, node, node->name);
1030 } else {
1031 /* TODO use the BuildQName interface */
1032 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001033
Daniel Veillardf4e55762003-04-15 23:32:22 +00001034 qname = xmlStrdup(node->ns->prefix);
1035 qname = xmlStrcat(qname, BAD_CAST ":");
1036 qname = xmlStrcat(qname, node->name);
1037 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1038 reader->ctxt->myDoc, node, qname);
1039 if (qname != NULL)
1040 xmlFree(qname);
1041 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001042 }
1043#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001044#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001045 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001046 (reader->rngValidCtxt != NULL)) {
1047 int ret;
1048
1049 if (reader->rngFullNode != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001050 if (node == reader->rngFullNode)
Daniel Veillardf4e55762003-04-15 23:32:22 +00001051 reader->rngFullNode = NULL;
1052 return;
1053 }
1054 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1055 reader->ctxt->myDoc,
1056 node);
1057 if (ret != 1)
1058 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001059 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001060#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001061}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001062
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001063/**
1064 * xmlTextReaderValidateEntity:
1065 * @reader: the xmlTextReaderPtr used
1066 *
1067 * Handle the validation when an entity reference is encountered and
1068 * entity substitution is not activated. As a result the parser interface
1069 * must walk through the entity and do the validation calls
1070 */
1071static void
1072xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1073 xmlNodePtr oldnode = reader->node;
1074 xmlNodePtr node = reader->node;
1075 xmlParserCtxtPtr ctxt = reader->ctxt;
1076
1077 do {
1078 if (node->type == XML_ENTITY_REF_NODE) {
1079 /*
1080 * Case where the underlying tree is not availble, lookup the entity
1081 * and walk it.
1082 */
1083 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1084 (ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001085 node->children = (xmlNodePtr)
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001086 ctxt->sax->getEntity(ctxt, node->name);
1087 }
1088
1089 if ((node->children != NULL) &&
1090 (node->children->type == XML_ENTITY_DECL) &&
1091 (node->children->children != NULL)) {
1092 xmlTextReaderEntPush(reader, node);
1093 node = node->children->children;
1094 continue;
1095 } else {
1096 /*
1097 * The error has probably be raised already.
1098 */
1099 if (node == oldnode)
1100 break;
1101 node = node->next;
1102 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001103#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001104 } else if (node->type == XML_ELEMENT_NODE) {
1105 reader->node = node;
1106 xmlTextReaderValidatePush(reader);
1107 } else if ((node->type == XML_TEXT_NODE) ||
1108 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001109 xmlTextReaderValidateCData(reader, node->content,
1110 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001111#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001112 }
1113
1114 /*
1115 * go to next node
1116 */
1117 if (node->children != NULL) {
1118 node = node->children;
1119 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001120 } else if (node->type == XML_ELEMENT_NODE) {
1121 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001122 }
1123 if (node->next != NULL) {
1124 node = node->next;
1125 continue;
1126 }
1127 do {
1128 node = node->parent;
1129 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001130 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001131 if (reader->entNr == 0) {
1132 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001133 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001134 xmlUnlinkNode(tmp);
1135 xmlTextReaderFreeNode(reader, tmp);
1136 } else
1137 break;
1138 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001139 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001140 reader->node = node;
1141 xmlTextReaderValidatePop(reader);
1142 }
1143 if ((node->type == XML_ENTITY_DECL) &&
1144 (reader->ent != NULL) && (reader->ent->children == node)) {
1145 node = xmlTextReaderEntPop(reader);
1146 }
1147 if (node == oldnode)
1148 break;
1149 if (node->next != NULL) {
1150 node = node->next;
1151 break;
1152 }
1153 } while ((node != NULL) && (node != oldnode));
1154 } while ((node != NULL) && (node != oldnode));
1155 reader->node = oldnode;
1156}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001157#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001158
1159
1160/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001161 * xmlTextReaderGetSuccessor:
1162 * @cur: the current node
1163 *
1164 * Get the successor of a node if available.
1165 *
1166 * Returns the successor node or NULL
1167 */
1168static xmlNodePtr
1169xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1170 if (cur == NULL) return(NULL) ; /* ERROR */
1171 if (cur->next != NULL) return(cur->next) ;
1172 do {
1173 cur = cur->parent;
Daniel Veillard11ce4002006-03-10 00:36:23 +00001174 if (cur == NULL) break;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001175 if (cur->next != NULL) return(cur->next);
1176 } while (cur != NULL);
1177 return(cur);
1178}
1179
1180/**
1181 * xmlTextReaderDoExpand:
1182 * @reader: the xmlTextReaderPtr used
1183 *
1184 * Makes sure that the current node is fully read as well as all its
1185 * descendant. It means the full DOM subtree must be available at the
1186 * end of the call.
1187 *
1188 * Returns 1 if the node was expanded successfully, 0 if there is no more
1189 * nodes to read, or -1 in case of error
1190 */
1191static int
1192xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1193 int val;
1194
1195 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1196 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001197 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001198 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1199
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001200 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1201 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001202 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001203 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001204 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1205 return(1);
1206 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001207 if (val < 0){
William M. Brack0c1e3012007-03-14 12:40:21 +00001208 reader->mode = XML_TEXTREADER_MODE_ERROR;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001209 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001210 }
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001211 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1212 return(1);
1213}
1214
1215/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001216 * xmlTextReaderCollectSiblings:
1217 * @node: the first child
1218 *
1219 * Traverse depth-first through all sibling nodes and their children
1220 * nodes and concatenate their content. This is an auxiliary function
1221 * to xmlTextReaderReadString.
1222 *
1223 * Returns a string containing the content, or NULL in case of error.
1224 */
1225static xmlChar *
1226xmlTextReaderCollectSiblings(xmlNodePtr node)
1227{
1228 xmlBufferPtr buffer;
1229 xmlChar *ret;
1230
Daniel Veillard3e62adb2012-08-09 14:24:02 +08001231 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1232 return(NULL);
1233
Daniel Veillarde125b312005-01-28 17:39:49 +00001234 buffer = xmlBufferCreate();
1235 if (buffer == NULL)
1236 return NULL;
1237
1238 for ( ; node != NULL; node = node->next) {
1239 switch (node->type) {
1240 case XML_TEXT_NODE:
1241 case XML_CDATA_SECTION_NODE:
1242 xmlBufferCat(buffer, node->content);
1243 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001244 case XML_ELEMENT_NODE: {
1245 xmlChar *tmp;
1246
1247 tmp = xmlTextReaderCollectSiblings(node->children);
1248 xmlBufferCat(buffer, tmp);
1249 xmlFree(tmp);
1250 break;
1251 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001252 default:
1253 break;
1254 }
1255 }
1256 ret = buffer->content;
1257 buffer->content = NULL;
1258 xmlBufferFree(buffer);
1259 return(ret);
1260}
1261
1262/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001263 * xmlTextReaderRead:
1264 * @reader: the xmlTextReaderPtr used
1265 *
1266 * Moves the position of the current instance to the next node in
1267 * the stream, exposing its properties.
1268 *
1269 * Returns 1 if the node was read successfully, 0 if there is no more
1270 * nodes to read, or -1 in case of error
1271 */
1272int
1273xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001274 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001275 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001276 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001277
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001278
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001279 if (reader == NULL)
1280 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001281 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001282 if (reader->doc != NULL)
1283 return(xmlTextReaderReadTree(reader));
1284 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001285 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001286
1287#ifdef DEBUG_READER
1288 fprintf(stderr, "\nREAD ");
1289 DUMP_READER
1290#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001291 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1292 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001293 /*
1294 * Initial state
1295 */
1296 do {
1297 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001298 if (val < 0){
1299 reader->mode = XML_TEXTREADER_MODE_ERROR;
1300 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001301 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001302 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001303 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001304 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
Daniel Veillarda9c56772007-03-09 16:59:05 +00001305 (reader->state != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001306 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001307 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001308 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001309 }
Daniel Veillarda9c56772007-03-09 16:59:05 +00001310 if (reader->node == NULL){
1311 reader->mode = XML_TEXTREADER_MODE_ERROR;
1312 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001313 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001314 }
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001315 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001316 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001317 if (reader->ctxt->myDoc != NULL) {
1318 reader->node = reader->ctxt->myDoc->children;
1319 }
1320 if (reader->node == NULL)
1321 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001322 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001323 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001324 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001325 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001326 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001327 }
1328 oldstate = reader->state;
1329 olddepth = reader->ctxt->nodeNr;
1330 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001331
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001332get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001333 if (reader->node == NULL) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001334 if (reader->mode == XML_TEXTREADER_MODE_EOF)
Daniel Veillard6f379a72004-04-29 18:45:42 +00001335 return(0);
1336 else
1337 return(-1);
1338 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001339
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001340 /*
1341 * If we are not backtracking on ancestors or examined nodes,
1342 * that the parser didn't finished or that we arent at the end
1343 * of stream, continue processing.
1344 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001345 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001346 (reader->ctxt->nodeNr == olddepth) &&
1347 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001348 (reader->node->children == NULL) ||
1349 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001350 ((reader->node->children != NULL) &&
1351 (reader->node->children->type == XML_TEXT_NODE) &&
1352 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001353 (reader->node->type == XML_DTD_NODE) ||
1354 (reader->node->type == XML_DOCUMENT_NODE) ||
1355 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001356 ((reader->ctxt->node == NULL) ||
1357 (reader->ctxt->node == reader->node) ||
1358 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001359 (reader->ctxt->instate != XML_PARSER_EOF)) {
1360 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001361 if (val < 0){
1362 reader->mode = XML_TEXTREADER_MODE_ERROR;
1363 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001364 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001365 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001366 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001367 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001368 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001369 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001370 if ((reader->node->children != NULL) &&
1371 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001372 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001373 (reader->node->type != XML_DTD_NODE)) {
1374 reader->node = reader->node->children;
1375 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001376 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001377 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001378 }
1379 }
1380 if (reader->node->next != NULL) {
1381 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001382 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001383 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001384 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1385#ifdef LIBXML_XINCLUDE_ENABLED
1386 && (reader->in_xinclude <= 0)
1387#endif
1388 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001389 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001390 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001391 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001392#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001393 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001394 (reader->node->type == XML_ELEMENT_NODE))
1395 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001396#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001397 if ((reader->preserves > 0) &&
1398 (reader->node->extra & NODE_IS_SPRESERVED))
1399 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001400 reader->node = reader->node->next;
1401 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001402
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001403 /*
1404 * Cleanup of the old node
1405 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001406 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001407#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001408 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001409#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001410 (reader->entNr == 0) &&
1411 (reader->node->prev != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001412 (reader->node->prev->type != XML_DTD_NODE) &&
1413 (reader->entNr == 0)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001414 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001415 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001416 xmlUnlinkNode(tmp);
1417 xmlTextReaderFreeNode(reader, tmp);
1418 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001419 }
1420
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001421 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001422 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001423 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001424 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001425 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001426 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001427 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001428 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001429 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001430#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001431 if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001432 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001433#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001434 if ((reader->preserves > 0) &&
1435 (reader->node->extra & NODE_IS_SPRESERVED))
1436 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001437 reader->node = reader->node->parent;
1438 if ((reader->node == NULL) ||
1439 (reader->node->type == XML_DOCUMENT_NODE) ||
1440#ifdef LIBXML_DOCB_ENABLED
1441 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1442#endif
1443 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001444 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001445 val = xmlParseChunk(reader->ctxt, "", 0, 1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001446 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001447 if (val != 0)
1448 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001449 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001450 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001451 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001452
1453 /*
1454 * Cleanup of the old node
1455 */
Daniel Veillard76d36452009-09-07 11:19:33 +02001456 if ((oldnode != NULL) && (reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001457#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001458 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001459#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001460 (reader->entNr == 0) &&
1461 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001462 ((oldnode->extra & NODE_IS_PRESERVED) == 0) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +00001463 (reader->entNr == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001464 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001465 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001466 }
1467
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001468 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001469 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001470 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001471#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001472 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001473#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001474 (reader->entNr == 0) &&
1475 (reader->node->last != NULL) &&
1476 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1477 xmlNodePtr tmp = reader->node->last;
1478 xmlUnlinkNode(tmp);
1479 xmlTextReaderFreeNode(reader, tmp);
1480 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001481 reader->depth--;
1482 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001483
1484node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001485 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001486
1487 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001488 * If we are in the middle of a piece of CDATA make sure it's finished
1489 */
1490 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001491 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001492 ((reader->node->type == XML_TEXT_NODE) ||
1493 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001494 if (xmlTextReaderExpand(reader) == NULL)
1495 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001496 }
1497
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001498#ifdef LIBXML_XINCLUDE_ENABLED
1499 /*
1500 * Handle XInclude if asked for
1501 */
1502 if ((reader->xinclude) && (reader->node != NULL) &&
1503 (reader->node->type == XML_ELEMENT_NODE) &&
1504 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001505 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1506 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001507 if (reader->xincctxt == NULL) {
1508 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001509 xmlXIncludeSetFlags(reader->xincctxt,
Daniel Veillardc14c3892004-08-16 12:34:50 +00001510 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001511 }
1512 /*
1513 * expand that node and process it
1514 */
William M. Brack42331a92004-07-29 07:07:16 +00001515 if (xmlTextReaderExpand(reader) == NULL)
1516 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001517 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1518 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001519 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001520 reader->in_xinclude++;
1521 goto get_next_node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001522 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001523 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001524 reader->in_xinclude--;
1525 goto get_next_node;
1526 }
1527#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001528 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001529 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001530 */
1531 if ((reader->node != NULL) &&
1532 (reader->node->type == XML_ENTITY_REF_NODE) &&
1533 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1534 /*
1535 * Case where the underlying tree is not availble, lookup the entity
1536 * and walk it.
1537 */
1538 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1539 (reader->ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001540 reader->node->children = (xmlNodePtr)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001541 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1542 }
1543
1544 if ((reader->node->children != NULL) &&
1545 (reader->node->children->type == XML_ENTITY_DECL) &&
1546 (reader->node->children->children != NULL)) {
1547 xmlTextReaderEntPush(reader, reader->node);
1548 reader->node = reader->node->children->children;
1549 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001550#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001551 } else if ((reader->node != NULL) &&
1552 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001553 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001554 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001555#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001556 }
1557 if ((reader->node != NULL) &&
1558 (reader->node->type == XML_ENTITY_DECL) &&
1559 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1560 reader->node = xmlTextReaderEntPop(reader);
1561 reader->depth++;
1562 goto get_next_node;
1563 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001564#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001565 if ((reader->validate) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001566 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001567
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001568 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001569 ((reader->state != XML_TEXTREADER_END) &&
1570 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1571 xmlTextReaderValidatePush(reader);
1572 } else if ((node->type == XML_TEXT_NODE) ||
1573 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001574 xmlTextReaderValidateCData(reader, node->content,
1575 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001576 }
1577 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001578#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001579#ifdef LIBXML_PATTERN_ENABLED
1580 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1581 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1582 int i;
1583 for (i = 0;i < reader->patternNr;i++) {
1584 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1585 xmlTextReaderPreserve(reader);
1586 break;
1587 }
1588 }
1589 }
1590#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001591#ifdef LIBXML_SCHEMAS_ENABLED
1592 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001593 (reader->xsdValidErrors == 0) &&
Daniel Veillardf10ae122005-07-10 19:03:16 +00001594 (reader->xsdValidCtxt != NULL)) {
1595 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1596 }
1597#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001598 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001599node_end:
Daniel Veillarda9c56772007-03-09 16:59:05 +00001600 reader->state = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001601 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001602}
1603
Daniel Veillard67df8092002-12-16 22:04:11 +00001604/**
1605 * xmlTextReaderReadState:
1606 * @reader: the xmlTextReaderPtr used
1607 *
1608 * Gets the read state of the reader.
1609 *
1610 * Returns the state value, or -1 in case of error
1611 */
1612int
1613xmlTextReaderReadState(xmlTextReaderPtr reader) {
1614 if (reader == NULL)
1615 return(-1);
1616 return(reader->mode);
1617}
1618
1619/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001620 * xmlTextReaderExpand:
1621 * @reader: the xmlTextReaderPtr used
1622 *
1623 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001624 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001625 *
1626 * Returns a node pointer valid until the next xmlTextReaderRead() call
1627 * or NULL in case of error.
1628 */
1629xmlNodePtr
1630xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001631 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001632 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001633 if (reader->doc != NULL)
1634 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001635 if (reader->ctxt == NULL)
1636 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001637 if (xmlTextReaderDoExpand(reader) < 0)
1638 return(NULL);
1639 return(reader->node);
1640}
1641
1642/**
1643 * xmlTextReaderNext:
1644 * @reader: the xmlTextReaderPtr used
1645 *
1646 * Skip to the node following the current one in document order while
1647 * avoiding the subtree if any.
1648 *
1649 * Returns 1 if the node was read successfully, 0 if there is no more
1650 * nodes to read, or -1 in case of error
1651 */
1652int
1653xmlTextReaderNext(xmlTextReaderPtr reader) {
1654 int ret;
1655 xmlNodePtr cur;
1656
1657 if (reader == NULL)
1658 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001659 if (reader->doc != NULL)
1660 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001661 cur = reader->node;
1662 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1663 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001664 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001665 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001666 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001667 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001668 do {
1669 ret = xmlTextReaderRead(reader);
1670 if (ret != 1)
1671 return(ret);
1672 } while (reader->node != cur);
1673 return(xmlTextReaderRead(reader));
1674}
1675
Daniel Veillardd0271472006-01-02 10:22:02 +00001676#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001677/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001678 * xmlTextReaderReadInnerXml:
1679 * @reader: the xmlTextReaderPtr used
1680 *
1681 * Reads the contents of the current node, including child nodes and markup.
1682 *
1683 * Returns a string containing the XML content, or NULL if the current node
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001684 * is neither an element nor attribute, or has no child nodes. The
Daniel Veillard67df8092002-12-16 22:04:11 +00001685 * string must be deallocated by the caller.
1686 */
1687xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001688xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1689{
1690 xmlChar *resbuf;
1691 xmlNodePtr node, cur_node;
1692 xmlBufferPtr buff, buff2;
1693 xmlDocPtr doc;
1694
1695 if (xmlTextReaderExpand(reader) == NULL) {
1696 return NULL;
1697 }
1698 doc = reader->doc;
1699 buff = xmlBufferCreate();
1700 for (cur_node = reader->node->children; cur_node != NULL;
1701 cur_node = cur_node->next) {
1702 node = xmlDocCopyNode(cur_node, doc, 1);
1703 buff2 = xmlBufferCreate();
1704 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1705 xmlFreeNode(node);
1706 xmlBufferFree(buff2);
1707 xmlBufferFree(buff);
1708 return NULL;
1709 }
1710 xmlBufferCat(buff, buff2->content);
1711 xmlFreeNode(node);
1712 xmlBufferFree(buff2);
1713 }
1714 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001715 buff->content = NULL;
1716
1717 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001718 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001719}
Daniel Veillardd0271472006-01-02 10:22:02 +00001720#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001721
Daniel Veillardd0271472006-01-02 10:22:02 +00001722#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001723/**
1724 * xmlTextReaderReadOuterXml:
1725 * @reader: the xmlTextReaderPtr used
1726 *
1727 * Reads the contents of the current node, including child nodes and markup.
1728 *
Rob Richards5b9dde32010-05-05 07:59:44 -04001729 * Returns a string containing the node and any XML content, or NULL if the
1730 * current node cannot be serialized. The string must be deallocated
1731 * by the caller.
Daniel Veillard67df8092002-12-16 22:04:11 +00001732 */
1733xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001734xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1735{
1736 xmlChar *resbuf;
1737 xmlNodePtr node;
1738 xmlBufferPtr buff;
1739 xmlDocPtr doc;
1740
1741 node = reader->node;
1742 doc = reader->doc;
1743 if (xmlTextReaderExpand(reader) == NULL) {
1744 return NULL;
1745 }
Rob Richards5b9dde32010-05-05 07:59:44 -04001746 if (node->type == XML_DTD_NODE) {
1747 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1748 } else {
1749 node = xmlDocCopyNode(node, doc, 1);
1750 }
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001751 buff = xmlBufferCreate();
1752 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1753 xmlFreeNode(node);
1754 xmlBufferFree(buff);
1755 return NULL;
1756 }
1757
1758 resbuf = buff->content;
1759 buff->content = NULL;
1760
1761 xmlFreeNode(node);
1762 xmlBufferFree(buff);
1763 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001764}
Daniel Veillardd0271472006-01-02 10:22:02 +00001765#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001766
1767/**
1768 * xmlTextReaderReadString:
1769 * @reader: the xmlTextReaderPtr used
1770 *
1771 * Reads the contents of an element or a text node as a string.
1772 *
1773 * Returns a string containing the contents of the Element or Text node,
1774 * or NULL if the reader is positioned on any other type of node.
1775 * The string must be deallocated by the caller.
1776 */
1777xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001778xmlTextReaderReadString(xmlTextReaderPtr reader)
1779{
1780 xmlNodePtr node;
1781
1782 if ((reader == NULL) || (reader->node == NULL))
1783 return(NULL);
1784
1785 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1786 switch (node->type) {
1787 case XML_TEXT_NODE:
1788 if (node->content != NULL)
1789 return(xmlStrdup(node->content));
1790 break;
1791 case XML_ELEMENT_NODE:
1792 if (xmlTextReaderDoExpand(reader) != -1) {
1793 return xmlTextReaderCollectSiblings(node->children);
1794 }
1795 case XML_ATTRIBUTE_NODE:
1796 TODO
1797 break;
1798 default:
1799 break;
1800 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001801 return(NULL);
1802}
1803
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001804#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001805/**
1806 * xmlTextReaderReadBase64:
1807 * @reader: the xmlTextReaderPtr used
1808 * @array: a byte array to store the content.
1809 * @offset: the zero-based index into array where the method should
1810 * begin to write.
1811 * @len: the number of bytes to write.
1812 *
1813 * Reads and decodes the Base64 encoded contents of an element and
1814 * stores the result in a byte buffer.
1815 *
1816 * Returns the number of bytes written to array, or zero if the current
1817 * instance is not positioned on an element or -1 in case of error.
1818 */
1819int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001820xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1821 unsigned char *array ATTRIBUTE_UNUSED,
1822 int offset ATTRIBUTE_UNUSED,
1823 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001824 if ((reader == NULL) || (reader->ctxt == NULL))
1825 return(-1);
1826 if (reader->ctxt->wellFormed != 1)
1827 return(-1);
1828
1829 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1830 return(0);
1831 TODO
1832 return(0);
1833}
1834
1835/**
1836 * xmlTextReaderReadBinHex:
1837 * @reader: the xmlTextReaderPtr used
1838 * @array: a byte array to store the content.
1839 * @offset: the zero-based index into array where the method should
1840 * begin to write.
1841 * @len: the number of bytes to write.
1842 *
1843 * Reads and decodes the BinHex encoded contents of an element and
1844 * stores the result in a byte buffer.
1845 *
1846 * Returns the number of bytes written to array, or zero if the current
1847 * instance is not positioned on an element or -1 in case of error.
1848 */
1849int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001850xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1851 unsigned char *array ATTRIBUTE_UNUSED,
1852 int offset ATTRIBUTE_UNUSED,
1853 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001854 if ((reader == NULL) || (reader->ctxt == NULL))
1855 return(-1);
1856 if (reader->ctxt->wellFormed != 1)
1857 return(-1);
1858
1859 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1860 return(0);
1861 TODO
1862 return(0);
1863}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001864#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001865
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001866/************************************************************************
1867 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001868 * Operating on a preparsed tree *
1869 * *
1870 ************************************************************************/
1871static int
1872xmlTextReaderNextTree(xmlTextReaderPtr reader)
1873{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001874 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001875 return(-1);
1876
1877 if (reader->state == XML_TEXTREADER_END)
1878 return(0);
1879
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001880 if (reader->node == NULL) {
1881 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001882 reader->state = XML_TEXTREADER_END;
1883 return(0);
1884 }
1885
1886 reader->node = reader->doc->children;
1887 reader->state = XML_TEXTREADER_START;
1888 return(1);
1889 }
1890
1891 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001892 /* Here removed traversal to child, because we want to skip the subtree,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001893 replace with traversal to sibling to skip subtree */
1894 if (reader->node->next != 0) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001895 /* Move to sibling if present,skipping sub-tree */
1896 reader->node = reader->node->next;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001897 reader->state = XML_TEXTREADER_START;
1898 return(1);
1899 }
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001900
1901 /* if reader->node->next is NULL mean no subtree for current node,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001902 so need to move to sibling of parent node if present */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001903 if ((reader->node->type == XML_ELEMENT_NODE) ||
1904 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1905 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001906 /* This will move to parent if present */
1907 xmlTextReaderRead(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001908 }
1909 }
1910
1911 if (reader->node->next != 0) {
1912 reader->node = reader->node->next;
1913 reader->state = XML_TEXTREADER_START;
1914 return(1);
1915 }
1916
1917 if (reader->node->parent != 0) {
1918 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1919 reader->state = XML_TEXTREADER_END;
1920 return(0);
1921 }
1922
1923 reader->node = reader->node->parent;
1924 reader->depth--;
1925 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001926 /* Repeat process to move to sibling of parent node if present */
1927 xmlTextReaderNextTree(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001928 }
1929
1930 reader->state = XML_TEXTREADER_END;
1931
1932 return(1);
1933}
1934
1935/**
1936 * xmlTextReaderReadTree:
1937 * @reader: the xmlTextReaderPtr used
1938 *
1939 * Moves the position of the current instance to the next node in
1940 * the stream, exposing its properties.
1941 *
1942 * Returns 1 if the node was read successfully, 0 if there is no more
1943 * nodes to read, or -1 in case of error
1944 */
1945static int
1946xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1947 if (reader->state == XML_TEXTREADER_END)
1948 return(0);
1949
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001950next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001951 if (reader->node == NULL) {
1952 if (reader->doc->children == NULL) {
1953 reader->state = XML_TEXTREADER_END;
1954 return(0);
1955 }
1956
1957 reader->node = reader->doc->children;
1958 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001959 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001960 }
1961
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001962 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1963 (reader->node->type != XML_DTD_NODE) &&
1964 (reader->node->type != XML_XINCLUDE_START) &&
1965 (reader->node->type != XML_ENTITY_REF_NODE)) {
1966 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001967 reader->node = reader->node->children;
1968 reader->depth++;
1969 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001970 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001971 }
1972
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001973 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001974 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001975 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001976 }
1977 }
1978
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001979 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001980 reader->node = reader->node->next;
1981 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001982 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001983 }
1984
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001985 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001986 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1987 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1988 reader->state = XML_TEXTREADER_END;
1989 return(0);
1990 }
1991
1992 reader->node = reader->node->parent;
1993 reader->depth--;
1994 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001995 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001996 }
1997
1998 reader->state = XML_TEXTREADER_END;
1999
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002000found_node:
2001 if ((reader->node->type == XML_XINCLUDE_START) ||
2002 (reader->node->type == XML_XINCLUDE_END))
2003 goto next_node;
2004
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002005 return(1);
2006}
2007
2008/**
William M. Brackb1d53162003-11-18 06:54:40 +00002009 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002010 * @reader: the xmlTextReaderPtr used
2011 *
2012 * Skip to the node following the current one in document order while
2013 * avoiding the subtree if any.
2014 * Currently implemented only for Readers built on a document
2015 *
2016 * Returns 1 if the node was read successfully, 0 if there is no more
2017 * nodes to read, or -1 in case of error
2018 */
2019int
2020xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2021 if (reader == NULL)
2022 return(-1);
2023 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002024 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002025 return(-1);
2026 }
2027
2028 if (reader->state == XML_TEXTREADER_END)
2029 return(0);
2030
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002031 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002032 return(xmlTextReaderNextTree(reader));
2033
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002034 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002035 reader->node = reader->node->next;
2036 reader->state = XML_TEXTREADER_START;
2037 return(1);
2038 }
2039
2040 return(0);
2041}
2042
2043/************************************************************************
2044 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002045 * Constructor and destructors *
2046 * *
2047 ************************************************************************/
2048/**
2049 * xmlNewTextReader:
2050 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002051 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002052 *
2053 * Create an xmlTextReader structure fed with @input
2054 *
2055 * Returns the new xmlTextReaderPtr or NULL in case of error
2056 */
2057xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002058xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002059 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002060
2061 if (input == NULL)
2062 return(NULL);
2063 ret = xmlMalloc(sizeof(xmlTextReader));
2064 if (ret == NULL) {
2065 xmlGenericError(xmlGenericErrorContext,
2066 "xmlNewTextReader : malloc failed\n");
2067 return(NULL);
2068 }
2069 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002070 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002071 ret->entTab = NULL;
2072 ret->entMax = 0;
2073 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002074 ret->input = input;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002075 ret->buffer = xmlBufCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002076 if (ret->buffer == NULL) {
2077 xmlFree(ret);
2078 xmlGenericError(xmlGenericErrorContext,
2079 "xmlNewTextReader : malloc failed\n");
2080 return(NULL);
2081 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002082 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2083 if (ret->sax == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08002084 xmlBufFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002085 xmlFree(ret);
2086 xmlGenericError(xmlGenericErrorContext,
2087 "xmlNewTextReader : malloc failed\n");
2088 return(NULL);
2089 }
Daniel Veillard81273902003-09-30 00:43:48 +00002090 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002091 ret->startElement = ret->sax->startElement;
2092 ret->sax->startElement = xmlTextReaderStartElement;
2093 ret->endElement = ret->sax->endElement;
2094 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002095#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002096 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002097#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002098 ret->startElementNs = ret->sax->startElementNs;
2099 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2100 ret->endElementNs = ret->sax->endElementNs;
2101 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002102#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002103 } else {
2104 ret->startElementNs = NULL;
2105 ret->endElementNs = NULL;
2106 }
Daniel Veillard81273902003-09-30 00:43:48 +00002107#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002108 ret->characters = ret->sax->characters;
2109 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002110 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002111 ret->cdataBlock = ret->sax->cdataBlock;
2112 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002113
Daniel Veillard67df8092002-12-16 22:04:11 +00002114 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002116 ret->curnode = NULL;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002117 if (xmlBufUse(ret->input->buffer) < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002118 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002119 }
Daniel Veillard8aebce32012-07-16 14:42:31 +08002120 if (xmlBufUse(ret->input->buffer) >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002121 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08002122 (const char *) xmlBufContent(ret->input->buffer),
2123 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002124 ret->base = 0;
2125 ret->cur = 4;
2126 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002127 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002128 ret->base = 0;
2129 ret->cur = 0;
2130 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002131
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002132 if (ret->ctxt == NULL) {
2133 xmlGenericError(xmlGenericErrorContext,
2134 "xmlNewTextReader : malloc failed\n");
Daniel Veillard8aebce32012-07-16 14:42:31 +08002135 xmlBufFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002136 xmlFree(ret->sax);
2137 xmlFree(ret);
2138 return(NULL);
2139 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002140 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002141 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002142 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002143 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002144 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002145 /*
2146 * use the parser dictionnary to allocate all elements and attributes names
2147 */
2148 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002149 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002150#ifdef LIBXML_XINCLUDE_ENABLED
2151 ret->xinclude = 0;
2152#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002153#ifdef LIBXML_PATTERN_ENABLED
2154 ret->patternMax = 0;
2155 ret->patternTab = NULL;
2156#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002157 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002158}
2159
2160/**
2161 * xmlNewTextReaderFilename:
2162 * @URI: the URI of the resource to process
2163 *
2164 * Create an xmlTextReader structure fed with the resource at @URI
2165 *
2166 * Returns the new xmlTextReaderPtr or NULL in case of error
2167 */
2168xmlTextReaderPtr
2169xmlNewTextReaderFilename(const char *URI) {
2170 xmlParserInputBufferPtr input;
2171 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002172 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002173
2174 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2175 if (input == NULL)
2176 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002177 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002178 if (ret == NULL) {
2179 xmlFreeParserInputBuffer(input);
2180 return(NULL);
2181 }
2182 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002183 if (ret->ctxt->directory == NULL)
2184 directory = xmlParserGetDirectory(URI);
2185 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2186 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2187 if (directory != NULL)
2188 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002189 return(ret);
2190}
2191
2192/**
2193 * xmlFreeTextReader:
2194 * @reader: the xmlTextReaderPtr
2195 *
2196 * Deallocate all the resources associated to the reader
2197 */
2198void
2199xmlFreeTextReader(xmlTextReaderPtr reader) {
2200 if (reader == NULL)
2201 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002202#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002203 if (reader->rngSchemas != NULL) {
2204 xmlRelaxNGFree(reader->rngSchemas);
2205 reader->rngSchemas = NULL;
2206 }
2207 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08002208 if (! reader->rngPreserveCtxt)
2209 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillardf4e55762003-04-15 23:32:22 +00002210 reader->rngValidCtxt = NULL;
2211 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002212 if (reader->xsdPlug != NULL) {
2213 xmlSchemaSAXUnplug(reader->xsdPlug);
2214 reader->xsdPlug = NULL;
2215 }
2216 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002217 if (! reader->xsdPreserveCtxt)
2218 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002219 reader->xsdValidCtxt = NULL;
2220 }
2221 if (reader->xsdSchemas != NULL) {
2222 xmlSchemaFree(reader->xsdSchemas);
2223 reader->xsdSchemas = NULL;
2224 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002225#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002226#ifdef LIBXML_XINCLUDE_ENABLED
2227 if (reader->xincctxt != NULL)
2228 xmlXIncludeFreeContext(reader->xincctxt);
2229#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002230#ifdef LIBXML_PATTERN_ENABLED
2231 if (reader->patternTab != NULL) {
2232 int i;
2233 for (i = 0;i < reader->patternNr;i++) {
2234 if (reader->patternTab[i] != NULL)
2235 xmlFreePattern(reader->patternTab[i]);
2236 }
2237 xmlFree(reader->patternTab);
2238 }
2239#endif
Daniel Veillardf4653dc2009-08-21 18:40:50 +02002240 if (reader->faketext != NULL) {
2241 xmlFreeNode(reader->faketext);
2242 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002243 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002244 if (reader->dict == reader->ctxt->dict)
2245 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002246 if (reader->ctxt->myDoc != NULL) {
2247 if (reader->preserve == 0)
2248 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2249 reader->ctxt->myDoc = NULL;
2250 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002251 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2252 (reader->ctxt->vctxt.vstateMax > 0)){
2253 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002254 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002255 reader->ctxt->vctxt.vstateMax = 0;
2256 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002257 if (reader->allocs & XML_TEXTREADER_CTXT)
2258 xmlFreeParserCtxt(reader->ctxt);
2259 }
2260 if (reader->sax != NULL)
2261 xmlFree(reader->sax);
2262 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2263 xmlFreeParserInputBuffer(reader->input);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002264 if (reader->buffer != NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08002265 xmlBufFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002266 if (reader->entTab != NULL)
2267 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002268 if (reader->dict != NULL)
2269 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002270 xmlFree(reader);
2271}
2272
2273/************************************************************************
2274 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002275 * Methods for XmlTextReader *
2276 * *
2277 ************************************************************************/
2278/**
2279 * xmlTextReaderClose:
2280 * @reader: the xmlTextReaderPtr used
2281 *
2282 * This method releases any resources allocated by the current instance
2283 * changes the state to Closed and close any underlying input.
2284 *
2285 * Returns 0 or -1 in case of error
2286 */
2287int
2288xmlTextReaderClose(xmlTextReaderPtr reader) {
2289 if (reader == NULL)
2290 return(-1);
2291 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002292 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002293 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2294 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002295 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002296 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002297 if (reader->preserve == 0)
2298 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002299 reader->ctxt->myDoc = NULL;
2300 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002301 }
2302 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2303 xmlFreeParserInputBuffer(reader->input);
2304 reader->allocs -= XML_TEXTREADER_INPUT;
2305 }
2306 return(0);
2307}
2308
2309/**
2310 * xmlTextReaderGetAttributeNo:
2311 * @reader: the xmlTextReaderPtr used
2312 * @no: the zero-based index of the attribute relative to the containing element
2313 *
2314 * Provides the value of the attribute with the specified index relative
2315 * to the containing element.
2316 *
2317 * Returns a string containing the value of the specified attribute, or NULL
2318 * in case of error. The string must be deallocated by the caller.
2319 */
2320xmlChar *
2321xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2322 xmlChar *ret;
2323 int i;
2324 xmlAttrPtr cur;
2325 xmlNsPtr ns;
2326
2327 if (reader == NULL)
2328 return(NULL);
2329 if (reader->node == NULL)
2330 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002331 if (reader->curnode != NULL)
2332 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002333 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002334 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002335 return(NULL);
2336
2337 ns = reader->node->nsDef;
2338 for (i = 0;(i < no) && (ns != NULL);i++) {
2339 ns = ns->next;
2340 }
2341 if (ns != NULL)
2342 return(xmlStrdup(ns->href));
2343
2344 cur = reader->node->properties;
2345 if (cur == NULL)
2346 return(NULL);
2347 for (;i < no;i++) {
2348 cur = cur->next;
2349 if (cur == NULL)
2350 return(NULL);
2351 }
2352 /* TODO walk the DTD if present */
2353
2354 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2355 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2356 return(ret);
2357}
2358
2359/**
2360 * xmlTextReaderGetAttribute:
2361 * @reader: the xmlTextReaderPtr used
2362 * @name: the qualified name of the attribute.
2363 *
2364 * Provides the value of the attribute with the specified qualified name.
2365 *
2366 * Returns a string containing the value of the specified attribute, or NULL
2367 * in case of error. The string must be deallocated by the caller.
2368 */
2369xmlChar *
2370xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2371 xmlChar *prefix = NULL;
2372 xmlChar *localname;
2373 xmlNsPtr ns;
2374 xmlChar *ret = NULL;
2375
2376 if ((reader == NULL) || (name == NULL))
2377 return(NULL);
2378 if (reader->node == NULL)
2379 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002380 if (reader->curnode != NULL)
2381 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002382
2383 /* TODO: handle the xmlDecl */
2384 if (reader->node->type != XML_ELEMENT_NODE)
2385 return(NULL);
2386
2387 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002388 if (localname == NULL) {
2389 /*
2390 * Namespace default decl
2391 */
2392 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2393 ns = reader->node->nsDef;
2394 while (ns != NULL) {
2395 if (ns->prefix == NULL) {
2396 return(xmlStrdup(ns->href));
2397 }
2398 ns = ns->next;
2399 }
2400 return NULL;
2401 }
2402 return(xmlGetNoNsProp(reader->node, name));
2403 }
2404
2405 /*
2406 * Namespace default decl
2407 */
2408 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2409 ns = reader->node->nsDef;
2410 while (ns != NULL) {
2411 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2412 ret = xmlStrdup(ns->href);
2413 break;
2414 }
2415 ns = ns->next;
2416 }
2417 } else {
2418 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2419 if (ns != NULL)
2420 ret = xmlGetNsProp(reader->node, localname, ns->href);
2421 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002422
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002423 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002424 if (prefix != NULL)
2425 xmlFree(prefix);
2426 return(ret);
2427}
2428
2429
2430/**
2431 * xmlTextReaderGetAttributeNs:
2432 * @reader: the xmlTextReaderPtr used
2433 * @localName: the local name of the attribute.
2434 * @namespaceURI: the namespace URI of the attribute.
2435 *
2436 * Provides the value of the specified attribute
2437 *
2438 * Returns a string containing the value of the specified attribute, or NULL
2439 * in case of error. The string must be deallocated by the caller.
2440 */
2441xmlChar *
2442xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2443 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002444 xmlChar *prefix = NULL;
2445 xmlNsPtr ns;
2446
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002447 if ((reader == NULL) || (localName == NULL))
2448 return(NULL);
2449 if (reader->node == NULL)
2450 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002451 if (reader->curnode != NULL)
2452 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002453
2454 /* TODO: handle the xmlDecl */
2455 if (reader->node->type != XML_ELEMENT_NODE)
2456 return(NULL);
2457
Daniel Veillard45b97e72005-08-20 21:14:28 +00002458 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2459 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2460 prefix = BAD_CAST localName;
2461 }
2462 ns = reader->node->nsDef;
2463 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002464 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002465 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2466 return xmlStrdup(ns->href);
2467 }
2468 ns = ns->next;
2469 }
2470 return NULL;
2471 }
2472
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002473 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2474}
2475
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002476/**
2477 * xmlTextReaderGetRemainder:
2478 * @reader: the xmlTextReaderPtr used
2479 *
2480 * Method to get the remainder of the buffered XML. this method stops the
2481 * parser, set its state to End Of File and return the input stream with
2482 * what is left that the parser did not use.
2483 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002484 * The implementation is not good, the parser certainly procgressed past
2485 * what's left in reader->input, and there is an allocation problem. Best
2486 * would be to rewrite it differently.
2487 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002488 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2489 * in case of error.
2490 */
2491xmlParserInputBufferPtr
2492xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2493 xmlParserInputBufferPtr ret = NULL;
2494
2495 if (reader == NULL)
2496 return(NULL);
2497 if (reader->node == NULL)
2498 return(NULL);
2499
2500 reader->node = NULL;
2501 reader->curnode = NULL;
2502 reader->mode = XML_TEXTREADER_MODE_EOF;
2503 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002504 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002505 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002506 if (reader->preserve == 0)
2507 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002508 reader->ctxt->myDoc = NULL;
2509 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002510 }
2511 if (reader->allocs & XML_TEXTREADER_INPUT) {
2512 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002513 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002514 reader->allocs -= XML_TEXTREADER_INPUT;
2515 } else {
2516 /*
2517 * Hum, one may need to duplicate the data structure because
2518 * without reference counting the input may be freed twice:
2519 * - by the layer which allocated it.
2520 * - by the layer to which would have been returned to.
2521 */
2522 TODO
2523 return(NULL);
2524 }
2525 return(ret);
2526}
2527
2528/**
2529 * xmlTextReaderLookupNamespace:
2530 * @reader: the xmlTextReaderPtr used
2531 * @prefix: the prefix whose namespace URI is to be resolved. To return
2532 * the default namespace, specify NULL
2533 *
2534 * Resolves a namespace prefix in the scope of the current element.
2535 *
2536 * Returns a string containing the namespace URI to which the prefix maps
2537 * or NULL in case of error. The string must be deallocated by the caller.
2538 */
2539xmlChar *
2540xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2541 xmlNsPtr ns;
2542
2543 if (reader == NULL)
2544 return(NULL);
2545 if (reader->node == NULL)
2546 return(NULL);
2547
2548 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2549 if (ns == NULL)
2550 return(NULL);
2551 return(xmlStrdup(ns->href));
2552}
2553
2554/**
2555 * xmlTextReaderMoveToAttributeNo:
2556 * @reader: the xmlTextReaderPtr used
2557 * @no: the zero-based index of the attribute relative to the containing
2558 * element.
2559 *
2560 * Moves the position of the current instance to the attribute with
2561 * the specified index relative to the containing element.
2562 *
2563 * Returns 1 in case of success, -1 in case of error, 0 if not found
2564 */
2565int
2566xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2567 int i;
2568 xmlAttrPtr cur;
2569 xmlNsPtr ns;
2570
2571 if (reader == NULL)
2572 return(-1);
2573 if (reader->node == NULL)
2574 return(-1);
2575 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002576 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002577 return(-1);
2578
2579 reader->curnode = NULL;
2580
2581 ns = reader->node->nsDef;
2582 for (i = 0;(i < no) && (ns != NULL);i++) {
2583 ns = ns->next;
2584 }
2585 if (ns != NULL) {
2586 reader->curnode = (xmlNodePtr) ns;
2587 return(1);
2588 }
2589
2590 cur = reader->node->properties;
2591 if (cur == NULL)
2592 return(0);
2593 for (;i < no;i++) {
2594 cur = cur->next;
2595 if (cur == NULL)
2596 return(0);
2597 }
2598 /* TODO walk the DTD if present */
2599
2600 reader->curnode = (xmlNodePtr) cur;
2601 return(1);
2602}
2603
2604/**
2605 * xmlTextReaderMoveToAttribute:
2606 * @reader: the xmlTextReaderPtr used
2607 * @name: the qualified name of the attribute.
2608 *
2609 * Moves the position of the current instance to the attribute with
2610 * the specified qualified name.
2611 *
2612 * Returns 1 in case of success, -1 in case of error, 0 if not found
2613 */
2614int
2615xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2616 xmlChar *prefix = NULL;
2617 xmlChar *localname;
2618 xmlNsPtr ns;
2619 xmlAttrPtr prop;
2620
2621 if ((reader == NULL) || (name == NULL))
2622 return(-1);
2623 if (reader->node == NULL)
2624 return(-1);
2625
2626 /* TODO: handle the xmlDecl */
2627 if (reader->node->type != XML_ELEMENT_NODE)
2628 return(0);
2629
2630 localname = xmlSplitQName2(name, &prefix);
2631 if (localname == NULL) {
2632 /*
2633 * Namespace default decl
2634 */
2635 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2636 ns = reader->node->nsDef;
2637 while (ns != NULL) {
2638 if (ns->prefix == NULL) {
2639 reader->curnode = (xmlNodePtr) ns;
2640 return(1);
2641 }
2642 ns = ns->next;
2643 }
2644 return(0);
2645 }
2646
2647 prop = reader->node->properties;
2648 while (prop != NULL) {
2649 /*
2650 * One need to have
2651 * - same attribute names
2652 * - and the attribute carrying that namespace
2653 */
2654 if ((xmlStrEqual(prop->name, name)) &&
2655 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2656 reader->curnode = (xmlNodePtr) prop;
2657 return(1);
2658 }
2659 prop = prop->next;
2660 }
2661 return(0);
2662 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002663
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002664 /*
2665 * Namespace default decl
2666 */
2667 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2668 ns = reader->node->nsDef;
2669 while (ns != NULL) {
2670 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2671 reader->curnode = (xmlNodePtr) ns;
2672 goto found;
2673 }
2674 ns = ns->next;
2675 }
2676 goto not_found;
2677 }
2678 prop = reader->node->properties;
2679 while (prop != NULL) {
2680 /*
2681 * One need to have
2682 * - same attribute names
2683 * - and the attribute carrying that namespace
2684 */
2685 if ((xmlStrEqual(prop->name, localname)) &&
2686 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2687 reader->curnode = (xmlNodePtr) prop;
2688 goto found;
2689 }
2690 prop = prop->next;
2691 }
2692not_found:
2693 if (localname != NULL)
2694 xmlFree(localname);
2695 if (prefix != NULL)
2696 xmlFree(prefix);
2697 return(0);
2698
2699found:
2700 if (localname != NULL)
2701 xmlFree(localname);
2702 if (prefix != NULL)
2703 xmlFree(prefix);
2704 return(1);
2705}
2706
2707/**
2708 * xmlTextReaderMoveToAttributeNs:
2709 * @reader: the xmlTextReaderPtr used
2710 * @localName: the local name of the attribute.
2711 * @namespaceURI: the namespace URI of the attribute.
2712 *
2713 * Moves the position of the current instance to the attribute with the
2714 * specified local name and namespace URI.
2715 *
2716 * Returns 1 in case of success, -1 in case of error, 0 if not found
2717 */
2718int
2719xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2720 const xmlChar *localName, const xmlChar *namespaceURI) {
2721 xmlAttrPtr prop;
2722 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002723 xmlNsPtr ns;
2724 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002725
2726 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2727 return(-1);
2728 if (reader->node == NULL)
2729 return(-1);
2730 if (reader->node->type != XML_ELEMENT_NODE)
2731 return(0);
2732 node = reader->node;
2733
Daniel Veillard45b97e72005-08-20 21:14:28 +00002734 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2735 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2736 prefix = BAD_CAST localName;
2737 }
2738 ns = reader->node->nsDef;
2739 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002740 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002741 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2742 reader->curnode = (xmlNodePtr) ns;
2743 return(1);
2744 }
2745 ns = ns->next;
2746 }
2747 return(0);
2748 }
2749
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002750 prop = node->properties;
2751 while (prop != NULL) {
2752 /*
2753 * One need to have
2754 * - same attribute names
2755 * - and the attribute carrying that namespace
2756 */
2757 if (xmlStrEqual(prop->name, localName) &&
2758 ((prop->ns != NULL) &&
2759 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2760 reader->curnode = (xmlNodePtr) prop;
2761 return(1);
2762 }
2763 prop = prop->next;
2764 }
2765 return(0);
2766}
2767
2768/**
2769 * xmlTextReaderMoveToFirstAttribute:
2770 * @reader: the xmlTextReaderPtr used
2771 *
2772 * Moves the position of the current instance to the first attribute
2773 * associated with the current node.
2774 *
2775 * Returns 1 in case of success, -1 in case of error, 0 if not found
2776 */
2777int
2778xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2779 if (reader == NULL)
2780 return(-1);
2781 if (reader->node == NULL)
2782 return(-1);
2783 if (reader->node->type != XML_ELEMENT_NODE)
2784 return(0);
2785
2786 if (reader->node->nsDef != NULL) {
2787 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2788 return(1);
2789 }
2790 if (reader->node->properties != NULL) {
2791 reader->curnode = (xmlNodePtr) reader->node->properties;
2792 return(1);
2793 }
2794 return(0);
2795}
2796
2797/**
2798 * xmlTextReaderMoveToNextAttribute:
2799 * @reader: the xmlTextReaderPtr used
2800 *
2801 * Moves the position of the current instance to the next attribute
2802 * associated with the current node.
2803 *
2804 * Returns 1 in case of success, -1 in case of error, 0 if not found
2805 */
2806int
2807xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2808 if (reader == NULL)
2809 return(-1);
2810 if (reader->node == NULL)
2811 return(-1);
2812 if (reader->node->type != XML_ELEMENT_NODE)
2813 return(0);
2814 if (reader->curnode == NULL)
2815 return(xmlTextReaderMoveToFirstAttribute(reader));
2816
2817 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2818 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2819 if (ns->next != NULL) {
2820 reader->curnode = (xmlNodePtr) ns->next;
2821 return(1);
2822 }
2823 if (reader->node->properties != NULL) {
2824 reader->curnode = (xmlNodePtr) reader->node->properties;
2825 return(1);
2826 }
2827 return(0);
2828 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2829 (reader->curnode->next != NULL)) {
2830 reader->curnode = reader->curnode->next;
2831 return(1);
2832 }
2833 return(0);
2834}
2835
2836/**
2837 * xmlTextReaderMoveToElement:
2838 * @reader: the xmlTextReaderPtr used
2839 *
2840 * Moves the position of the current instance to the node that
2841 * contains the current Attribute node.
2842 *
2843 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2844 */
2845int
2846xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2847 if (reader == NULL)
2848 return(-1);
2849 if (reader->node == NULL)
2850 return(-1);
2851 if (reader->node->type != XML_ELEMENT_NODE)
2852 return(0);
2853 if (reader->curnode != NULL) {
2854 reader->curnode = NULL;
2855 return(1);
2856 }
2857 return(0);
2858}
2859
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002860/**
2861 * xmlTextReaderReadAttributeValue:
2862 * @reader: the xmlTextReaderPtr used
2863 *
2864 * Parses an attribute value into one or more Text and EntityReference nodes.
2865 *
2866 * Returns 1 in case of success, 0 if the reader was not positionned on an
2867 * ttribute node or all the attribute values have been read, or -1
2868 * in case of error.
2869 */
2870int
2871xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2872 if (reader == NULL)
2873 return(-1);
2874 if (reader->node == NULL)
2875 return(-1);
2876 if (reader->curnode == NULL)
2877 return(0);
2878 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2879 if (reader->curnode->children == NULL)
2880 return(0);
2881 reader->curnode = reader->curnode->children;
2882 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2883 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2884
2885 if (reader->faketext == NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002886 reader->faketext = xmlNewDocText(reader->node->doc,
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002887 ns->href);
2888 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002889 if ((reader->faketext->content != NULL) &&
2890 (reader->faketext->content !=
2891 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002892 xmlFree(reader->faketext->content);
2893 reader->faketext->content = xmlStrdup(ns->href);
2894 }
2895 reader->curnode = reader->faketext;
2896 } else {
2897 if (reader->curnode->next == NULL)
2898 return(0);
2899 reader->curnode = reader->curnode->next;
2900 }
2901 return(1);
2902}
2903
Daniel Veillarde2811272004-10-19 09:04:23 +00002904/**
2905 * xmlTextReaderConstEncoding:
2906 * @reader: the xmlTextReaderPtr used
2907 *
2908 * Determine the encoding of the document being read.
2909 *
2910 * Returns a string containing the encoding of the document or NULL in
2911 * case of error. The string is deallocated with the reader.
2912 */
2913const xmlChar *
2914xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2915 xmlDocPtr doc = NULL;
2916 if (reader == NULL)
2917 return(NULL);
2918 if (reader->doc != NULL)
2919 doc = reader->doc;
2920 else if (reader->ctxt != NULL)
2921 doc = reader->ctxt->myDoc;
2922 if (doc == NULL)
2923 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002924
Daniel Veillarde2811272004-10-19 09:04:23 +00002925 if (doc->encoding == NULL)
2926 return(NULL);
2927 else
2928 return(CONSTSTR(doc->encoding));
2929}
2930
2931
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002932/************************************************************************
2933 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002934 * Acces API to the current node *
2935 * *
2936 ************************************************************************/
2937/**
2938 * xmlTextReaderAttributeCount:
2939 * @reader: the xmlTextReaderPtr used
2940 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002941 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002942 *
2943 * Returns 0 i no attributes, -1 in case of error or the attribute count
2944 */
2945int
2946xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2947 int ret;
2948 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002949 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002950 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002951
2952 if (reader == NULL)
2953 return(-1);
2954 if (reader->node == NULL)
2955 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002956
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002957 if (reader->curnode != NULL)
2958 node = reader->curnode;
2959 else
2960 node = reader->node;
2961
2962 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002963 return(0);
2964 if ((reader->state == XML_TEXTREADER_END) ||
2965 (reader->state == XML_TEXTREADER_BACKTRACK))
2966 return(0);
2967 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002968 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002969 while (attr != NULL) {
2970 ret++;
2971 attr = attr->next;
2972 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002973 ns = node->nsDef;
2974 while (ns != NULL) {
2975 ret++;
2976 ns = ns->next;
2977 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002978 return(ret);
2979}
2980
2981/**
2982 * xmlTextReaderNodeType:
2983 * @reader: the xmlTextReaderPtr used
2984 *
2985 * Get the node type of the current node
2986 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002987 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002988 *
2989 * Returns the xmlNodeType of the current node or -1 in case of error
2990 */
2991int
2992xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002993 xmlNodePtr node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002994
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002995 if (reader == NULL)
2996 return(-1);
2997 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00002998 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002999 if (reader->curnode != NULL)
3000 node = reader->curnode;
3001 else
3002 node = reader->node;
3003 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003004 case XML_ELEMENT_NODE:
3005 if ((reader->state == XML_TEXTREADER_END) ||
3006 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00003007 return(XML_READER_TYPE_END_ELEMENT);
3008 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00003009 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003010 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003011 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003012 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003013 if (xmlIsBlankNode(reader->node)) {
3014 if (xmlNodeGetSpacePreserve(reader->node))
3015 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3016 else
3017 return(XML_READER_TYPE_WHITESPACE);
3018 } else {
3019 return(XML_READER_TYPE_TEXT);
3020 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003021 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003022 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003024 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003025 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003026 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003027 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003028 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003029 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003030 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003031 case XML_DOCUMENT_NODE:
3032 case XML_HTML_DOCUMENT_NODE:
3033#ifdef LIBXML_DOCB_ENABLED
3034 case XML_DOCB_DOCUMENT_NODE:
3035#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00003036 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003037 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003038 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003039 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003040 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003041 case XML_DOCUMENT_TYPE_NODE:
3042 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003043 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003044
3045 case XML_ELEMENT_DECL:
3046 case XML_ATTRIBUTE_DECL:
3047 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003048 case XML_XINCLUDE_START:
3049 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003050 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003051 }
3052 return(-1);
3053}
3054
3055/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003056 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003057 * @reader: the xmlTextReaderPtr used
3058 *
3059 * Check if the current node is empty
3060 *
3061 * Returns 1 if empty, 0 if not and -1 in case of error
3062 */
3063int
3064xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3065 if ((reader == NULL) || (reader->node == NULL))
3066 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003067 if (reader->node->type != XML_ELEMENT_NODE)
3068 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003069 if (reader->curnode != NULL)
3070 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003071 if (reader->node->children != NULL)
3072 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003073 if (reader->state == XML_TEXTREADER_END)
3074 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003075 if (reader->doc != NULL)
3076 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003077#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003078 if (reader->in_xinclude > 0)
3079 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003080#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003081 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003082}
3083
3084/**
3085 * xmlTextReaderLocalName:
3086 * @reader: the xmlTextReaderPtr used
3087 *
3088 * The local name of the node.
3089 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003090 * Returns the local name or NULL if not available,
3091 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003092 */
3093xmlChar *
3094xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003095 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003096 if ((reader == NULL) || (reader->node == NULL))
3097 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003098 if (reader->curnode != NULL)
3099 node = reader->curnode;
3100 else
3101 node = reader->node;
3102 if (node->type == XML_NAMESPACE_DECL) {
3103 xmlNsPtr ns = (xmlNsPtr) node;
3104 if (ns->prefix == NULL)
3105 return(xmlStrdup(BAD_CAST "xmlns"));
3106 else
3107 return(xmlStrdup(ns->prefix));
3108 }
3109 if ((node->type != XML_ELEMENT_NODE) &&
3110 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003111 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003112 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003113}
3114
3115/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003116 * xmlTextReaderConstLocalName:
3117 * @reader: the xmlTextReaderPtr used
3118 *
3119 * The local name of the node.
3120 *
3121 * Returns the local name or NULL if not available, the
3122 * string will be deallocated with the reader.
3123 */
3124const xmlChar *
3125xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3126 xmlNodePtr node;
3127 if ((reader == NULL) || (reader->node == NULL))
3128 return(NULL);
3129 if (reader->curnode != NULL)
3130 node = reader->curnode;
3131 else
3132 node = reader->node;
3133 if (node->type == XML_NAMESPACE_DECL) {
3134 xmlNsPtr ns = (xmlNsPtr) node;
3135 if (ns->prefix == NULL)
3136 return(CONSTSTR(BAD_CAST "xmlns"));
3137 else
3138 return(ns->prefix);
3139 }
3140 if ((node->type != XML_ELEMENT_NODE) &&
3141 (node->type != XML_ATTRIBUTE_NODE))
3142 return(xmlTextReaderConstName(reader));
3143 return(node->name);
3144}
3145
3146/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003147 * xmlTextReaderName:
3148 * @reader: the xmlTextReaderPtr used
3149 *
3150 * The qualified name of the node, equal to Prefix :LocalName.
3151 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003152 * Returns the local name or NULL if not available,
3153 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003154 */
3155xmlChar *
3156xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003157 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003158 xmlChar *ret;
3159
3160 if ((reader == NULL) || (reader->node == NULL))
3161 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003162 if (reader->curnode != NULL)
3163 node = reader->curnode;
3164 else
3165 node = reader->node;
3166 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003167 case XML_ELEMENT_NODE:
3168 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003169 if ((node->ns == NULL) ||
3170 (node->ns->prefix == NULL))
3171 return(xmlStrdup(node->name));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003172
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003173 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003174 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003175 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003176 return(ret);
3177 case XML_TEXT_NODE:
3178 return(xmlStrdup(BAD_CAST "#text"));
3179 case XML_CDATA_SECTION_NODE:
3180 return(xmlStrdup(BAD_CAST "#cdata-section"));
3181 case XML_ENTITY_NODE:
3182 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003183 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003184 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003185 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003186 case XML_COMMENT_NODE:
3187 return(xmlStrdup(BAD_CAST "#comment"));
3188 case XML_DOCUMENT_NODE:
3189 case XML_HTML_DOCUMENT_NODE:
3190#ifdef LIBXML_DOCB_ENABLED
3191 case XML_DOCB_DOCUMENT_NODE:
3192#endif
3193 return(xmlStrdup(BAD_CAST "#document"));
3194 case XML_DOCUMENT_FRAG_NODE:
3195 return(xmlStrdup(BAD_CAST "#document-fragment"));
3196 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003197 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003198 case XML_DOCUMENT_TYPE_NODE:
3199 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003200 return(xmlStrdup(node->name));
3201 case XML_NAMESPACE_DECL: {
3202 xmlNsPtr ns = (xmlNsPtr) node;
3203
3204 ret = xmlStrdup(BAD_CAST "xmlns");
3205 if (ns->prefix == NULL)
3206 return(ret);
3207 ret = xmlStrcat(ret, BAD_CAST ":");
3208 ret = xmlStrcat(ret, ns->prefix);
3209 return(ret);
3210 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003211
3212 case XML_ELEMENT_DECL:
3213 case XML_ATTRIBUTE_DECL:
3214 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003215 case XML_XINCLUDE_START:
3216 case XML_XINCLUDE_END:
3217 return(NULL);
3218 }
3219 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003220}
3221
3222/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003223 * xmlTextReaderConstName:
3224 * @reader: the xmlTextReaderPtr used
3225 *
3226 * The qualified name of the node, equal to Prefix :LocalName.
3227 *
3228 * Returns the local name or NULL if not available, the string is
3229 * deallocated with the reader.
3230 */
3231const xmlChar *
3232xmlTextReaderConstName(xmlTextReaderPtr reader) {
3233 xmlNodePtr node;
3234
3235 if ((reader == NULL) || (reader->node == NULL))
3236 return(NULL);
3237 if (reader->curnode != NULL)
3238 node = reader->curnode;
3239 else
3240 node = reader->node;
3241 switch (node->type) {
3242 case XML_ELEMENT_NODE:
3243 case XML_ATTRIBUTE_NODE:
3244 if ((node->ns == NULL) ||
3245 (node->ns->prefix == NULL))
3246 return(node->name);
3247 return(CONSTQSTR(node->ns->prefix, node->name));
3248 case XML_TEXT_NODE:
3249 return(CONSTSTR(BAD_CAST "#text"));
3250 case XML_CDATA_SECTION_NODE:
3251 return(CONSTSTR(BAD_CAST "#cdata-section"));
3252 case XML_ENTITY_NODE:
3253 case XML_ENTITY_REF_NODE:
3254 return(CONSTSTR(node->name));
3255 case XML_PI_NODE:
3256 return(CONSTSTR(node->name));
3257 case XML_COMMENT_NODE:
3258 return(CONSTSTR(BAD_CAST "#comment"));
3259 case XML_DOCUMENT_NODE:
3260 case XML_HTML_DOCUMENT_NODE:
3261#ifdef LIBXML_DOCB_ENABLED
3262 case XML_DOCB_DOCUMENT_NODE:
3263#endif
3264 return(CONSTSTR(BAD_CAST "#document"));
3265 case XML_DOCUMENT_FRAG_NODE:
3266 return(CONSTSTR(BAD_CAST "#document-fragment"));
3267 case XML_NOTATION_NODE:
3268 return(CONSTSTR(node->name));
3269 case XML_DOCUMENT_TYPE_NODE:
3270 case XML_DTD_NODE:
3271 return(CONSTSTR(node->name));
3272 case XML_NAMESPACE_DECL: {
3273 xmlNsPtr ns = (xmlNsPtr) node;
3274
3275 if (ns->prefix == NULL)
3276 return(CONSTSTR(BAD_CAST "xmlns"));
3277 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3278 }
3279
3280 case XML_ELEMENT_DECL:
3281 case XML_ATTRIBUTE_DECL:
3282 case XML_ENTITY_DECL:
3283 case XML_XINCLUDE_START:
3284 case XML_XINCLUDE_END:
3285 return(NULL);
3286 }
3287 return(NULL);
3288}
3289
3290/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003291 * xmlTextReaderPrefix:
3292 * @reader: the xmlTextReaderPtr used
3293 *
3294 * A shorthand reference to the namespace associated with the node.
3295 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003296 * Returns the prefix or NULL if not available,
3297 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003298 */
3299xmlChar *
3300xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003301 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003302 if ((reader == NULL) || (reader->node == NULL))
3303 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003304 if (reader->curnode != NULL)
3305 node = reader->curnode;
3306 else
3307 node = reader->node;
3308 if (node->type == XML_NAMESPACE_DECL) {
3309 xmlNsPtr ns = (xmlNsPtr) node;
3310 if (ns->prefix == NULL)
3311 return(NULL);
3312 return(xmlStrdup(BAD_CAST "xmlns"));
3313 }
3314 if ((node->type != XML_ELEMENT_NODE) &&
3315 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003316 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003317 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003318 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003319 return(NULL);
3320}
3321
3322/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003323 * xmlTextReaderConstPrefix:
3324 * @reader: the xmlTextReaderPtr used
3325 *
3326 * A shorthand reference to the namespace associated with the node.
3327 *
3328 * Returns the prefix or NULL if not available, the string is deallocated
3329 * with the reader.
3330 */
3331const xmlChar *
3332xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3333 xmlNodePtr node;
3334 if ((reader == NULL) || (reader->node == NULL))
3335 return(NULL);
3336 if (reader->curnode != NULL)
3337 node = reader->curnode;
3338 else
3339 node = reader->node;
3340 if (node->type == XML_NAMESPACE_DECL) {
3341 xmlNsPtr ns = (xmlNsPtr) node;
3342 if (ns->prefix == NULL)
3343 return(NULL);
3344 return(CONSTSTR(BAD_CAST "xmlns"));
3345 }
3346 if ((node->type != XML_ELEMENT_NODE) &&
3347 (node->type != XML_ATTRIBUTE_NODE))
3348 return(NULL);
3349 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3350 return(CONSTSTR(node->ns->prefix));
3351 return(NULL);
3352}
3353
3354/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003355 * xmlTextReaderNamespaceUri:
3356 * @reader: the xmlTextReaderPtr used
3357 *
3358 * The URI defining the namespace associated with the node.
3359 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003360 * Returns the namespace URI or NULL if not available,
3361 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003362 */
3363xmlChar *
3364xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003365 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003366 if ((reader == NULL) || (reader->node == NULL))
3367 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003368 if (reader->curnode != NULL)
3369 node = reader->curnode;
3370 else
3371 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003372 if (node->type == XML_NAMESPACE_DECL)
3373 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003374 if ((node->type != XML_ELEMENT_NODE) &&
3375 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003376 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003377 if (node->ns != NULL)
3378 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003379 return(NULL);
3380}
3381
3382/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003383 * xmlTextReaderConstNamespaceUri:
3384 * @reader: the xmlTextReaderPtr used
3385 *
3386 * The URI defining the namespace associated with the node.
3387 *
3388 * Returns the namespace URI or NULL if not available, the string
3389 * will be deallocated with the reader
3390 */
3391const xmlChar *
3392xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3393 xmlNodePtr node;
3394 if ((reader == NULL) || (reader->node == NULL))
3395 return(NULL);
3396 if (reader->curnode != NULL)
3397 node = reader->curnode;
3398 else
3399 node = reader->node;
3400 if (node->type == XML_NAMESPACE_DECL)
3401 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3402 if ((node->type != XML_ELEMENT_NODE) &&
3403 (node->type != XML_ATTRIBUTE_NODE))
3404 return(NULL);
3405 if (node->ns != NULL)
3406 return(CONSTSTR(node->ns->href));
3407 return(NULL);
3408}
3409
3410/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003411 * xmlTextReaderBaseUri:
3412 * @reader: the xmlTextReaderPtr used
3413 *
3414 * The base URI of the node.
3415 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003416 * Returns the base URI or NULL if not available,
3417 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003418 */
3419xmlChar *
3420xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3421 if ((reader == NULL) || (reader->node == NULL))
3422 return(NULL);
3423 return(xmlNodeGetBase(NULL, reader->node));
3424}
3425
3426/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003427 * xmlTextReaderConstBaseUri:
3428 * @reader: the xmlTextReaderPtr used
3429 *
3430 * The base URI of the node.
3431 *
3432 * Returns the base URI or NULL if not available, the string
3433 * will be deallocated with the reader
3434 */
3435const xmlChar *
3436xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3437 xmlChar *tmp;
3438 const xmlChar *ret;
3439
3440 if ((reader == NULL) || (reader->node == NULL))
3441 return(NULL);
3442 tmp = xmlNodeGetBase(NULL, reader->node);
3443 if (tmp == NULL)
3444 return(NULL);
3445 ret = CONSTSTR(tmp);
3446 xmlFree(tmp);
3447 return(ret);
3448}
3449
3450/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003451 * xmlTextReaderDepth:
3452 * @reader: the xmlTextReaderPtr used
3453 *
3454 * The depth of the node in the tree.
3455 *
3456 * Returns the depth or -1 in case of error
3457 */
3458int
3459xmlTextReaderDepth(xmlTextReaderPtr reader) {
3460 if (reader == NULL)
3461 return(-1);
3462 if (reader->node == NULL)
3463 return(0);
3464
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003465 if (reader->curnode != NULL) {
3466 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3467 (reader->curnode->type == XML_NAMESPACE_DECL))
3468 return(reader->depth + 1);
3469 return(reader->depth + 2);
3470 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003471 return(reader->depth);
3472}
3473
3474/**
3475 * xmlTextReaderHasAttributes:
3476 * @reader: the xmlTextReaderPtr used
3477 *
3478 * Whether the node has attributes.
3479 *
3480 * Returns 1 if true, 0 if false, and -1 in case or error
3481 */
3482int
3483xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003484 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003485 if (reader == NULL)
3486 return(-1);
3487 if (reader->node == NULL)
3488 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003489 if (reader->curnode != NULL)
3490 node = reader->curnode;
3491 else
3492 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003493
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003494 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003495 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003496 return(1);
3497 /* TODO: handle the xmlDecl */
3498 return(0);
3499}
3500
3501/**
3502 * xmlTextReaderHasValue:
3503 * @reader: the xmlTextReaderPtr used
3504 *
3505 * Whether the node can have a text value.
3506 *
3507 * Returns 1 if true, 0 if false, and -1 in case or error
3508 */
3509int
3510xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003511 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003512 if (reader == NULL)
3513 return(-1);
3514 if (reader->node == NULL)
3515 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003516 if (reader->curnode != NULL)
3517 node = reader->curnode;
3518 else
3519 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003520
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003521 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003522 case XML_ATTRIBUTE_NODE:
3523 case XML_TEXT_NODE:
3524 case XML_CDATA_SECTION_NODE:
3525 case XML_PI_NODE:
3526 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003527 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003528 return(1);
3529 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003530 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003531 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003532 return(0);
3533}
3534
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003535/**
3536 * xmlTextReaderValue:
3537 * @reader: the xmlTextReaderPtr used
3538 *
3539 * Provides the text value of the node if present
3540 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003541 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003542 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003543 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003544xmlChar *
3545xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003546 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003547 if (reader == NULL)
3548 return(NULL);
3549 if (reader->node == NULL)
3550 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003551 if (reader->curnode != NULL)
3552 node = reader->curnode;
3553 else
3554 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003555
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003556 switch (node->type) {
3557 case XML_NAMESPACE_DECL:
3558 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003559 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003560 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003561
3562 if (attr->parent != NULL)
3563 return (xmlNodeListGetString
3564 (attr->parent->doc, attr->children, 1));
3565 else
3566 return (xmlNodeListGetString(NULL, attr->children, 1));
3567 break;
3568 }
3569 case XML_TEXT_NODE:
3570 case XML_CDATA_SECTION_NODE:
3571 case XML_PI_NODE:
3572 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003573 if (node->content != NULL)
3574 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003575 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003576 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003577 }
3578 return(NULL);
3579}
3580
3581/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003582 * xmlTextReaderConstValue:
3583 * @reader: the xmlTextReaderPtr used
3584 *
3585 * Provides the text value of the node if present
3586 *
3587 * Returns the string or NULL if not available. The result will be
3588 * deallocated on the next Read() operation.
3589 */
3590const xmlChar *
3591xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3592 xmlNodePtr node;
3593 if (reader == NULL)
3594 return(NULL);
3595 if (reader->node == NULL)
3596 return(NULL);
3597 if (reader->curnode != NULL)
3598 node = reader->curnode;
3599 else
3600 node = reader->node;
3601
3602 switch (node->type) {
3603 case XML_NAMESPACE_DECL:
3604 return(((xmlNsPtr) node)->href);
3605 case XML_ATTRIBUTE_NODE:{
3606 xmlAttrPtr attr = (xmlAttrPtr) node;
3607
3608 if ((attr->children != NULL) &&
3609 (attr->children->type == XML_TEXT_NODE) &&
3610 (attr->children->next == NULL))
3611 return(attr->children->content);
3612 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003613 if (reader->buffer == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08003614 reader->buffer = xmlBufCreateSize(100);
3615 if (reader->buffer == NULL) {
3616 xmlGenericError(xmlGenericErrorContext,
3617 "xmlTextReaderSetup : malloc failed\n");
3618 return (NULL);
3619 }
3620 } else
3621 xmlBufEmpty(reader->buffer);
3622 xmlBufGetNodeContent(reader->buffer, node);
3623 return(xmlBufContent(reader->buffer));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003624 }
3625 break;
3626 }
3627 case XML_TEXT_NODE:
3628 case XML_CDATA_SECTION_NODE:
3629 case XML_PI_NODE:
3630 case XML_COMMENT_NODE:
3631 return(node->content);
3632 default:
3633 break;
3634 }
3635 return(NULL);
3636}
3637
3638/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003639 * xmlTextReaderIsDefault:
3640 * @reader: the xmlTextReaderPtr used
3641 *
3642 * Whether an Attribute node was generated from the default value
3643 * defined in the DTD or schema.
3644 *
3645 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3646 */
3647int
3648xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3649 if (reader == NULL)
3650 return(-1);
3651 return(0);
3652}
3653
3654/**
3655 * xmlTextReaderQuoteChar:
3656 * @reader: the xmlTextReaderPtr used
3657 *
3658 * The quotation mark character used to enclose the value of an attribute.
3659 *
3660 * Returns " or ' and -1 in case of error
3661 */
3662int
3663xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3664 if (reader == NULL)
3665 return(-1);
3666 /* TODO maybe lookup the attribute value for " first */
3667 return((int) '"');
3668}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003669
3670/**
3671 * xmlTextReaderXmlLang:
3672 * @reader: the xmlTextReaderPtr used
3673 *
3674 * The xml:lang scope within which the node resides.
3675 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003676 * Returns the xml:lang value or NULL if none exists.,
3677 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003678 */
3679xmlChar *
3680xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3681 if (reader == NULL)
3682 return(NULL);
3683 if (reader->node == NULL)
3684 return(NULL);
3685 return(xmlNodeGetLang(reader->node));
3686}
3687
Daniel Veillard67df8092002-12-16 22:04:11 +00003688/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003689 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003690 * @reader: the xmlTextReaderPtr used
3691 *
3692 * The xml:lang scope within which the node resides.
3693 *
3694 * Returns the xml:lang value or NULL if none exists.
3695 */
3696const xmlChar *
3697xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3698 xmlChar *tmp;
3699 const xmlChar *ret;
3700
3701 if (reader == NULL)
3702 return(NULL);
3703 if (reader->node == NULL)
3704 return(NULL);
3705 tmp = xmlNodeGetLang(reader->node);
3706 if (tmp == NULL)
3707 return(NULL);
3708 ret = CONSTSTR(tmp);
3709 xmlFree(tmp);
3710 return(ret);
3711}
3712
3713/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003714 * xmlTextReaderConstString:
3715 * @reader: the xmlTextReaderPtr used
3716 * @str: the string to intern.
3717 *
3718 * Get an interned string from the reader, allows for example to
3719 * speedup string name comparisons
3720 *
3721 * Returns an interned copy of the string or NULL in case of error. The
3722 * string will be deallocated with the reader.
3723 */
3724const xmlChar *
3725xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3726 if (reader == NULL)
3727 return(NULL);
3728 return(CONSTSTR(str));
3729}
3730
3731/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003732 * xmlTextReaderNormalization:
3733 * @reader: the xmlTextReaderPtr used
3734 *
3735 * The value indicating whether to normalize white space and attribute values.
3736 * Since attribute value and end of line normalizations are a MUST in the XML
3737 * specification only the value true is accepted. The broken bahaviour of
3738 * accepting out of range character entities like &#0; is of course not
3739 * supported either.
3740 *
3741 * Returns 1 or -1 in case of error.
3742 */
3743int
3744xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3745 if (reader == NULL)
3746 return(-1);
3747 return(1);
3748}
3749
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003750/************************************************************************
3751 * *
3752 * Extensions to the base APIs *
3753 * *
3754 ************************************************************************/
3755
3756/**
3757 * xmlTextReaderSetParserProp:
3758 * @reader: the xmlTextReaderPtr used
3759 * @prop: the xmlParserProperties to set
3760 * @value: usually 0 or 1 to (de)activate it
3761 *
3762 * Change the parser processing behaviour by changing some of its internal
3763 * properties. Note that some properties can only be changed before any
3764 * read has been done.
3765 *
3766 * Returns 0 if the call was successful, or -1 in case of error
3767 */
3768int
3769xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3770 xmlParserProperties p = (xmlParserProperties) prop;
3771 xmlParserCtxtPtr ctxt;
3772
3773 if ((reader == NULL) || (reader->ctxt == NULL))
3774 return(-1);
3775 ctxt = reader->ctxt;
3776
3777 switch (p) {
3778 case XML_PARSER_LOADDTD:
3779 if (value != 0) {
3780 if (ctxt->loadsubset == 0) {
3781 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3782 return(-1);
3783 ctxt->loadsubset = XML_DETECT_IDS;
3784 }
3785 } else {
3786 ctxt->loadsubset = 0;
3787 }
3788 return(0);
3789 case XML_PARSER_DEFAULTATTRS:
3790 if (value != 0) {
3791 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3792 } else {
3793 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3794 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3795 }
3796 return(0);
3797 case XML_PARSER_VALIDATE:
3798 if (value != 0) {
3799 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003800 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003801 } else {
3802 ctxt->validate = 0;
3803 }
3804 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003805 case XML_PARSER_SUBST_ENTITIES:
3806 if (value != 0) {
3807 ctxt->replaceEntities = 1;
3808 } else {
3809 ctxt->replaceEntities = 0;
3810 }
3811 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003812 }
3813 return(-1);
3814}
3815
3816/**
3817 * xmlTextReaderGetParserProp:
3818 * @reader: the xmlTextReaderPtr used
3819 * @prop: the xmlParserProperties to get
3820 *
3821 * Read the parser internal property.
3822 *
3823 * Returns the value, usually 0 or 1, or -1 in case of error.
3824 */
3825int
3826xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3827 xmlParserProperties p = (xmlParserProperties) prop;
3828 xmlParserCtxtPtr ctxt;
3829
3830 if ((reader == NULL) || (reader->ctxt == NULL))
3831 return(-1);
3832 ctxt = reader->ctxt;
3833
3834 switch (p) {
3835 case XML_PARSER_LOADDTD:
3836 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3837 return(1);
3838 return(0);
3839 case XML_PARSER_DEFAULTATTRS:
3840 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3841 return(1);
3842 return(0);
3843 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003844 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003845 case XML_PARSER_SUBST_ENTITIES:
3846 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003847 }
3848 return(-1);
3849}
3850
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003851
Daniel Veillarde18fc182002-12-28 22:56:33 +00003852/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003853 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003854 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003855 *
3856 * Provide the line number of the current parsing point.
3857 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003858 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003859 */
3860int
3861xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3862{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003863 if ((reader == NULL) || (reader->ctxt == NULL) ||
3864 (reader->ctxt->input == NULL)) {
3865 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003866 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003867 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003868}
3869
3870/**
3871 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003872 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003873 *
3874 * Provide the column number of the current parsing point.
3875 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003876 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003877 */
3878int
3879xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3880{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003881 if ((reader == NULL) || (reader->ctxt == NULL) ||
3882 (reader->ctxt->input == NULL)) {
3883 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003884 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003885 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003886}
3887
3888/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003889 * xmlTextReaderCurrentNode:
3890 * @reader: the xmlTextReaderPtr used
3891 *
3892 * Hacking interface allowing to get the xmlNodePtr correponding to the
3893 * current node being accessed by the xmlTextReader. This is dangerous
3894 * because the underlying node may be destroyed on the next Reads.
3895 *
3896 * Returns the xmlNodePtr or NULL in case of error.
3897 */
3898xmlNodePtr
3899xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3900 if (reader == NULL)
3901 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003902
Daniel Veillarde18fc182002-12-28 22:56:33 +00003903 if (reader->curnode != NULL)
3904 return(reader->curnode);
3905 return(reader->node);
3906}
3907
3908/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003909 * xmlTextReaderPreserve:
3910 * @reader: the xmlTextReaderPtr used
3911 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003912 * This tells the XML Reader to preserve the current node.
3913 * The caller must also use xmlTextReaderCurrentDoc() to
3914 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003915 *
3916 * Returns the xmlNodePtr or NULL in case of error.
3917 */
3918xmlNodePtr
3919xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3920 xmlNodePtr cur, parent;
3921
3922 if (reader == NULL)
3923 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003924
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003925 if (reader->curnode != NULL)
3926 cur = reader->curnode;
3927 else
3928 cur = reader->node;
3929 if (cur == NULL)
3930 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003931
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003932 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003933 cur->extra |= NODE_IS_PRESERVED;
3934 cur->extra |= NODE_IS_SPRESERVED;
3935 }
3936 reader->preserves++;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003937
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003938 parent = cur->parent;;
3939 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003940 if (parent->type == XML_ELEMENT_NODE)
3941 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003942 parent = parent->parent;
3943 }
3944 return(cur);
3945}
3946
Daniel Veillard1e906612003-12-05 14:57:46 +00003947#ifdef LIBXML_PATTERN_ENABLED
3948/**
3949 * xmlTextReaderPreservePattern:
3950 * @reader: the xmlTextReaderPtr used
3951 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003952 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003953 *
Daniel Veillard1e906612003-12-05 14:57:46 +00003954 * This tells the XML Reader to preserve all nodes matched by the
3955 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3956 * keep an handle on the resulting document once parsing has finished
3957 *
3958 * Returns a positive number in case of success and -1 in case of error
3959 */
3960int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003961xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3962 const xmlChar **namespaces)
3963{
Daniel Veillard1e906612003-12-05 14:57:46 +00003964 xmlPatternPtr comp;
3965
3966 if ((reader == NULL) || (pattern == NULL))
3967 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003968
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003969 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003970 if (comp == NULL)
3971 return(-1);
3972
3973 if (reader->patternMax <= 0) {
3974 reader->patternMax = 4;
3975 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3976 sizeof(reader->patternTab[0]));
3977 if (reader->patternTab == NULL) {
3978 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3979 return (-1);
3980 }
3981 }
3982 if (reader->patternNr >= reader->patternMax) {
3983 xmlPatternPtr *tmp;
3984 reader->patternMax *= 2;
3985 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3986 reader->patternMax *
3987 sizeof(reader->patternTab[0]));
3988 if (tmp == NULL) {
3989 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3990 reader->patternMax /= 2;
3991 return (-1);
3992 }
3993 reader->patternTab = tmp;
3994 }
3995 reader->patternTab[reader->patternNr] = comp;
3996 return(reader->patternNr++);
3997}
3998#endif
3999
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004000/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00004001 * xmlTextReaderCurrentDoc:
4002 * @reader: the xmlTextReaderPtr used
4003 *
4004 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004005 * current document being accessed by the xmlTextReader.
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004006 * NOTE: as a result of this call, the reader will not destroy the
4007 * associated XML document and calling xmlFreeDoc() on the result
4008 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00004009 *
4010 * Returns the xmlDocPtr or NULL in case of error.
4011 */
4012xmlDocPtr
4013xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004014 if (reader == NULL)
4015 return(NULL);
4016 if (reader->doc != NULL)
4017 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00004018 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00004019 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004020
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004021 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00004022 return(reader->ctxt->myDoc);
4023}
4024
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004025#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004026static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004027
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004028static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004029xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4030
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004031static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004032xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4033
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004034static void XMLCDECL
4035xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004036{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004037 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004038
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004039 char *str;
4040
4041 va_list ap;
4042
4043 va_start(ap, msg);
4044 str = xmlTextReaderBuildMessage(msg, ap);
4045 if (!reader->errorFunc) {
4046 xmlTextReaderValidityError(ctx, "%s", str);
4047 } else {
4048 reader->errorFunc(reader->errorFuncArg, str,
4049 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4050 NULL /* locator */ );
4051 }
4052 if (str != NULL)
4053 xmlFree(str);
4054 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004055}
4056
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004057static void XMLCDECL
4058xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004059{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004060 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004061
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004062 char *str;
4063
4064 va_list ap;
4065
4066 va_start(ap, msg);
4067 str = xmlTextReaderBuildMessage(msg, ap);
4068 if (!reader->errorFunc) {
4069 xmlTextReaderValidityWarning(ctx, "%s", str);
4070 } else {
4071 reader->errorFunc(reader->errorFuncArg, str,
4072 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4073 NULL /* locator */ );
4074 }
4075 if (str != NULL)
4076 xmlFree(str);
4077 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004078}
4079
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004080static void
4081 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004082
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004083static void
4084xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004085{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004086 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004087
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004088 if (reader->sErrorFunc) {
4089 reader->sErrorFunc(reader->errorFuncArg, error);
4090 } else {
4091 xmlTextReaderStructuredError(reader, error);
4092 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004093}
Daniel Veillardf4e55762003-04-15 23:32:22 +00004094/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004095 * xmlTextReaderRelaxNGSetSchema:
4096 * @reader: the xmlTextReaderPtr used
4097 * @schema: a precompiled RelaxNG schema
4098 *
4099 * Use RelaxNG to validate the document as it is processed.
4100 * Activation is only possible before the first Read().
4101 * if @schema is NULL, then RelaxNG validation is desactivated.
4102 @ The @schema should not be freed until the reader is deallocated
4103 * or its use has been deactivated.
4104 *
4105 * Returns 0 in case the RelaxNG validation could be (des)activated and
4106 * -1 in case of error.
4107 */
4108int
4109xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004110 if (reader == NULL)
4111 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004112 if (schema == NULL) {
4113 if (reader->rngSchemas != NULL) {
4114 xmlRelaxNGFree(reader->rngSchemas);
4115 reader->rngSchemas = NULL;
4116 }
4117 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004118 if (! reader->rngPreserveCtxt)
4119 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004120 reader->rngValidCtxt = NULL;
4121 }
Noam Postavsky15794992012-03-19 16:08:16 +08004122 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004123 return(0);
4124 }
4125 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4126 return(-1);
4127 if (reader->rngSchemas != NULL) {
4128 xmlRelaxNGFree(reader->rngSchemas);
4129 reader->rngSchemas = NULL;
4130 }
4131 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004132 if (! reader->rngPreserveCtxt)
4133 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004134 reader->rngValidCtxt = NULL;
4135 }
Noam Postavsky15794992012-03-19 16:08:16 +08004136 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004137 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4138 if (reader->rngValidCtxt == NULL)
4139 return(-1);
4140 if (reader->errorFunc != NULL) {
4141 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004142 xmlTextReaderValidityErrorRelay,
4143 xmlTextReaderValidityWarningRelay,
4144 reader);
4145 }
4146 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004147 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004148 xmlTextReaderValidityStructuredRelay,
4149 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004150 }
4151 reader->rngValidErrors = 0;
4152 reader->rngFullNode = NULL;
4153 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4154 return(0);
4155}
4156
4157/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004158 * xmlTextReaderSetSchema:
4159 * @reader: the xmlTextReaderPtr used
4160 * @schema: a precompiled Schema schema
4161 *
4162 * Use XSD Schema to validate the document as it is processed.
4163 * Activation is only possible before the first Read().
4164 * if @schema is NULL, then Schema validation is desactivated.
4165 @ The @schema should not be freed until the reader is deallocated
4166 * or its use has been deactivated.
4167 *
4168 * Returns 0 in case the Schema validation could be (des)activated and
4169 * -1 in case of error.
4170 */
4171int
4172xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4173 if (reader == NULL)
4174 return(-1);
4175 if (schema == NULL) {
4176 if (reader->xsdPlug != NULL) {
4177 xmlSchemaSAXUnplug(reader->xsdPlug);
4178 reader->xsdPlug = NULL;
4179 }
4180 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004181 if (! reader->xsdPreserveCtxt)
4182 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004183 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004184 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004185 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004186 if (reader->xsdSchemas != NULL) {
4187 xmlSchemaFree(reader->xsdSchemas);
4188 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004189 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004190 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004191 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004192 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4193 return(-1);
4194 if (reader->xsdPlug != NULL) {
4195 xmlSchemaSAXUnplug(reader->xsdPlug);
4196 reader->xsdPlug = NULL;
4197 }
4198 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004199 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004200 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004201 reader->xsdValidCtxt = NULL;
4202 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004203 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004204 if (reader->xsdSchemas != NULL) {
4205 xmlSchemaFree(reader->xsdSchemas);
4206 reader->xsdSchemas = NULL;
4207 }
4208 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4209 if (reader->xsdValidCtxt == NULL) {
4210 xmlSchemaFree(reader->xsdSchemas);
4211 reader->xsdSchemas = NULL;
4212 return(-1);
4213 }
4214 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4215 &(reader->ctxt->sax),
4216 &(reader->ctxt->userData));
4217 if (reader->xsdPlug == NULL) {
4218 xmlSchemaFree(reader->xsdSchemas);
4219 reader->xsdSchemas = NULL;
4220 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4221 reader->xsdValidCtxt = NULL;
4222 return(-1);
4223 }
4224 if (reader->errorFunc != NULL) {
4225 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004226 xmlTextReaderValidityErrorRelay,
4227 xmlTextReaderValidityWarningRelay,
4228 reader);
4229 }
4230 if (reader->sErrorFunc != NULL) {
4231 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4232 xmlTextReaderValidityStructuredRelay,
4233 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004234 }
4235 reader->xsdValidErrors = 0;
4236 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4237 return(0);
4238}
4239
4240/**
Noam Postavsky15794992012-03-19 16:08:16 +08004241 * xmlTextReaderRelaxNGValidateInternal:
Daniel Veillardf4e55762003-04-15 23:32:22 +00004242 * @reader: the xmlTextReaderPtr used
4243 * @rng: the path to a RelaxNG schema or NULL
Noam Postavsky15794992012-03-19 16:08:16 +08004244 * @ctxt: the RelaxNG schema validation context or NULL
4245 * @options: options (not yet used)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004246 *
4247 * Use RelaxNG to validate the document as it is processed.
4248 * Activation is only possible before the first Read().
Noam Postavsky15794992012-03-19 16:08:16 +08004249 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004250 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004251 * Returns 0 in case the RelaxNG validation could be (de)activated and
Noam Postavsky15794992012-03-19 16:08:16 +08004252 * -1 in case of error.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004253 */
Noam Postavsky15794992012-03-19 16:08:16 +08004254static int
4255xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4256 const char *rng,
4257 xmlRelaxNGValidCtxtPtr ctxt,
4258 int options ATTRIBUTE_UNUSED)
4259{
Daniel Veillardf4e55762003-04-15 23:32:22 +00004260 if (reader == NULL)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004261 return(-1);
Noam Postavsky15794992012-03-19 16:08:16 +08004262
4263 if ((rng != NULL) && (ctxt != NULL))
4264 return (-1);
4265
4266 if (((rng != NULL) || (ctxt != NULL)) &&
4267 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4268 (reader->ctxt == NULL)))
4269 return(-1);
4270
4271 /* Cleanup previous validation stuff. */
4272 if (reader->rngValidCtxt != NULL) {
4273 if ( !reader->rngPreserveCtxt)
4274 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4275 reader->rngValidCtxt = NULL;
4276 }
4277 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004278 if (reader->rngSchemas != NULL) {
4279 xmlRelaxNGFree(reader->rngSchemas);
4280 reader->rngSchemas = NULL;
4281 }
Noam Postavsky15794992012-03-19 16:08:16 +08004282
4283 if ((rng == NULL) && (ctxt == NULL)) {
4284 /* We just want to deactivate the validation, so get out. */
4285 return(0);
Daniel Veillard33300b42003-04-17 09:09:19 +00004286 }
Noam Postavsky15794992012-03-19 16:08:16 +08004287
4288
4289 if (rng != NULL) {
4290 xmlRelaxNGParserCtxtPtr pctxt;
4291 /* Parse the schema and create validation environment. */
4292
4293 pctxt = xmlRelaxNGNewParserCtxt(rng);
4294 if (reader->errorFunc != NULL) {
4295 xmlRelaxNGSetParserErrors(pctxt,
4296 xmlTextReaderValidityErrorRelay,
4297 xmlTextReaderValidityWarningRelay,
4298 reader);
4299 }
4300 if (reader->sErrorFunc != NULL) {
4301 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4302 xmlTextReaderValidityStructuredRelay,
4303 reader);
4304 }
4305 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4306 xmlRelaxNGFreeParserCtxt(pctxt);
4307 if (reader->rngSchemas == NULL)
4308 return(-1);
4309 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4310 if (reader->rngValidCtxt == NULL) {
4311 xmlRelaxNGFree(reader->rngSchemas);
4312 reader->rngSchemas = NULL;
4313 return(-1);
4314 }
4315 } else {
4316 /* Use the given validation context. */
4317 reader->rngValidCtxt = ctxt;
4318 reader->rngPreserveCtxt = 1;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004319 }
Noam Postavsky15794992012-03-19 16:08:16 +08004320 /*
4321 * Redirect the validation context's error channels to use
4322 * the reader channels.
4323 * TODO: In case the user provides the validation context we
4324 * could make this redirection optional.
4325 */
Daniel Veillardf4e55762003-04-15 23:32:22 +00004326 if (reader->errorFunc != NULL) {
4327 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004328 xmlTextReaderValidityErrorRelay,
4329 xmlTextReaderValidityWarningRelay,
4330 reader);
4331 }
4332 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004333 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004334 xmlTextReaderValidityStructuredRelay,
4335 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004336 }
4337 reader->rngValidErrors = 0;
4338 reader->rngFullNode = NULL;
4339 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4340 return(0);
4341}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004342
4343/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004344 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004345 * @reader: the xmlTextReaderPtr used
4346 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004347 * @ctxt: the XML Schema validation context or NULL
4348 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004349 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004350 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004351 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004352 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004353 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004354 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004355 * -1 in case of error.
4356 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004357static int
4358xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4359 const char *xsd,
4360 xmlSchemaValidCtxtPtr ctxt,
4361 int options ATTRIBUTE_UNUSED)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004362{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004363 if (reader == NULL)
4364 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004365
4366 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004367 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004368
4369 if (((xsd != NULL) || (ctxt != NULL)) &&
4370 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4371 (reader->ctxt == NULL)))
4372 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004373
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004374 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004375 if (reader->xsdPlug != NULL) {
4376 xmlSchemaSAXUnplug(reader->xsdPlug);
4377 reader->xsdPlug = NULL;
4378 }
4379 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004380 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004381 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004382 reader->xsdValidCtxt = NULL;
4383 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004384 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004385 if (reader->xsdSchemas != NULL) {
4386 xmlSchemaFree(reader->xsdSchemas);
4387 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004388 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004389
4390 if ((xsd == NULL) && (ctxt == NULL)) {
4391 /* We just want to deactivate the validation, so get out. */
4392 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004393 }
4394
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004395 if (xsd != NULL) {
4396 xmlSchemaParserCtxtPtr pctxt;
4397 /* Parse the schema and create validation environment. */
4398 pctxt = xmlSchemaNewParserCtxt(xsd);
4399 if (reader->errorFunc != NULL) {
4400 xmlSchemaSetParserErrors(pctxt,
4401 xmlTextReaderValidityErrorRelay,
4402 xmlTextReaderValidityWarningRelay,
4403 reader);
4404 }
4405 reader->xsdSchemas = xmlSchemaParse(pctxt);
4406 xmlSchemaFreeParserCtxt(pctxt);
4407 if (reader->xsdSchemas == NULL)
4408 return(-1);
4409 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4410 if (reader->xsdValidCtxt == NULL) {
4411 xmlSchemaFree(reader->xsdSchemas);
4412 reader->xsdSchemas = NULL;
4413 return(-1);
4414 }
4415 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4416 &(reader->ctxt->sax),
4417 &(reader->ctxt->userData));
4418 if (reader->xsdPlug == NULL) {
4419 xmlSchemaFree(reader->xsdSchemas);
4420 reader->xsdSchemas = NULL;
4421 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4422 reader->xsdValidCtxt = NULL;
4423 return(-1);
4424 }
4425 } else {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004426 /* Use the given validation context. */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004427 reader->xsdValidCtxt = ctxt;
4428 reader->xsdPreserveCtxt = 1;
4429 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4430 &(reader->ctxt->sax),
4431 &(reader->ctxt->userData));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004432 if (reader->xsdPlug == NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004433 reader->xsdValidCtxt = NULL;
4434 reader->xsdPreserveCtxt = 0;
4435 return(-1);
4436 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004437 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004438 /*
4439 * Redirect the validation context's error channels to use
4440 * the reader channels.
4441 * TODO: In case the user provides the validation context we
4442 * could make this redirection optional.
4443 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004444 if (reader->errorFunc != NULL) {
4445 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004446 xmlTextReaderValidityErrorRelay,
4447 xmlTextReaderValidityWarningRelay,
4448 reader);
4449 }
4450 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004451 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004452 xmlTextReaderValidityStructuredRelay,
4453 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004454 }
4455 reader->xsdValidErrors = 0;
4456 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4457 return(0);
4458}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004459
4460/**
4461 * xmlTextReaderSchemaValidateCtxt:
4462 * @reader: the xmlTextReaderPtr used
4463 * @ctxt: the XML Schema validation context or NULL
4464 * @options: options (not used yet)
4465 *
4466 * Use W3C XSD schema context to validate the document as it is processed.
4467 * Activation is only possible before the first Read().
4468 * If @ctxt is NULL, then XML Schema validation is deactivated.
4469 *
4470 * Returns 0 in case the schemas validation could be (de)activated and
4471 * -1 in case of error.
4472 */
4473int
4474xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4475 xmlSchemaValidCtxtPtr ctxt,
4476 int options)
4477{
4478 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4479}
4480
4481/**
4482 * xmlTextReaderSchemaValidate:
4483 * @reader: the xmlTextReaderPtr used
4484 * @xsd: the path to a W3C XSD schema or NULL
4485 *
4486 * Use W3C XSD schema to validate the document as it is processed.
4487 * Activation is only possible before the first Read().
4488 * If @xsd is NULL, then XML Schema validation is deactivated.
4489 *
4490 * Returns 0 in case the schemas validation could be (de)activated and
4491 * -1 in case of error.
4492 */
4493int
4494xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4495{
4496 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4497}
Noam Postavsky15794992012-03-19 16:08:16 +08004498
4499/**
4500 * xmlTextReaderRelaxNGValidateCtxt:
4501 * @reader: the xmlTextReaderPtr used
4502 * @ctxt: the RelaxNG schema validation context or NULL
4503 * @options: options (not used yet)
4504 *
4505 * Use RelaxNG schema context to validate the document as it is processed.
4506 * Activation is only possible before the first Read().
4507 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4508 *
4509 * Returns 0 in case the schemas validation could be (de)activated and
4510 * -1 in case of error.
4511 */
4512int
4513xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4514 xmlRelaxNGValidCtxtPtr ctxt,
4515 int options)
4516{
4517 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4518}
4519
4520/**
4521 * xmlTextReaderRelaxNGValidate:
4522 * @reader: the xmlTextReaderPtr used
4523 * @rng: the path to a RelaxNG schema or NULL
4524 *
4525 * Use RelaxNG schema to validate the document as it is processed.
4526 * Activation is only possible before the first Read().
4527 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4528 *
4529 * Returns 0 in case the schemas validation could be (de)activated and
4530 * -1 in case of error.
4531 */
4532int
4533xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4534{
4535 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4536}
4537
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004538#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004539
Daniel Veillarde2811272004-10-19 09:04:23 +00004540/**
4541 * xmlTextReaderIsNamespaceDecl:
4542 * @reader: the xmlTextReaderPtr used
4543 *
4544 * Determine whether the current node is a namespace declaration
4545 * rather than a regular attribute.
4546 *
4547 * Returns 1 if the current node is a namespace declaration, 0 if it
4548 * is a regular attribute or other type of node, or -1 in case of
4549 * error.
4550 */
4551int
4552xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4553 xmlNodePtr node;
4554 if (reader == NULL)
4555 return(-1);
4556 if (reader->node == NULL)
4557 return(-1);
4558 if (reader->curnode != NULL)
4559 node = reader->curnode;
4560 else
4561 node = reader->node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004562
Daniel Veillarde2811272004-10-19 09:04:23 +00004563 if (XML_NAMESPACE_DECL == node->type)
4564 return(1);
4565 else
4566 return(0);
4567}
4568
4569/**
4570 * xmlTextReaderConstXmlVersion:
4571 * @reader: the xmlTextReaderPtr used
4572 *
4573 * Determine the XML version of the document being read.
4574 *
4575 * Returns a string containing the XML version of the document or NULL
4576 * in case of error. The string is deallocated with the reader.
4577 */
4578const xmlChar *
4579xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4580 xmlDocPtr doc = NULL;
4581 if (reader == NULL)
4582 return(NULL);
4583 if (reader->doc != NULL)
4584 doc = reader->doc;
4585 else if (reader->ctxt != NULL)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004586 doc = reader->ctxt->myDoc;
Daniel Veillarde2811272004-10-19 09:04:23 +00004587 if (doc == NULL)
4588 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004589
Daniel Veillarde2811272004-10-19 09:04:23 +00004590 if (doc->version == NULL)
4591 return(NULL);
4592 else
4593 return(CONSTSTR(doc->version));
4594}
4595
4596/**
4597 * xmlTextReaderStandalone:
4598 * @reader: the xmlTextReaderPtr used
4599 *
4600 * Determine the standalone status of the document being read.
4601 *
4602 * Returns 1 if the document was declared to be standalone, 0 if it
4603 * was declared to be not standalone, or -1 if the document did not
4604 * specify its standalone status or in case of error.
4605 */
4606int
4607xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4608 xmlDocPtr doc = NULL;
4609 if (reader == NULL)
4610 return(-1);
4611 if (reader->doc != NULL)
4612 doc = reader->doc;
4613 else if (reader->ctxt != NULL)
4614 doc = reader->ctxt->myDoc;
4615 if (doc == NULL)
4616 return(-1);
4617
4618 return(doc->standalone);
4619}
4620
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004621/************************************************************************
4622 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004623 * Error Handling Extensions *
4624 * *
4625 ************************************************************************/
4626
4627/* helper to build a xmlMalloc'ed string from a format and va_list */
4628static char *
4629xmlTextReaderBuildMessage(const char *msg, va_list ap) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004630 int size = 0;
Daniel Veillard26f70262003-01-16 22:45:08 +00004631 int chars;
4632 char *larger;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004633 char *str = NULL;
4634 va_list aq;
Daniel Veillard26f70262003-01-16 22:45:08 +00004635
4636 while (1) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004637 VA_COPY(aq, ap);
4638 chars = vsnprintf(str, size, msg, aq);
4639 va_end(aq);
4640 if (chars < 0) {
4641 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004642 if (str)
4643 xmlFree(str);
4644 return NULL;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004645 }
4646 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
Daniel Veillard26f70262003-01-16 22:45:08 +00004647 break;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004648 if (chars < MAX_ERR_MSG_SIZE)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004649 size = chars + 1;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004650 else
4651 size = MAX_ERR_MSG_SIZE;
Daniel Veillard26f70262003-01-16 22:45:08 +00004652 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4653 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004654 if (str)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004655 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004656 return NULL;
4657 }
4658 str = larger;
4659 }
4660
4661 return str;
4662}
4663
Daniel Veillard417be3a2003-01-20 21:26:34 +00004664/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004665 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004666 * @locator: the xmlTextReaderLocatorPtr used
4667 *
4668 * Obtain the line number for the given locator.
4669 *
4670 * Returns the line number or -1 in case of error.
4671 */
4672int
4673xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4674 /* we know that locator is a xmlParserCtxtPtr */
4675 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4676 int ret = -1;
4677
Daniel Veillardce682bc2004-11-05 17:22:25 +00004678 if (locator == NULL)
4679 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004680 if (ctx->node != NULL) {
4681 ret = xmlGetLineNo(ctx->node);
4682 }
4683 else {
4684 /* inspired from error.c */
4685 xmlParserInputPtr input;
4686 input = ctx->input;
4687 if ((input->filename == NULL) && (ctx->inputNr > 1))
4688 input = ctx->inputTab[ctx->inputNr - 2];
4689 if (input != NULL) {
4690 ret = input->line;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004691 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004692 else {
4693 ret = -1;
4694 }
4695 }
4696
4697 return ret;
4698}
4699
4700/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004701 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004702 * @locator: the xmlTextReaderLocatorPtr used
4703 *
4704 * Obtain the base URI for the given locator.
4705 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004706 * Returns the base URI or NULL in case of error,
4707 * if non NULL it need to be freed by the caller.
Daniel Veillard417be3a2003-01-20 21:26:34 +00004708 */
4709xmlChar *
4710xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4711 /* we know that locator is a xmlParserCtxtPtr */
4712 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4713 xmlChar *ret = NULL;
4714
Daniel Veillardce682bc2004-11-05 17:22:25 +00004715 if (locator == NULL)
4716 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004717 if (ctx->node != NULL) {
4718 ret = xmlNodeGetBase(NULL,ctx->node);
4719 }
4720 else {
4721 /* inspired from error.c */
4722 xmlParserInputPtr input;
4723 input = ctx->input;
4724 if ((input->filename == NULL) && (ctx->inputNr > 1))
4725 input = ctx->inputTab[ctx->inputNr - 2];
4726 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004727 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004728 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004729 else {
4730 ret = NULL;
4731 }
4732 }
4733
4734 return ret;
4735}
4736
Daniel Veillard26f70262003-01-16 22:45:08 +00004737static void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004738xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4739 char *str)
4740{
4741 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4742
4743 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
Daniel Veillard26f70262003-01-16 22:45:08 +00004744
William M. Bracka3215c72004-07-31 16:24:01 +00004745 if (str != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004746 if (reader->errorFunc)
4747 reader->errorFunc(reader->errorFuncArg, str, severity,
4748 (xmlTextReaderLocatorPtr) ctx);
4749 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004750 }
4751}
4752
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004753static void
4754xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4755{
4756 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
William M. Brack93d004f2004-02-03 00:14:10 +00004757
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004758 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4759
4760 if (error && reader->sErrorFunc) {
4761 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4762 }
William M. Brack93d004f2004-02-03 00:14:10 +00004763}
4764
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004765static void XMLCDECL
4766xmlTextReaderError(void *ctxt, const char *msg, ...)
4767{
Daniel Veillard26f70262003-01-16 22:45:08 +00004768 va_list ap;
4769
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004770 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004771 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004772 XML_PARSER_SEVERITY_ERROR,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004773 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004774 va_end(ap);
4775
4776}
4777
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004778static void XMLCDECL
4779xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4780{
Daniel Veillard26f70262003-01-16 22:45:08 +00004781 va_list ap;
4782
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004783 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004784 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004785 XML_PARSER_SEVERITY_WARNING,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004786 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004787 va_end(ap);
4788}
4789
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004790static void XMLCDECL
4791xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4792{
Daniel Veillard26f70262003-01-16 22:45:08 +00004793 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004794
Daniel Veillard417be3a2003-01-20 21:26:34 +00004795 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004796
Daniel Veillard417be3a2003-01-20 21:26:34 +00004797 if ((len > 1) && (msg[len - 2] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004798 /*
4799 * some callbacks only report locator information:
4800 * skip them (mimicking behaviour in error.c)
4801 */
4802 va_start(ap, msg);
4803 xmlTextReaderGenericError(ctxt,
4804 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4805 xmlTextReaderBuildMessage(msg, ap));
4806 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004807 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004808}
4809
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004810static void XMLCDECL
4811xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4812{
Daniel Veillard26f70262003-01-16 22:45:08 +00004813 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004814
Daniel Veillard417be3a2003-01-20 21:26:34 +00004815 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004816
Daniel Veillard417be3a2003-01-20 21:26:34 +00004817 if ((len != 0) && (msg[len - 1] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004818 /*
4819 * some callbacks only report locator information:
4820 * skip them (mimicking behaviour in error.c)
4821 */
4822 va_start(ap, msg);
4823 xmlTextReaderGenericError(ctxt,
4824 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4825 xmlTextReaderBuildMessage(msg, ap));
4826 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004827 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004828}
4829
4830/**
4831 * xmlTextReaderSetErrorHandler:
4832 * @reader: the xmlTextReaderPtr used
4833 * @f: the callback function to call on error and warnings
4834 * @arg: a user argument to pass to the callback function
4835 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004836 * Register a callback function that will be called on error and warnings.
4837 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004838 * If @f is NULL, the default error and warning handlers are restored.
4839 */
4840void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004841xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4842 xmlTextReaderErrorFunc f, void *arg)
4843{
Daniel Veillard26f70262003-01-16 22:45:08 +00004844 if (f != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004845 reader->ctxt->sax->error = xmlTextReaderError;
4846 reader->ctxt->sax->serror = NULL;
4847 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4848 reader->ctxt->sax->warning = xmlTextReaderWarning;
4849 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4850 reader->errorFunc = f;
4851 reader->sErrorFunc = NULL;
4852 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004853#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004854 if (reader->rngValidCtxt) {
4855 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4856 xmlTextReaderValidityErrorRelay,
4857 xmlTextReaderValidityWarningRelay,
4858 reader);
4859 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4860 reader);
4861 }
4862 if (reader->xsdValidCtxt) {
4863 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4864 xmlTextReaderValidityErrorRelay,
4865 xmlTextReaderValidityWarningRelay,
4866 reader);
4867 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4868 reader);
4869 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004870#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004871 } else {
4872 /* restore defaults */
4873 reader->ctxt->sax->error = xmlParserError;
4874 reader->ctxt->vctxt.error = xmlParserValidityError;
4875 reader->ctxt->sax->warning = xmlParserWarning;
4876 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4877 reader->errorFunc = NULL;
4878 reader->sErrorFunc = NULL;
4879 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004880#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004881 if (reader->rngValidCtxt) {
4882 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4883 reader);
4884 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4885 reader);
4886 }
4887 if (reader->xsdValidCtxt) {
4888 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4889 reader);
4890 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4891 reader);
4892 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004893#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004894 }
4895}
4896
Daniel Veillard417be3a2003-01-20 21:26:34 +00004897/**
William M. Brack93d004f2004-02-03 00:14:10 +00004898* xmlTextReaderSetStructuredErrorHandler:
4899 * @reader: the xmlTextReaderPtr used
4900 * @f: the callback function to call on error and warnings
4901 * @arg: a user argument to pass to the callback function
4902 *
4903 * Register a callback function that will be called on error and warnings.
4904 *
4905 * If @f is NULL, the default error and warning handlers are restored.
4906 */
4907void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004908xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4909 xmlStructuredErrorFunc f, void *arg)
4910{
4911 if (f != NULL) {
4912 reader->ctxt->sax->error = NULL;
4913 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4914 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4915 reader->ctxt->sax->warning = xmlTextReaderWarning;
4916 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4917 reader->sErrorFunc = f;
4918 reader->errorFunc = NULL;
4919 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004920#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004921 if (reader->rngValidCtxt) {
4922 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4923 reader);
4924 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4925 xmlTextReaderValidityStructuredRelay,
4926 reader);
4927 }
4928 if (reader->xsdValidCtxt) {
4929 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4930 reader);
4931 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4932 xmlTextReaderValidityStructuredRelay,
4933 reader);
4934 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004935#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004936 } else {
4937 /* restore defaults */
4938 reader->ctxt->sax->error = xmlParserError;
4939 reader->ctxt->sax->serror = NULL;
4940 reader->ctxt->vctxt.error = xmlParserValidityError;
4941 reader->ctxt->sax->warning = xmlParserWarning;
4942 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4943 reader->errorFunc = NULL;
4944 reader->sErrorFunc = NULL;
4945 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004946#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004947 if (reader->rngValidCtxt) {
4948 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4949 reader);
4950 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4951 reader);
4952 }
4953 if (reader->xsdValidCtxt) {
4954 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4955 reader);
4956 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4957 reader);
4958 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004959#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004960 }
William M. Brack93d004f2004-02-03 00:14:10 +00004961}
4962
4963/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00004964 * xmlTextReaderIsValid:
4965 * @reader: the xmlTextReaderPtr used
4966 *
4967 * Retrieve the validity status from the parser context
4968 *
4969 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
4970 */
4971int
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004972xmlTextReaderIsValid(xmlTextReaderPtr reader)
4973{
4974 if (reader == NULL)
4975 return (-1);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004976#ifdef LIBXML_SCHEMAS_ENABLED
4977 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004978 return (reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004979 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004980 return (reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004981#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00004982 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004983 return (reader->ctxt->valid);
4984 return (0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00004985}
4986
4987/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00004988 * xmlTextReaderGetErrorHandler:
4989 * @reader: the xmlTextReaderPtr used
4990 * @f: the callback function or NULL is no callback has been registered
4991 * @arg: a user argument
4992 *
4993 * Retrieve the error callback function and user argument.
4994 */
Daniel Veillard26f70262003-01-16 22:45:08 +00004995void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004996xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
4997 xmlTextReaderErrorFunc * f, void **arg)
4998{
4999 if (f != NULL)
5000 *f = reader->errorFunc;
5001 if (arg != NULL)
5002 *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00005003}
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005004/************************************************************************
5005 * *
5006 * New set (2.6.0) of simpler and more flexible APIs *
5007 * *
5008 ************************************************************************/
5009
5010/**
5011 * xmlTextReaderSetup:
5012 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00005013 * @input: xmlParserInputBufferPtr used to feed the reader, will
5014 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005015 * @URL: the base URL to use for the document
5016 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005017 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005018 *
5019 * Setup an XML reader with new options
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005020 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005021 * Returns 0 in case of success and -1 in case of error.
5022 */
Aleksey Sanind8377642007-01-03 23:13:12 +00005023int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005024xmlTextReaderSetup(xmlTextReaderPtr reader,
5025 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005026 const char *encoding, int options)
5027{
William M. Brackd46c1ca2007-02-08 23:34:34 +00005028 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00005029 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00005030 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00005031 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00005032 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005033
Daniel Veillard8874b942005-08-25 13:19:21 +00005034 /*
5035 * we force the generation of compact text nodes on the reader
5036 * since usr applications should never modify the tree
5037 */
5038 options |= XML_PARSE_COMPACT;
5039
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005040 reader->doc = NULL;
5041 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00005042 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00005043 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005044 if ((input != NULL) && (reader->input != NULL) &&
5045 (reader->allocs & XML_TEXTREADER_INPUT)) {
5046 xmlFreeParserInputBuffer(reader->input);
5047 reader->input = NULL;
5048 reader->allocs -= XML_TEXTREADER_INPUT;
5049 }
5050 if (input != NULL) {
5051 reader->input = input;
5052 reader->allocs |= XML_TEXTREADER_INPUT;
5053 }
5054 if (reader->buffer == NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08005055 reader->buffer = xmlBufCreateSize(100);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005056 if (reader->buffer == NULL) {
5057 xmlGenericError(xmlGenericErrorContext,
5058 "xmlTextReaderSetup : malloc failed\n");
5059 return (-1);
5060 }
5061 if (reader->sax == NULL)
5062 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5063 if (reader->sax == NULL) {
5064 xmlGenericError(xmlGenericErrorContext,
5065 "xmlTextReaderSetup : malloc failed\n");
5066 return (-1);
5067 }
5068 xmlSAXVersion(reader->sax, 2);
5069 reader->startElement = reader->sax->startElement;
5070 reader->sax->startElement = xmlTextReaderStartElement;
5071 reader->endElement = reader->sax->endElement;
5072 reader->sax->endElement = xmlTextReaderEndElement;
5073#ifdef LIBXML_SAX1_ENABLED
5074 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5075#endif /* LIBXML_SAX1_ENABLED */
5076 reader->startElementNs = reader->sax->startElementNs;
5077 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5078 reader->endElementNs = reader->sax->endElementNs;
5079 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5080#ifdef LIBXML_SAX1_ENABLED
5081 } else {
5082 reader->startElementNs = NULL;
5083 reader->endElementNs = NULL;
5084 }
5085#endif /* LIBXML_SAX1_ENABLED */
5086 reader->characters = reader->sax->characters;
5087 reader->sax->characters = xmlTextReaderCharacters;
5088 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5089 reader->cdataBlock = reader->sax->cdataBlock;
5090 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5091
5092 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5093 reader->node = NULL;
5094 reader->curnode = NULL;
5095 if (input != NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005096 if (xmlBufUse(reader->input->buffer) < 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005097 xmlParserInputBufferRead(input, 4);
5098 }
5099 if (reader->ctxt == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005100 if (xmlBufUse(reader->input->buffer) >= 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005101 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08005102 (const char *) xmlBufContent(reader->input->buffer),
5103 4, URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005104 reader->base = 0;
5105 reader->cur = 4;
5106 } else {
5107 reader->ctxt =
5108 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5109 reader->base = 0;
5110 reader->cur = 0;
5111 }
5112 } else {
5113 xmlParserInputPtr inputStream;
5114 xmlParserInputBufferPtr buf;
5115 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5116
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005117 xmlCtxtReset(reader->ctxt);
5118 buf = xmlAllocParserInputBuffer(enc);
5119 if (buf == NULL) return(-1);
5120 inputStream = xmlNewInputStream(reader->ctxt);
5121 if (inputStream == NULL) {
5122 xmlFreeParserInputBuffer(buf);
5123 return(-1);
5124 }
5125
5126 if (URL == NULL)
5127 inputStream->filename = NULL;
5128 else
5129 inputStream->filename = (char *)
5130 xmlCanonicPath((const xmlChar *) URL);
5131 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +08005132 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005133
5134 inputPush(reader->ctxt, inputStream);
5135 reader->cur = 0;
5136 }
5137 if (reader->ctxt == NULL) {
5138 xmlGenericError(xmlGenericErrorContext,
5139 "xmlTextReaderSetup : malloc failed\n");
5140 return (-1);
5141 }
5142 }
5143 if (reader->dict != NULL) {
5144 if (reader->ctxt->dict != NULL) {
5145 if (reader->dict != reader->ctxt->dict) {
5146 xmlDictFree(reader->dict);
5147 reader->dict = reader->ctxt->dict;
5148 }
5149 } else {
5150 reader->ctxt->dict = reader->dict;
5151 }
5152 } else {
5153 if (reader->ctxt->dict == NULL)
5154 reader->ctxt->dict = xmlDictCreate();
5155 reader->dict = reader->ctxt->dict;
5156 }
5157 reader->ctxt->_private = reader;
5158 reader->ctxt->linenumbers = 1;
5159 reader->ctxt->dictNames = 1;
5160 /*
5161 * use the parser dictionnary to allocate all elements and attributes names
5162 */
5163 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005164 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005165
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005166#ifdef LIBXML_XINCLUDE_ENABLED
5167 if (reader->xincctxt != NULL) {
5168 xmlXIncludeFreeContext(reader->xincctxt);
5169 reader->xincctxt = NULL;
5170 }
5171 if (options & XML_PARSE_XINCLUDE) {
5172 reader->xinclude = 1;
5173 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5174 options -= XML_PARSE_XINCLUDE;
5175 } else
5176 reader->xinclude = 0;
5177 reader->in_xinclude = 0;
5178#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005179#ifdef LIBXML_PATTERN_ENABLED
5180 if (reader->patternTab == NULL) {
5181 reader->patternNr = 0;
5182 reader->patternMax = 0;
5183 }
5184 while (reader->patternNr > 0) {
5185 reader->patternNr--;
5186 if (reader->patternTab[reader->patternNr] != NULL) {
5187 xmlFreePattern(reader->patternTab[reader->patternNr]);
5188 reader->patternTab[reader->patternNr] = NULL;
5189 }
5190 }
5191#endif
5192
Daniel Veillardc36965d2003-12-02 10:28:48 +00005193 if (options & XML_PARSE_DTDVALID)
5194 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5195
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005196 xmlCtxtUseOptions(reader->ctxt, options);
5197 if (encoding != NULL) {
5198 xmlCharEncodingHandlerPtr hdlr;
5199
5200 hdlr = xmlFindCharEncodingHandler(encoding);
5201 if (hdlr != NULL)
5202 xmlSwitchToEncoding(reader->ctxt, hdlr);
5203 }
5204 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5205 (reader->ctxt->input->filename == NULL))
5206 reader->ctxt->input->filename = (char *)
5207 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005208
5209 reader->doc = NULL;
5210
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005211 return (0);
5212}
5213
5214/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005215 * xmlTextReaderByteConsumed:
5216 * @reader: an XML reader
5217 *
5218 * This function provides the current index of the parser used
5219 * by the reader, relative to the start of the current entity.
5220 * This function actually just wraps a call to xmlBytesConsumed()
5221 * for the parser context associated with the reader.
5222 * See xmlBytesConsumed() for more information.
5223 *
5224 * Returns the index in bytes from the beginning of the entity or -1
5225 * in case the index could not be computed.
5226 */
5227long
5228xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5229 if ((reader == NULL) || (reader->ctxt == NULL))
5230 return(-1);
5231 return(xmlByteConsumed(reader->ctxt));
5232}
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005233
Daniel Veillard5e094142005-02-18 19:36:12 +00005234
5235/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005236 * xmlReaderWalker:
5237 * @doc: a preparsed document
5238 *
5239 * Create an xmltextReader for a preparsed document.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005240 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005241 * Returns the new reader or NULL in case of error.
5242 */
5243xmlTextReaderPtr
5244xmlReaderWalker(xmlDocPtr doc)
5245{
5246 xmlTextReaderPtr ret;
5247
5248 if (doc == NULL)
5249 return(NULL);
5250
5251 ret = xmlMalloc(sizeof(xmlTextReader));
5252 if (ret == NULL) {
5253 xmlGenericError(xmlGenericErrorContext,
5254 "xmlNewTextReader : malloc failed\n");
5255 return(NULL);
5256 }
5257 memset(ret, 0, sizeof(xmlTextReader));
5258 ret->entNr = 0;
5259 ret->input = NULL;
5260 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5261 ret->node = NULL;
5262 ret->curnode = NULL;
5263 ret->base = 0;
5264 ret->cur = 0;
5265 ret->allocs = XML_TEXTREADER_CTXT;
5266 ret->doc = doc;
5267 ret->state = XML_TEXTREADER_START;
5268 ret->dict = xmlDictCreate();
5269 return(ret);
5270}
5271
5272/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005273 * xmlReaderForDoc:
5274 * @cur: a pointer to a zero terminated string
5275 * @URL: the base URL to use for the document
5276 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005277 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005278 *
5279 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005280 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005281 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005282 * Returns the new reader or NULL in case of error.
5283 */
5284xmlTextReaderPtr
5285xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5286 int options)
5287{
5288 int len;
5289
5290 if (cur == NULL)
5291 return (NULL);
5292 len = xmlStrlen(cur);
5293
5294 return (xmlReaderForMemory
5295 ((const char *) cur, len, URL, encoding, options));
5296}
5297
5298/**
5299 * xmlReaderForFile:
5300 * @filename: a file or URL
5301 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005302 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005303 *
5304 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005305 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005306 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005307 * Returns the new reader or NULL in case of error.
5308 */
5309xmlTextReaderPtr
5310xmlReaderForFile(const char *filename, const char *encoding, int options)
5311{
5312 xmlTextReaderPtr reader;
5313
5314 reader = xmlNewTextReaderFilename(filename);
5315 if (reader == NULL)
5316 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005317 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005318 return (reader);
5319}
5320
5321/**
5322 * xmlReaderForMemory:
5323 * @buffer: a pointer to a char array
5324 * @size: the size of the array
5325 * @URL: the base URL to use for the document
5326 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005327 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005328 *
5329 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005330 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005331 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005332 * Returns the new reader or NULL in case of error.
5333 */
5334xmlTextReaderPtr
5335xmlReaderForMemory(const char *buffer, int size, const char *URL,
5336 const char *encoding, int options)
5337{
5338 xmlTextReaderPtr reader;
5339 xmlParserInputBufferPtr buf;
5340
Daniel Veillard21924522004-02-19 16:37:07 +00005341 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005342 XML_CHAR_ENCODING_NONE);
5343 if (buf == NULL) {
5344 return (NULL);
5345 }
5346 reader = xmlNewTextReader(buf, URL);
5347 if (reader == NULL) {
5348 xmlFreeParserInputBuffer(buf);
5349 return (NULL);
5350 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005351 reader->allocs |= XML_TEXTREADER_INPUT;
5352 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005353 return (reader);
5354}
5355
5356/**
5357 * xmlReaderForFd:
5358 * @fd: an open file descriptor
5359 * @URL: the base URL to use for the document
5360 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005361 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005362 *
5363 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005364 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005365 * NOTE that the file descriptor will not be closed when the
5366 * reader is closed or reset.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005367 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005368 * Returns the new reader or NULL in case of error.
5369 */
5370xmlTextReaderPtr
5371xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5372{
5373 xmlTextReaderPtr reader;
5374 xmlParserInputBufferPtr input;
5375
5376 if (fd < 0)
5377 return (NULL);
5378
5379 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5380 if (input == NULL)
5381 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005382 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005383 reader = xmlNewTextReader(input, URL);
5384 if (reader == NULL) {
5385 xmlFreeParserInputBuffer(input);
5386 return (NULL);
5387 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005388 reader->allocs |= XML_TEXTREADER_INPUT;
5389 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005390 return (reader);
5391}
5392
5393/**
5394 * xmlReaderForIO:
5395 * @ioread: an I/O read function
5396 * @ioclose: an I/O close function
5397 * @ioctx: an I/O handler
5398 * @URL: the base URL to use for the document
5399 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005400 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005401 *
5402 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005403 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005404 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005405 * Returns the new reader or NULL in case of error.
5406 */
5407xmlTextReaderPtr
5408xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5409 void *ioctx, const char *URL, const char *encoding,
5410 int options)
5411{
5412 xmlTextReaderPtr reader;
5413 xmlParserInputBufferPtr input;
5414
5415 if (ioread == NULL)
5416 return (NULL);
5417
5418 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5419 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005420 if (input == NULL) {
5421 if (ioclose != NULL)
5422 ioclose(ioctx);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005423 return (NULL);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005424 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005425 reader = xmlNewTextReader(input, URL);
5426 if (reader == NULL) {
5427 xmlFreeParserInputBuffer(input);
5428 return (NULL);
5429 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005430 reader->allocs |= XML_TEXTREADER_INPUT;
5431 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005432 return (reader);
5433}
5434
5435/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005436 * xmlReaderNewWalker:
5437 * @reader: an XML reader
5438 * @doc: a preparsed document
5439 *
5440 * Setup an xmltextReader to parse a preparsed XML document.
5441 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005442 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005443 * Returns 0 in case of success and -1 in case of error
5444 */
5445int
5446xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5447{
5448 if (doc == NULL)
5449 return (-1);
5450 if (reader == NULL)
5451 return (-1);
5452
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005453 if (reader->input != NULL) {
5454 xmlFreeParserInputBuffer(reader->input);
5455 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005456 if (reader->ctxt != NULL) {
5457 xmlCtxtReset(reader->ctxt);
5458 }
5459
5460 reader->entNr = 0;
5461 reader->input = NULL;
5462 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5463 reader->node = NULL;
5464 reader->curnode = NULL;
5465 reader->base = 0;
5466 reader->cur = 0;
5467 reader->allocs = XML_TEXTREADER_CTXT;
5468 reader->doc = doc;
5469 reader->state = XML_TEXTREADER_START;
5470 if (reader->dict == NULL) {
5471 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5472 reader->dict = reader->ctxt->dict;
5473 else
5474 reader->dict = xmlDictCreate();
5475 }
5476 return(0);
5477}
5478
5479/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005480 * xmlReaderNewDoc:
5481 * @reader: an XML reader
5482 * @cur: a pointer to a zero terminated string
5483 * @URL: the base URL to use for the document
5484 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005485 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005486 *
5487 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005488 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005489 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005490 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005491 * Returns 0 in case of success and -1 in case of error
5492 */
5493int
5494xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5495 const char *URL, const char *encoding, int options)
5496{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005497
5498 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005499
5500 if (cur == NULL)
5501 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005502 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005503 return (-1);
5504
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005505 len = xmlStrlen(cur);
5506 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5507 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005508}
5509
5510/**
5511 * xmlReaderNewFile:
5512 * @reader: an XML reader
5513 * @filename: a file or URL
5514 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005515 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005516 *
5517 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005518 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005519 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005520 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005521 * Returns 0 in case of success and -1 in case of error
5522 */
5523int
5524xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5525 const char *encoding, int options)
5526{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005527 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005528
5529 if (filename == NULL)
5530 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005531 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005532 return (-1);
5533
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005534 input =
5535 xmlParserInputBufferCreateFilename(filename,
5536 XML_CHAR_ENCODING_NONE);
5537 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005538 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005539 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005540}
5541
5542/**
5543 * xmlReaderNewMemory:
5544 * @reader: an XML reader
5545 * @buffer: a pointer to a char array
5546 * @size: the size of the array
5547 * @URL: the base URL to use for the document
5548 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005549 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005550 *
5551 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005552 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005553 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005554 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005555 * Returns 0 in case of success and -1 in case of error
5556 */
5557int
5558xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5559 const char *URL, const char *encoding, int options)
5560{
5561 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005562
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005563 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005564 return (-1);
5565 if (buffer == NULL)
5566 return (-1);
5567
Daniel Veillard21924522004-02-19 16:37:07 +00005568 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005569 XML_CHAR_ENCODING_NONE);
5570 if (input == NULL) {
5571 return (-1);
5572 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005573 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005574}
5575
5576/**
5577 * xmlReaderNewFd:
5578 * @reader: an XML reader
5579 * @fd: an open file descriptor
5580 * @URL: the base URL to use for the document
5581 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005582 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005583 *
5584 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005585 * NOTE that the file descriptor will not be closed when the
5586 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005587 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005588 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005589 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005590 * Returns 0 in case of success and -1 in case of error
5591 */
5592int
5593xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5594 const char *URL, const char *encoding, int options)
5595{
5596 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005597
5598 if (fd < 0)
5599 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005600 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005601 return (-1);
5602
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005603 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5604 if (input == NULL)
5605 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005606 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005607 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005608}
5609
5610/**
5611 * xmlReaderNewIO:
5612 * @reader: an XML reader
5613 * @ioread: an I/O read function
5614 * @ioclose: an I/O close function
5615 * @ioctx: an I/O handler
5616 * @URL: the base URL to use for the document
5617 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005618 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005619 *
5620 * Setup an xmltextReader to parse an XML document from I/O functions
5621 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005622 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005623 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005624 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005625 * Returns 0 in case of success and -1 in case of error
5626 */
5627int
5628xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5629 xmlInputCloseCallback ioclose, void *ioctx,
5630 const char *URL, const char *encoding, int options)
5631{
5632 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005633
5634 if (ioread == NULL)
5635 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005636 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005637 return (-1);
5638
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005639 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5640 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005641 if (input == NULL) {
5642 if (ioclose != NULL)
5643 ioclose(ioctx);
Daniel Veillard2c437da2012-05-11 12:08:15 +08005644 return (-1);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005645 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005646 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005647}
Lin Yi-Li24464be2012-05-10 16:14:55 +08005648
Daniel Veillard26f70262003-01-16 22:45:08 +00005649/************************************************************************
5650 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005651 * Utilities *
5652 * *
5653 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005654#ifdef NOT_USED_YET
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005655
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005656/**
5657 * xmlBase64Decode:
5658 * @in: the input buffer
5659 * @inlen: the size of the input (in), the size read from it (out)
5660 * @to: the output buffer
5661 * @tolen: the size of the output (in), the size written to (out)
5662 *
5663 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005664 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005665 *
5666 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5667 * 2 if there wasn't enough space on the output or -1 in case of error.
5668 */
5669static int
5670xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005671 unsigned char *to, unsigned long *tolen)
5672{
5673 unsigned long incur; /* current index in in[] */
5674
5675 unsigned long inblk; /* last block index in in[] */
5676
5677 unsigned long outcur; /* current index in out[] */
5678
5679 unsigned long inmax; /* size of in[] */
5680
5681 unsigned long outmax; /* size of out[] */
5682
5683 unsigned char cur; /* the current value read from in[] */
5684
5685 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5686
5687 int nbintmp; /* number of byte in intmp[] */
5688
5689 int is_ignore; /* cur should be ignored */
5690
5691 int is_end = 0; /* the end of the base64 was found */
5692
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005693 int retval = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005694
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005695 int i;
5696
5697 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005698 return (-1);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005699
5700 incur = 0;
5701 inblk = 0;
5702 outcur = 0;
5703 inmax = *inlen;
5704 outmax = *tolen;
5705 nbintmp = 0;
5706
5707 while (1) {
5708 if (incur >= inmax)
5709 break;
5710 cur = in[incur++];
5711 is_ignore = 0;
5712 if ((cur >= 'A') && (cur <= 'Z'))
5713 cur = cur - 'A';
5714 else if ((cur >= 'a') && (cur <= 'z'))
5715 cur = cur - 'a' + 26;
5716 else if ((cur >= '0') && (cur <= '9'))
5717 cur = cur - '0' + 52;
5718 else if (cur == '+')
5719 cur = 62;
5720 else if (cur == '/')
5721 cur = 63;
5722 else if (cur == '.')
5723 cur = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005724 else if (cur == '=') /*no op , end of the base64 stream */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005725 is_end = 1;
5726 else {
5727 is_ignore = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005728 if (nbintmp == 0)
5729 inblk = incur;
5730 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005731
5732 if (!is_ignore) {
5733 int nbouttmp = 3;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005734
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005735 int is_break = 0;
5736
5737 if (is_end) {
5738 if (nbintmp == 0)
5739 break;
5740 if ((nbintmp == 1) || (nbintmp == 2))
5741 nbouttmp = 1;
5742 else
5743 nbouttmp = 2;
5744 nbintmp = 3;
5745 is_break = 1;
5746 }
5747 intmp[nbintmp++] = cur;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005748 /*
5749 * if intmp is full, push the 4byte sequence as a 3 byte
5750 * sequence out
5751 */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005752 if (nbintmp == 4) {
5753 nbintmp = 0;
5754 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5755 outtmp[1] =
5756 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5757 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005758 if (outcur + 3 >= outmax) {
5759 retval = 2;
5760 break;
5761 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005762
5763 for (i = 0; i < nbouttmp; i++)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005764 to[outcur++] = outtmp[i];
5765 inblk = incur;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005766 }
5767
5768 if (is_break) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005769 retval = 0;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005770 break;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005771 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005772 }
5773 }
5774
5775 *tolen = outcur;
5776 *inlen = inblk;
5777 return (retval);
5778}
5779
5780/*
5781 * Test routine for the xmlBase64Decode function
5782 */
5783#if 0
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005784int
5785main(int argc, char **argv)
5786{
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005787 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005788
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005789 char output[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005790
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005791 char output2[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005792
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005793 char output3[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005794
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005795 unsigned long inlen = strlen(input);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005796
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005797 unsigned long outlen = 100;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005798
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005799 int ret;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005800
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005801 unsigned long cons, tmp, tmp2, prod;
5802
5803 /*
5804 * Direct
5805 */
5806 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5807
5808 output[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005809 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5810 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5811;
5812
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005813 /*
5814 * output chunking
5815 */
5816 cons = 0;
5817 prod = 0;
5818 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005819 tmp = 5;
5820 tmp2 = inlen - cons;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005821
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005822 printf("%ld %ld\n", cons, prod);
5823 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5824 cons += tmp2;
5825 prod += tmp;
5826 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005827 }
5828 output2[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005829 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5830 prod, output2);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005831
5832 /*
5833 * input chunking
5834 */
5835 cons = 0;
5836 prod = 0;
5837 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005838 tmp = 100 - prod;
5839 tmp2 = inlen - cons;
5840 if (tmp2 > 5)
5841 tmp2 = 5;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005842
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005843 printf("%ld %ld\n", cons, prod);
5844 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5845 cons += tmp2;
5846 prod += tmp;
5847 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005848 }
5849 output3[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005850 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5851 prod, output3);
5852 return (0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005853
5854}
5855#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005856#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005857#define bottom_xmlreader
5858#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005859#endif /* LIBXML_READER_ENABLED */