blob: 2607a70510e370863d34fec0445b51672da8bb9e [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
Patrick Monnerat0f7a26d2013-12-12 15:04:43 +080054 * esoteric implementations of va_list but (hopefully) will
55 * be sufficient for libxml2.
Daniel Veillard7e65fad2008-09-25 14:55:21 +000056 */
57#ifndef VA_COPY
58 #ifdef HAVE_VA_COPY
59 #define VA_COPY(dest, src) va_copy(dest, src)
60 #else
61 #ifdef HAVE___VA_COPY
62 #define VA_COPY(dest,src) __va_copy(dest, src)
63 #else
Patrick Monnerat0f7a26d2013-12-12 15:04:43 +080064 #ifndef VA_LIST_IS_ARRAY
65 #define VA_COPY(dest,src) (dest) = (src)
66 #else
67 #include <string.h>
68 #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
69 #endif
Daniel Veillard7e65fad2008-09-25 14:55:21 +000070 #endif
71 #endif
72#endif
73
Daniel Veillarde1ca5032002-12-09 14:13:43 +000074/* #define DEBUG_CALLBACKS */
75/* #define DEBUG_READER */
76
77/**
78 * TODO:
79 *
80 * macro to flag unimplemented blocks
81 */
Daniel Veillardaacc2a22009-08-11 18:31:42 +020082#define TODO \
Daniel Veillarde1ca5032002-12-09 14:13:43 +000083 xmlGenericError(xmlGenericErrorContext, \
84 "Unimplemented block at %s:%d\n", \
85 __FILE__, __LINE__);
86
87#ifdef DEBUG_READER
88#define DUMP_READER xmlTextReaderDebug(reader);
89#else
90#define DUMP_READER
91#endif
92
Daniel Veillarda880b122003-04-21 21:36:41 +000093#define CHUNK_SIZE 512
Daniel Veillarde1ca5032002-12-09 14:13:43 +000094/************************************************************************
95 * *
96 * The parser: maps the Text Reader API on top of the existing *
97 * parsing routines building a tree *
98 * *
99 ************************************************************************/
100
101#define XML_TEXTREADER_INPUT 1
102#define XML_TEXTREADER_CTXT 2
103
104typedef enum {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000105 XML_TEXTREADER_NONE = -1,
106 XML_TEXTREADER_START= 0,
107 XML_TEXTREADER_ELEMENT= 1,
108 XML_TEXTREADER_END= 2,
109 XML_TEXTREADER_EMPTY= 3,
Daniel Veillardea7751d2002-12-20 00:16:24 +0000110 XML_TEXTREADER_BACKTRACK= 4,
Daniel Veillarda76fe5c2003-04-24 16:06:47 +0000111 XML_TEXTREADER_DONE= 5,
112 XML_TEXTREADER_ERROR= 6
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000113} xmlTextReaderState;
114
Daniel Veillardf4e55762003-04-15 23:32:22 +0000115typedef enum {
116 XML_TEXTREADER_NOT_VALIDATE = 0,
117 XML_TEXTREADER_VALIDATE_DTD = 1,
Daniel Veillardf10ae122005-07-10 19:03:16 +0000118 XML_TEXTREADER_VALIDATE_RNG = 2,
119 XML_TEXTREADER_VALIDATE_XSD = 4
Daniel Veillardf4e55762003-04-15 23:32:22 +0000120} xmlTextReaderValidate;
121
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000122struct _xmlTextReader {
123 int mode; /* the parsing mode */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000124 xmlDocPtr doc; /* when walking an existing doc */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000125 xmlTextReaderValidate validate;/* is there any validation */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000126 int allocs; /* what structure were deallocated */
127 xmlTextReaderState state;
128 xmlParserCtxtPtr ctxt; /* the parser context */
129 xmlSAXHandlerPtr sax; /* the parser SAX callbacks */
130 xmlParserInputBufferPtr input; /* the input */
131 startElementSAXFunc startElement;/* initial SAX callbacks */
132 endElementSAXFunc endElement; /* idem */
Daniel Veillard07cb8222003-09-10 10:51:05 +0000133 startElementNsSAX2Func startElementNs;/* idem */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000134 endElementNsSAX2Func endElementNs; /* idem */
Daniel Veillardea7751d2002-12-20 00:16:24 +0000135 charactersSAXFunc characters;
136 cdataBlockSAXFunc cdataBlock;
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200137 unsigned int base; /* base of the segment in the input */
138 unsigned int cur; /* current position in the input */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000139 xmlNodePtr node; /* current node */
Daniel Veillardda46d2d2002-12-15 23:36:49 +0000140 xmlNodePtr curnode;/* current attribute node */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000141 int depth; /* depth of the current node */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +0000142 xmlNodePtr faketext;/* fake xmlNs chld */
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000143 int preserve;/* preserve the resulting document */
Daniel Veillard8aebce32012-07-16 14:42:31 +0800144 xmlBufPtr buffer; /* used to return const xmlChar * */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000145 xmlDictPtr dict; /* the context dictionnary */
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000146
147 /* entity stack when traversing entities content */
148 xmlNodePtr ent; /* Current Entity Ref Node */
149 int entNr; /* Depth of the entities stack */
150 int entMax; /* Max depth of the entities stack */
151 xmlNodePtr *entTab; /* array of entities */
Daniel Veillard26f70262003-01-16 22:45:08 +0000152
153 /* error handling */
154 xmlTextReaderErrorFunc errorFunc; /* callback function */
155 void *errorFuncArg; /* callback function user argument */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000156
157#ifdef LIBXML_SCHEMAS_ENABLED
158 /* Handling of RelaxNG validation */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000159 xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
160 xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
Noam Postavsky15794992012-03-19 16:08:16 +0800161 int rngPreserveCtxt; /* 1 if the context was provided by the user */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000162 int rngValidErrors;/* The number of errors detected */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000163 xmlNodePtr rngFullNode; /* the node if RNG not progressive */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000164 /* Handling of Schemas validation */
165 xmlSchemaPtr xsdSchemas; /* The Schemas schemas */
166 xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +0000167 int xsdPreserveCtxt; /* 1 if the context was provided by the user */
168 int xsdValidErrors;/* The number of errors detected */
Daniel Veillardf10ae122005-07-10 19:03:16 +0000169 xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000170#endif
171#ifdef LIBXML_XINCLUDE_ENABLED
172 /* Handling of XInclude processing */
173 int xinclude; /* is xinclude asked for */
174 const xmlChar * xinclude_name; /* the xinclude name from dict */
175 xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */
176 int in_xinclude; /* counts for xinclude */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000177#endif
Daniel Veillard1e906612003-12-05 14:57:46 +0000178#ifdef LIBXML_PATTERN_ENABLED
179 int patternNr; /* number of preserve patterns */
180 int patternMax; /* max preserve patterns */
181 xmlPatternPtr *patternTab; /* array of preserve patterns */
182#endif
183 int preserves; /* level of preserves */
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000184 int parserFlags; /* the set of options set */
William M. Brack93d004f2004-02-03 00:14:10 +0000185 /* Structured error handling */
186 xmlStructuredErrorFunc sErrorFunc; /* callback function */
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000187};
188
Daniel Veillarde8039df2003-10-27 11:25:13 +0000189#define NODE_IS_EMPTY 0x1
190#define NODE_IS_PRESERVED 0x2
Daniel Veillard1e906612003-12-05 14:57:46 +0000191#define NODE_IS_SPRESERVED 0x4
Daniel Veillard067bae52003-01-05 01:27:54 +0000192
Daniel Veillarde72c5082003-09-19 12:44:05 +0000193/**
194 * CONSTSTR:
195 *
196 * Macro used to return an interned string
197 */
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000198#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
199#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
200
201static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
202static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
Daniel Veillarde72c5082003-09-19 12:44:05 +0000203
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000204/************************************************************************
205 * *
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000206 * Our own version of the freeing routines as we recycle nodes *
207 * *
208 ************************************************************************/
209/**
210 * DICT_FREE:
211 * @str: a string
212 *
213 * Free a string if it is not owned by the "dict" dictionnary in the
214 * current scope
215 */
216#define DICT_FREE(str) \
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200217 if ((str) && ((!dict) || \
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000218 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
219 xmlFree((char *)(str));
220
221static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
222static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
223
224/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000225 * xmlFreeID:
226 * @not: A id
227 *
228 * Deallocate the memory used by an id definition
229 */
230static void
231xmlFreeID(xmlIDPtr id) {
232 xmlDictPtr dict = NULL;
233
234 if (id == NULL) return;
235
236 if (id->doc != NULL)
237 dict = id->doc->dict;
238
239 if (id->value != NULL)
240 DICT_FREE(id->value)
241 xmlFree(id);
242}
243
244/**
245 * xmlTextReaderRemoveID:
246 * @doc: the document
247 * @attr: the attribute
248 *
249 * Remove the given attribute from the ID table maintained internally.
250 *
251 * Returns -1 if the lookup failed and 0 otherwise
252 */
253static int
254xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
255 xmlIDTablePtr table;
256 xmlIDPtr id;
257 xmlChar *ID;
258
259 if (doc == NULL) return(-1);
260 if (attr == NULL) return(-1);
261 table = (xmlIDTablePtr) doc->ids;
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200262 if (table == NULL)
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000263 return(-1);
264
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000265 ID = xmlNodeListGetString(doc, attr->children, 1);
266 if (ID == NULL)
267 return(-1);
268 id = xmlHashLookup(table, ID);
269 xmlFree(ID);
270 if (id == NULL || id->attr != attr) {
271 return(-1);
272 }
273 id->name = attr->name;
274 id->attr = NULL;
275 return(0);
276}
277
278/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000279 * xmlTextReaderFreeProp:
280 * @reader: the xmlTextReaderPtr used
281 * @cur: the node
282 *
283 * Free a node.
284 */
285static void
286xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
287 xmlDictPtr dict;
288
289 dict = reader->ctxt->dict;
290 if (cur == NULL) return;
291
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000292 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
293 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
294
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000295 /* Check for ID removal -> leading to invalid references ! */
296 if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
297 ((cur->parent->doc->intSubset != NULL) ||
298 (cur->parent->doc->extSubset != NULL))) {
299 if (xmlIsID(cur->parent->doc, cur->parent, cur))
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000300 xmlTextReaderRemoveID(cur->parent->doc, cur);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000301 }
302 if (cur->children != NULL)
303 xmlTextReaderFreeNodeList(reader, cur->children);
304
305 DICT_FREE(cur->name);
306 if ((reader != NULL) && (reader->ctxt != NULL) &&
307 (reader->ctxt->freeAttrsNr < 100)) {
308 cur->next = reader->ctxt->freeAttrs;
309 reader->ctxt->freeAttrs = cur;
310 reader->ctxt->freeAttrsNr++;
311 } else {
312 xmlFree(cur);
313 }
314}
315
316/**
317 * xmlTextReaderFreePropList:
318 * @reader: the xmlTextReaderPtr used
319 * @cur: the first property in the list
320 *
321 * Free a property and all its siblings, all the children are freed too.
322 */
323static void
324xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
325 xmlAttrPtr next;
326 if (cur == NULL) return;
327 while (cur != NULL) {
328 next = cur->next;
329 xmlTextReaderFreeProp(reader, cur);
330 cur = next;
331 }
332}
333
334/**
335 * xmlTextReaderFreeNodeList:
336 * @reader: the xmlTextReaderPtr used
337 * @cur: the first node in the list
338 *
339 * Free a node and all its siblings, this is a recursive behaviour, all
340 * the children are freed too.
341 */
342static void
343xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
344 xmlNodePtr next;
345 xmlDictPtr dict;
346
347 dict = reader->ctxt->dict;
348 if (cur == NULL) return;
349 if (cur->type == XML_NAMESPACE_DECL) {
350 xmlFreeNsList((xmlNsPtr) cur);
351 return;
352 }
353 if ((cur->type == XML_DOCUMENT_NODE) ||
354 (cur->type == XML_HTML_DOCUMENT_NODE)) {
355 xmlFreeDoc((xmlDocPtr) cur);
356 return;
357 }
358 while (cur != NULL) {
359 next = cur->next;
360 /* unroll to speed up freeing the document */
361 if (cur->type != XML_DTD_NODE) {
362
363 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000364 (cur->type != XML_ENTITY_REF_NODE)) {
365 if (cur->children->parent == cur)
366 xmlTextReaderFreeNodeList(reader, cur->children);
367 cur->children = NULL;
368 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000369
370 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
371 xmlDeregisterNodeDefaultValue(cur);
372
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000373 if (((cur->type == XML_ELEMENT_NODE) ||
374 (cur->type == XML_XINCLUDE_START) ||
375 (cur->type == XML_XINCLUDE_END)) &&
376 (cur->properties != NULL))
377 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000378 if ((cur->content != (xmlChar *) &(cur->properties)) &&
379 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000380 (cur->type != XML_XINCLUDE_START) &&
381 (cur->type != XML_XINCLUDE_END) &&
382 (cur->type != XML_ENTITY_REF_NODE)) {
383 DICT_FREE(cur->content);
384 }
385 if (((cur->type == XML_ELEMENT_NODE) ||
386 (cur->type == XML_XINCLUDE_START) ||
387 (cur->type == XML_XINCLUDE_END)) &&
388 (cur->nsDef != NULL))
389 xmlFreeNsList(cur->nsDef);
390
391 /*
392 * we don't free element names here they are interned now
393 */
394 if ((cur->type != XML_TEXT_NODE) &&
395 (cur->type != XML_COMMENT_NODE))
396 DICT_FREE(cur->name);
397 if (((cur->type == XML_ELEMENT_NODE) ||
398 (cur->type == XML_TEXT_NODE)) &&
399 (reader != NULL) && (reader->ctxt != NULL) &&
400 (reader->ctxt->freeElemsNr < 100)) {
401 cur->next = reader->ctxt->freeElems;
402 reader->ctxt->freeElems = cur;
403 reader->ctxt->freeElemsNr++;
404 } else {
405 xmlFree(cur);
406 }
407 }
408 cur = next;
409 }
410}
411
412/**
413 * xmlTextReaderFreeNode:
414 * @reader: the xmlTextReaderPtr used
415 * @cur: the node
416 *
417 * Free a node, this is a recursive behaviour, all the children are freed too.
418 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
419 */
420static void
421xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
422 xmlDictPtr dict;
423
424 dict = reader->ctxt->dict;
425 if (cur->type == XML_DTD_NODE) {
426 xmlFreeDtd((xmlDtdPtr) cur);
427 return;
428 }
429 if (cur->type == XML_NAMESPACE_DECL) {
430 xmlFreeNs((xmlNsPtr) cur);
431 return;
432 }
433 if (cur->type == XML_ATTRIBUTE_NODE) {
434 xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
435 return;
436 }
437
438 if ((cur->children != NULL) &&
Daniel Veillard1d211e22003-10-20 22:32:39 +0000439 (cur->type != XML_ENTITY_REF_NODE)) {
440 if (cur->children->parent == cur)
441 xmlTextReaderFreeNodeList(reader, cur->children);
442 cur->children = NULL;
443 }
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000444
445 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
446 xmlDeregisterNodeDefaultValue(cur);
447
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000448 if (((cur->type == XML_ELEMENT_NODE) ||
449 (cur->type == XML_XINCLUDE_START) ||
450 (cur->type == XML_XINCLUDE_END)) &&
451 (cur->properties != NULL))
452 xmlTextReaderFreePropList(reader, cur->properties);
Daniel Veillard8874b942005-08-25 13:19:21 +0000453 if ((cur->content != (xmlChar *) &(cur->properties)) &&
454 (cur->type != XML_ELEMENT_NODE) &&
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000455 (cur->type != XML_XINCLUDE_START) &&
456 (cur->type != XML_XINCLUDE_END) &&
457 (cur->type != XML_ENTITY_REF_NODE)) {
458 DICT_FREE(cur->content);
459 }
460 if (((cur->type == XML_ELEMENT_NODE) ||
461 (cur->type == XML_XINCLUDE_START) ||
462 (cur->type == XML_XINCLUDE_END)) &&
463 (cur->nsDef != NULL))
464 xmlFreeNsList(cur->nsDef);
465
466 /*
467 * we don't free names here they are interned now
468 */
469 if ((cur->type != XML_TEXT_NODE) &&
470 (cur->type != XML_COMMENT_NODE))
471 DICT_FREE(cur->name);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000472
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000473 if (((cur->type == XML_ELEMENT_NODE) ||
474 (cur->type == XML_TEXT_NODE)) &&
475 (reader != NULL) && (reader->ctxt != NULL) &&
476 (reader->ctxt->freeElemsNr < 100)) {
477 cur->next = reader->ctxt->freeElems;
478 reader->ctxt->freeElems = cur;
479 reader->ctxt->freeElemsNr++;
480 } else {
481 xmlFree(cur);
482 }
483}
484
485/**
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000486 * xmlTextReaderFreeIDTable:
487 * @table: An id table
488 *
489 * Deallocate the memory used by an ID hash table.
490 */
William M. Brack60f394e2003-11-16 06:25:42 +0000491static void
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000492xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
493 xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
494}
495
496/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000497 * xmlTextReaderFreeDoc:
498 * @reader: the xmlTextReaderPtr used
499 * @cur: pointer to the document
500 *
501 * Free up all the structures used by a document, tree included.
502 */
503static void
504xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
505 xmlDtdPtr extSubset, intSubset;
506
507 if (cur == NULL) return;
508
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000509 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
510 xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
511
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000512 /*
513 * Do this before freeing the children list to avoid ID lookups
514 */
Daniel Veillard8d7b5c72003-11-15 18:24:36 +0000515 if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000516 cur->ids = NULL;
517 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
518 cur->refs = NULL;
519 extSubset = cur->extSubset;
520 intSubset = cur->intSubset;
521 if (intSubset == extSubset)
522 extSubset = NULL;
523 if (extSubset != NULL) {
524 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
525 cur->extSubset = NULL;
526 xmlFreeDtd(extSubset);
527 }
528 if (intSubset != NULL) {
529 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
530 cur->intSubset = NULL;
531 xmlFreeDtd(intSubset);
532 }
533
534 if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
535
536 if (cur->version != NULL) xmlFree((char *) cur->version);
537 if (cur->name != NULL) xmlFree((char *) cur->name);
538 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
539 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
540 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard500a1de2004-03-22 15:22:58 +0000541 if (cur->dict != NULL) xmlDictFree(cur->dict);
Daniel Veillarda2d51fc2004-04-30 22:25:59 +0000542
Daniel Veillard9ee35f32003-09-28 00:19:54 +0000543 xmlFree(cur);
544}
545
546/************************************************************************
547 * *
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +0000548 * The reader core parser *
549 * *
550 ************************************************************************/
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000551#ifdef DEBUG_READER
552static void
553xmlTextReaderDebug(xmlTextReaderPtr reader) {
554 if ((reader == NULL) || (reader->ctxt == NULL)) {
555 fprintf(stderr, "xmlTextReader NULL\n");
556 return;
557 }
558 fprintf(stderr, "xmlTextReader: state %d depth %d ",
559 reader->state, reader->depth);
560 if (reader->node == NULL) {
561 fprintf(stderr, "node = NULL\n");
562 } else {
563 fprintf(stderr, "node %s\n", reader->node->name);
564 }
565 fprintf(stderr, " input: base %d, cur %d, depth %d: ",
566 reader->base, reader->cur, reader->ctxt->nodeNr);
567 if (reader->input->buffer == NULL) {
568 fprintf(stderr, "buffer is NULL\n");
569 } else {
570#ifdef LIBXML_DEBUG_ENABLED
571 xmlDebugDumpString(stderr,
572 &reader->input->buffer->content[reader->cur]);
573#endif
574 fprintf(stderr, "\n");
575 }
576}
577#endif
578
579/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000580 * xmlTextReaderEntPush:
581 * @reader: the xmlTextReaderPtr used
582 * @value: the entity reference node
583 *
584 * Pushes a new entity reference node on top of the entities stack
585 *
586 * Returns 0 in case of error, the index in the stack otherwise
587 */
588static int
589xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
590{
591 if (reader->entMax <= 0) {
592 reader->entMax = 10;
593 reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
594 sizeof(reader->entTab[0]));
595 if (reader->entTab == NULL) {
596 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
597 return (0);
598 }
599 }
600 if (reader->entNr >= reader->entMax) {
601 reader->entMax *= 2;
602 reader->entTab =
603 (xmlNodePtr *) xmlRealloc(reader->entTab,
604 reader->entMax *
605 sizeof(reader->entTab[0]));
606 if (reader->entTab == NULL) {
607 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
608 return (0);
609 }
610 }
611 reader->entTab[reader->entNr] = value;
612 reader->ent = value;
613 return (reader->entNr++);
614}
615
616/**
617 * xmlTextReaderEntPop:
618 * @reader: the xmlTextReaderPtr used
619 *
620 * Pops the top element entity from the entities stack
621 *
622 * Returns the entity just removed
623 */
624static xmlNodePtr
625xmlTextReaderEntPop(xmlTextReaderPtr reader)
626{
627 xmlNodePtr ret;
628
629 if (reader->entNr <= 0)
Daniel Veillard75e389d2005-07-29 22:02:24 +0000630 return (NULL);
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000631 reader->entNr--;
632 if (reader->entNr > 0)
633 reader->ent = reader->entTab[reader->entNr - 1];
634 else
635 reader->ent = NULL;
636 ret = reader->entTab[reader->entNr];
Daniel Veillard75e389d2005-07-29 22:02:24 +0000637 reader->entTab[reader->entNr] = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000638 return (ret);
639}
640
641/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000642 * xmlTextReaderStartElement:
643 * @ctx: the user data (XML parser context)
644 * @fullname: The element name, including namespace prefix
645 * @atts: An array of name/value attributes pairs, NULL terminated
646 *
647 * called when an opening tag has been processed.
648 */
649static void
650xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
651 const xmlChar **atts) {
652 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
653 xmlTextReaderPtr reader = ctxt->_private;
654
655#ifdef DEBUG_CALLBACKS
656 printf("xmlTextReaderStartElement(%s)\n", fullname);
657#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000658 if ((reader != NULL) && (reader->startElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000659 reader->startElement(ctx, fullname, atts);
Daniel Veillard067bae52003-01-05 01:27:54 +0000660 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
661 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
662 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000663 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000664 }
Daniel Veillard9e395c22003-01-01 14:50:44 +0000665 if (reader != NULL)
666 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000667}
668
669/**
670 * xmlTextReaderEndElement:
671 * @ctx: the user data (XML parser context)
672 * @fullname: The element name, including namespace prefix
673 *
674 * called when an ending tag has been processed.
675 */
676static void
677xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
678 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
679 xmlTextReaderPtr reader = ctxt->_private;
680
681#ifdef DEBUG_CALLBACKS
682 printf("xmlTextReaderEndElement(%s)\n", fullname);
683#endif
Daniel Veillardea7751d2002-12-20 00:16:24 +0000684 if ((reader != NULL) && (reader->endElement != NULL)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000685 reader->endElement(ctx, fullname);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000686 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000687}
688
689/**
Daniel Veillard07cb8222003-09-10 10:51:05 +0000690 * xmlTextReaderStartElementNs:
691 * @ctx: the user data (XML parser context)
692 * @localname: the local name of the element
693 * @prefix: the element namespace prefix if available
694 * @URI: the element namespace name if available
695 * @nb_namespaces: number of namespace definitions on that node
696 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
697 * @nb_attributes: the number of attributes on that node
698 * nb_defaulted: the number of defaulted attributes.
699 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
700 * attribute values.
701 *
702 * called when an opening tag has been processed.
703 */
704static void
705xmlTextReaderStartElementNs(void *ctx,
706 const xmlChar *localname,
707 const xmlChar *prefix,
708 const xmlChar *URI,
709 int nb_namespaces,
710 const xmlChar **namespaces,
711 int nb_attributes,
712 int nb_defaulted,
713 const xmlChar **attributes)
714{
715 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
716 xmlTextReaderPtr reader = ctxt->_private;
717
718#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000719 printf("xmlTextReaderStartElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000720#endif
721 if ((reader != NULL) && (reader->startElementNs != NULL)) {
722 reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
723 namespaces, nb_attributes, nb_defaulted,
724 attributes);
725 if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
726 (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
727 (ctxt->input->cur[1] == '>'))
Daniel Veillarde8039df2003-10-27 11:25:13 +0000728 ctxt->node->extra = NODE_IS_EMPTY;
Daniel Veillard07cb8222003-09-10 10:51:05 +0000729 }
730 if (reader != NULL)
731 reader->state = XML_TEXTREADER_ELEMENT;
732}
733
734/**
735 * xmlTextReaderEndElementNs:
736 * @ctx: the user data (XML parser context)
737 * @localname: the local name of the element
738 * @prefix: the element namespace prefix if available
739 * @URI: the element namespace name if available
740 *
741 * called when an ending tag has been processed.
742 */
743static void
744xmlTextReaderEndElementNs(void *ctx,
745 const xmlChar * localname,
746 const xmlChar * prefix,
747 const xmlChar * URI)
748{
749 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
750 xmlTextReaderPtr reader = ctxt->_private;
751
752#ifdef DEBUG_CALLBACKS
Daniel Veillard198c1bf2003-10-20 17:07:41 +0000753 printf("xmlTextReaderEndElementNs(%s)\n", localname);
Daniel Veillard07cb8222003-09-10 10:51:05 +0000754#endif
755 if ((reader != NULL) && (reader->endElementNs != NULL)) {
756 reader->endElementNs(ctx, localname, prefix, URI);
757 }
758}
759
760
761/**
Daniel Veillardea7751d2002-12-20 00:16:24 +0000762 * xmlTextReaderCharacters:
763 * @ctx: the user data (XML parser context)
764 * @ch: a xmlChar string
765 * @len: the number of xmlChar
766 *
767 * receiving some chars from the parser.
768 */
769static void
770xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
771{
772 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
773 xmlTextReaderPtr reader = ctxt->_private;
774
775#ifdef DEBUG_CALLBACKS
776 printf("xmlTextReaderCharacters()\n");
777#endif
778 if ((reader != NULL) && (reader->characters != NULL)) {
779 reader->characters(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000780 }
781}
782
783/**
784 * xmlTextReaderCDataBlock:
785 * @ctx: the user data (XML parser context)
786 * @value: The pcdata content
787 * @len: the block length
788 *
789 * called when a pcdata block has been parsed
790 */
791static void
792xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
793{
794 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
795 xmlTextReaderPtr reader = ctxt->_private;
796
797#ifdef DEBUG_CALLBACKS
798 printf("xmlTextReaderCDataBlock()\n");
799#endif
800 if ((reader != NULL) && (reader->cdataBlock != NULL)) {
801 reader->cdataBlock(ctx, ch, len);
Daniel Veillardea7751d2002-12-20 00:16:24 +0000802 }
803}
804
805/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000806 * xmlTextReaderPushData:
807 * @reader: the xmlTextReaderPtr used
808 *
809 * Push data down the progressive parser until a significant callback
810 * got raised.
811 *
812 * Returns -1 in case of failure, 0 otherwise
813 */
814static int
815xmlTextReaderPushData(xmlTextReaderPtr reader) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800816 xmlBufPtr inbuf;
Daniel Veillarda880b122003-04-21 21:36:41 +0000817 int val, s;
William M. Brack779af002003-08-01 15:55:39 +0000818 xmlTextReaderState oldstate;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800819 int alloc;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000820
821 if ((reader->input == NULL) || (reader->input->buffer == NULL))
822 return(-1);
823
Daniel Veillardea7751d2002-12-20 00:16:24 +0000824 oldstate = reader->state;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000825 reader->state = XML_TEXTREADER_NONE;
826 inbuf = reader->input->buffer;
Daniel Veillard8aebce32012-07-16 14:42:31 +0800827 alloc = xmlBufGetAllocationScheme(inbuf);
Daniel Veillarda880b122003-04-21 21:36:41 +0000828
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000829 while (reader->state == XML_TEXTREADER_NONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800830 if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000831 /*
832 * Refill the buffer unless we are at the end of the stream
833 */
834 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
835 val = xmlParserInputBufferRead(reader->input, 4096);
Daniel Veillard53350552003-09-18 13:35:51 +0000836 if ((val == 0) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800837 (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
838 if (xmlBufUse(inbuf) == reader->cur) {
Daniel Veillard53350552003-09-18 13:35:51 +0000839 reader->mode = XML_TEXTREADER_MODE_EOF;
840 reader->state = oldstate;
Daniel Veillard53350552003-09-18 13:35:51 +0000841 }
842 } else if (val < 0) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000843 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000844 reader->state = oldstate;
Daniel Veillardaaa105b2002-12-30 11:42:17 +0000845 if ((oldstate != XML_TEXTREADER_START) ||
846 (reader->ctxt->myDoc != NULL))
847 return(val);
Daniel Veillard53350552003-09-18 13:35:51 +0000848 } else if (val == 0) {
849 /* mark the end of the stream and process the remains */
850 reader->mode = XML_TEXTREADER_MODE_EOF;
851 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000852 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000853
Daniel Veillardaacc2a22009-08-11 18:31:42 +0200854 } else
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000855 break;
856 }
Daniel Veillard067bae52003-01-05 01:27:54 +0000857 /*
Daniel Veillarda880b122003-04-21 21:36:41 +0000858 * parse by block of CHUNK_SIZE bytes, various tests show that
859 * it's the best tradeoff at least on a 1.2GH Duron
Daniel Veillard067bae52003-01-05 01:27:54 +0000860 */
Daniel Veillard8aebce32012-07-16 14:42:31 +0800861 if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000862 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800863 (const char *) xmlBufContent(inbuf) + reader->cur,
864 CHUNK_SIZE, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000865 reader->cur += CHUNK_SIZE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800866 if (val != 0)
867 reader->ctxt->wellFormed = 0;
868 if (reader->ctxt->wellFormed == 0)
869 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000870 } else {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800871 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillarda880b122003-04-21 21:36:41 +0000872 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800873 (const char *) xmlBufContent(inbuf) + reader->cur,
874 s, 0);
Daniel Veillarda880b122003-04-21 21:36:41 +0000875 reader->cur += s;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800876 if (val != 0)
877 reader->ctxt->wellFormed = 0;
Daniel Veillarda880b122003-04-21 21:36:41 +0000878 break;
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000879 }
880 }
Daniel Veillarda880b122003-04-21 21:36:41 +0000881
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000882 /*
883 * Discard the consumed input when needed and possible
884 */
Daniel Veillard67df8092002-12-16 22:04:11 +0000885 if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800886 if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
Daniel Veillard21924522004-02-19 16:37:07 +0000887 if ((reader->cur >= 4096) &&
Daniel Veillard8aebce32012-07-16 14:42:31 +0800888 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
889 val = xmlBufShrink(inbuf, reader->cur);
Daniel Veillard21924522004-02-19 16:37:07 +0000890 if (val >= 0) {
891 reader->cur -= val;
892 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000893 }
894 }
895 }
896
897 /*
898 * At the end of the stream signal that the work is done to the Push
899 * parser.
900 */
Daniel Veillarda880b122003-04-21 21:36:41 +0000901 else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
Daniel Veillarda9c56772007-03-09 16:59:05 +0000902 if (reader->state != XML_TEXTREADER_DONE) {
Daniel Veillard8aebce32012-07-16 14:42:31 +0800903 s = xmlBufUse(inbuf) - reader->cur;
Daniel Veillardea7751d2002-12-20 00:16:24 +0000904 val = xmlParseChunk(reader->ctxt,
Daniel Veillard8aebce32012-07-16 14:42:31 +0800905 (const char *) xmlBufContent(inbuf) + reader->cur,
906 s, 1);
907 reader->cur = xmlBufUse(inbuf);
Daniel Veillarda9c56772007-03-09 16:59:05 +0000908 reader->state = XML_TEXTREADER_DONE;
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800909 if (val != 0) {
910 if (reader->ctxt->wellFormed)
911 reader->ctxt->wellFormed = 0;
912 else
913 return(-1);
914 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000915 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000916 }
Daniel Veillardea7751d2002-12-20 00:16:24 +0000917 reader->state = oldstate;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800918 if (reader->ctxt->wellFormed == 0) {
Andy Lutomirski9d9685a2012-05-15 20:10:25 +0800919 reader->mode = XML_TEXTREADER_MODE_EOF;
Daniel Veillardc508fa32012-07-18 17:39:56 +0800920 return(-1);
921 }
922
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000923 return(0);
924}
925
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000926#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarde1ca5032002-12-09 14:13:43 +0000927/**
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000928 * xmlTextReaderValidatePush:
929 * @reader: the xmlTextReaderPtr used
930 *
931 * Push the current node for validation
932 */
933static void
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000934xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000935 xmlNodePtr node = reader->node;
936
Daniel Veillardf54cd532004-02-25 11:52:31 +0000937#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000938 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
939 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
940 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
941 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
942 reader->ctxt->myDoc, node, node->name);
943 } else {
944 /* TODO use the BuildQName interface */
945 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000946
Daniel Veillardf4e55762003-04-15 23:32:22 +0000947 qname = xmlStrdup(node->ns->prefix);
948 qname = xmlStrcat(qname, BAD_CAST ":");
949 qname = xmlStrcat(qname, node->name);
950 reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
951 reader->ctxt->myDoc, node, qname);
952 if (qname != NULL)
953 xmlFree(qname);
954 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000955 }
956#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +0000957#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +0000958 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +0000959 (reader->rngValidCtxt != NULL)) {
960 int ret;
961
962 if (reader->rngFullNode != NULL) return;
963 ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
964 reader->ctxt->myDoc,
965 node);
966 if (ret == 0) {
967 /*
968 * this element requires a full tree
969 */
970 node = xmlTextReaderExpand(reader);
971 if (node == NULL) {
972printf("Expand failed !\n");
973 ret = -1;
974 } else {
975 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
976 reader->ctxt->myDoc,
977 node);
978 reader->rngFullNode = node;
979 }
980 }
981 if (ret != 1)
982 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000983 }
Daniel Veillardf54cd532004-02-25 11:52:31 +0000984#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +0000985}
Daniel Veillardf4e55762003-04-15 23:32:22 +0000986
987/**
988 * xmlTextReaderValidateCData:
989 * @reader: the xmlTextReaderPtr used
990 * @data: pointer to the CData
Michael Woodfb27e2c2012-09-28 08:59:33 +0200991 * @len: length of the CData block in bytes.
Daniel Veillardf4e55762003-04-15 23:32:22 +0000992 *
993 * Push some CData for validation
994 */
995static void
996xmlTextReaderValidateCData(xmlTextReaderPtr reader,
997 const xmlChar *data, int len) {
Daniel Veillardf54cd532004-02-25 11:52:31 +0000998#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +0000999 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1000 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1001 reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1002 data, len);
Daniel Veillardf54cd532004-02-25 11:52:31 +00001003 }
1004#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001005#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001006 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001007 (reader->rngValidCtxt != NULL)) {
1008 int ret;
1009
1010 if (reader->rngFullNode != NULL) return;
1011 ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1012 if (ret != 1)
1013 reader->rngValidErrors++;
Daniel Veillardf4e55762003-04-15 23:32:22 +00001014 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001015#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00001016}
1017
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001018/**
1019 * xmlTextReaderValidatePop:
1020 * @reader: the xmlTextReaderPtr used
1021 *
1022 * Pop the current node from validation
1023 */
1024static void
1025xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1026 xmlNodePtr node = reader->node;
1027
Daniel Veillardf54cd532004-02-25 11:52:31 +00001028#ifdef LIBXML_VALID_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001029 if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1030 (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1031 if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1032 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1033 reader->ctxt->myDoc, node, node->name);
1034 } else {
1035 /* TODO use the BuildQName interface */
1036 xmlChar *qname;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001037
Daniel Veillardf4e55762003-04-15 23:32:22 +00001038 qname = xmlStrdup(node->ns->prefix);
1039 qname = xmlStrcat(qname, BAD_CAST ":");
1040 qname = xmlStrcat(qname, node->name);
1041 reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1042 reader->ctxt->myDoc, node, qname);
1043 if (qname != NULL)
1044 xmlFree(qname);
1045 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001046 }
1047#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf4e55762003-04-15 23:32:22 +00001048#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf54cd532004-02-25 11:52:31 +00001049 if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001050 (reader->rngValidCtxt != NULL)) {
1051 int ret;
1052
1053 if (reader->rngFullNode != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001054 if (node == reader->rngFullNode)
Daniel Veillardf4e55762003-04-15 23:32:22 +00001055 reader->rngFullNode = NULL;
1056 return;
1057 }
1058 ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1059 reader->ctxt->myDoc,
1060 node);
1061 if (ret != 1)
1062 reader->rngValidErrors++;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001063 }
Daniel Veillardf54cd532004-02-25 11:52:31 +00001064#endif
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001065}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001066
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001067/**
1068 * xmlTextReaderValidateEntity:
1069 * @reader: the xmlTextReaderPtr used
1070 *
1071 * Handle the validation when an entity reference is encountered and
1072 * entity substitution is not activated. As a result the parser interface
1073 * must walk through the entity and do the validation calls
1074 */
1075static void
1076xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1077 xmlNodePtr oldnode = reader->node;
1078 xmlNodePtr node = reader->node;
1079 xmlParserCtxtPtr ctxt = reader->ctxt;
1080
1081 do {
1082 if (node->type == XML_ENTITY_REF_NODE) {
1083 /*
1084 * Case where the underlying tree is not availble, lookup the entity
1085 * and walk it.
1086 */
1087 if ((node->children == NULL) && (ctxt->sax != NULL) &&
1088 (ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001089 node->children = (xmlNodePtr)
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001090 ctxt->sax->getEntity(ctxt, node->name);
1091 }
1092
1093 if ((node->children != NULL) &&
1094 (node->children->type == XML_ENTITY_DECL) &&
1095 (node->children->children != NULL)) {
1096 xmlTextReaderEntPush(reader, node);
1097 node = node->children->children;
1098 continue;
1099 } else {
1100 /*
1101 * The error has probably be raised already.
1102 */
1103 if (node == oldnode)
1104 break;
1105 node = node->next;
1106 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001107#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001108 } else if (node->type == XML_ELEMENT_NODE) {
1109 reader->node = node;
1110 xmlTextReaderValidatePush(reader);
1111 } else if ((node->type == XML_TEXT_NODE) ||
1112 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001113 xmlTextReaderValidateCData(reader, node->content,
1114 xmlStrlen(node->content));
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001115#endif
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001116 }
1117
1118 /*
1119 * go to next node
1120 */
1121 if (node->children != NULL) {
1122 node = node->children;
1123 continue;
Daniel Veillardef8dd7b2003-03-23 12:02:56 +00001124 } else if (node->type == XML_ELEMENT_NODE) {
1125 xmlTextReaderValidatePop(reader);
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001126 }
1127 if (node->next != NULL) {
1128 node = node->next;
1129 continue;
1130 }
1131 do {
1132 node = node->parent;
1133 if (node->type == XML_ELEMENT_NODE) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001134 xmlNodePtr tmp;
Daniel Veillard1d211e22003-10-20 22:32:39 +00001135 if (reader->entNr == 0) {
1136 while ((tmp = node->last) != NULL) {
Daniel Veillarde8039df2003-10-27 11:25:13 +00001137 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard1d211e22003-10-20 22:32:39 +00001138 xmlUnlinkNode(tmp);
1139 xmlTextReaderFreeNode(reader, tmp);
1140 } else
1141 break;
1142 }
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001143 }
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001144 reader->node = node;
1145 xmlTextReaderValidatePop(reader);
1146 }
1147 if ((node->type == XML_ENTITY_DECL) &&
1148 (reader->ent != NULL) && (reader->ent->children == node)) {
1149 node = xmlTextReaderEntPop(reader);
1150 }
1151 if (node == oldnode)
1152 break;
1153 if (node->next != NULL) {
1154 node = node->next;
1155 break;
1156 }
1157 } while ((node != NULL) && (node != oldnode));
1158 } while ((node != NULL) && (node != oldnode));
1159 reader->node = oldnode;
1160}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001161#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001162
1163
1164/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001165 * xmlTextReaderGetSuccessor:
1166 * @cur: the current node
1167 *
1168 * Get the successor of a node if available.
1169 *
1170 * Returns the successor node or NULL
1171 */
1172static xmlNodePtr
1173xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1174 if (cur == NULL) return(NULL) ; /* ERROR */
1175 if (cur->next != NULL) return(cur->next) ;
1176 do {
1177 cur = cur->parent;
Daniel Veillard11ce4002006-03-10 00:36:23 +00001178 if (cur == NULL) break;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001179 if (cur->next != NULL) return(cur->next);
1180 } while (cur != NULL);
1181 return(cur);
1182}
1183
1184/**
1185 * xmlTextReaderDoExpand:
1186 * @reader: the xmlTextReaderPtr used
1187 *
1188 * Makes sure that the current node is fully read as well as all its
1189 * descendant. It means the full DOM subtree must be available at the
1190 * end of the call.
1191 *
1192 * Returns 1 if the node was expanded successfully, 0 if there is no more
1193 * nodes to read, or -1 in case of error
1194 */
1195static int
1196xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1197 int val;
1198
1199 if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1200 return(-1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001201 do {
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001202 if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1203
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001204 if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1205 return(1);
Daniel Veillardf96cf4e2003-10-01 09:05:25 +00001206 if (reader->ctxt->nodeNr < reader->depth)
Daniel Veillarda37aab82003-06-09 09:10:36 +00001207 return(1);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001208 if (reader->mode == XML_TEXTREADER_MODE_EOF)
1209 return(1);
1210 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001211 if (val < 0){
William M. Brack0c1e3012007-03-14 12:40:21 +00001212 reader->mode = XML_TEXTREADER_MODE_ERROR;
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001213 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001214 }
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001215 } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1216 return(1);
1217}
1218
1219/**
Daniel Veillarde125b312005-01-28 17:39:49 +00001220 * xmlTextReaderCollectSiblings:
1221 * @node: the first child
1222 *
1223 * Traverse depth-first through all sibling nodes and their children
1224 * nodes and concatenate their content. This is an auxiliary function
1225 * to xmlTextReaderReadString.
1226 *
1227 * Returns a string containing the content, or NULL in case of error.
1228 */
1229static xmlChar *
1230xmlTextReaderCollectSiblings(xmlNodePtr node)
1231{
1232 xmlBufferPtr buffer;
1233 xmlChar *ret;
1234
Daniel Veillard3e62adb2012-08-09 14:24:02 +08001235 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1236 return(NULL);
1237
Daniel Veillarde125b312005-01-28 17:39:49 +00001238 buffer = xmlBufferCreate();
1239 if (buffer == NULL)
1240 return NULL;
1241
1242 for ( ; node != NULL; node = node->next) {
1243 switch (node->type) {
1244 case XML_TEXT_NODE:
1245 case XML_CDATA_SECTION_NODE:
1246 xmlBufferCat(buffer, node->content);
1247 break;
Daniel Veillard47fffb42005-09-22 11:14:43 +00001248 case XML_ELEMENT_NODE: {
1249 xmlChar *tmp;
1250
1251 tmp = xmlTextReaderCollectSiblings(node->children);
1252 xmlBufferCat(buffer, tmp);
1253 xmlFree(tmp);
1254 break;
1255 }
Daniel Veillarde125b312005-01-28 17:39:49 +00001256 default:
1257 break;
1258 }
1259 }
1260 ret = buffer->content;
1261 buffer->content = NULL;
1262 xmlBufferFree(buffer);
1263 return(ret);
1264}
1265
1266/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001267 * xmlTextReaderRead:
1268 * @reader: the xmlTextReaderPtr used
1269 *
1270 * Moves the position of the current instance to the next node in
1271 * the stream, exposing its properties.
1272 *
1273 * Returns 1 if the node was read successfully, 0 if there is no more
1274 * nodes to read, or -1 in case of error
1275 */
1276int
1277xmlTextReaderRead(xmlTextReaderPtr reader) {
Daniel Veillard067bae52003-01-05 01:27:54 +00001278 int val, olddepth = 0;
William M. Brack899e64a2003-09-26 18:03:42 +00001279 xmlTextReaderState oldstate = XML_TEXTREADER_START;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001280 xmlNodePtr oldnode = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001281
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001282
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001283 if (reader == NULL)
1284 return(-1);
William M. Brack1af55582004-07-22 17:18:00 +00001285 reader->curnode = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001286 if (reader->doc != NULL)
1287 return(xmlTextReaderReadTree(reader));
1288 if (reader->ctxt == NULL)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001289 return(-1);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001290
1291#ifdef DEBUG_READER
1292 fprintf(stderr, "\nREAD ");
1293 DUMP_READER
1294#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001295 if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1296 reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001297 /*
1298 * Initial state
1299 */
1300 do {
1301 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001302 if (val < 0){
1303 reader->mode = XML_TEXTREADER_MODE_ERROR;
1304 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001305 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001306 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001307 } while ((reader->ctxt->node == NULL) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001308 ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
Daniel Veillarda9c56772007-03-09 16:59:05 +00001309 (reader->state != XML_TEXTREADER_DONE)));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001310 if (reader->ctxt->node == NULL) {
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001311 if (reader->ctxt->myDoc != NULL) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001312 reader->node = reader->ctxt->myDoc->children;
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001313 }
Daniel Veillarda9c56772007-03-09 16:59:05 +00001314 if (reader->node == NULL){
1315 reader->mode = XML_TEXTREADER_MODE_ERROR;
1316 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001317 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001318 }
Daniel Veillarddab8ea92003-01-02 14:16:45 +00001319 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001320 } else {
Daniel Veillard48ef4c92003-03-22 12:38:15 +00001321 if (reader->ctxt->myDoc != NULL) {
1322 reader->node = reader->ctxt->myDoc->children;
1323 }
1324 if (reader->node == NULL)
1325 reader->node = reader->ctxt->nodeTab[0];
Daniel Veillarde59494f2003-01-04 16:35:29 +00001326 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001327 }
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001328 reader->depth = 0;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00001329 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001330 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001331 }
1332 oldstate = reader->state;
1333 olddepth = reader->ctxt->nodeNr;
1334 oldnode = reader->node;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001335
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001336get_next_node:
Daniel Veillard6f379a72004-04-29 18:45:42 +00001337 if (reader->node == NULL) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001338 if (reader->mode == XML_TEXTREADER_MODE_EOF)
Daniel Veillard6f379a72004-04-29 18:45:42 +00001339 return(0);
1340 else
1341 return(-1);
1342 }
Daniel Veillarde2161a62004-04-29 17:14:25 +00001343
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001344 /*
1345 * If we are not backtracking on ancestors or examined nodes,
1346 * that the parser didn't finished or that we arent at the end
1347 * of stream, continue processing.
1348 */
Daniel Veillarde2161a62004-04-29 17:14:25 +00001349 while ((reader->node != NULL) && (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001350 (reader->ctxt->nodeNr == olddepth) &&
1351 ((oldstate == XML_TEXTREADER_BACKTRACK) ||
Daniel Veillardea7751d2002-12-20 00:16:24 +00001352 (reader->node->children == NULL) ||
1353 (reader->node->type == XML_ENTITY_REF_NODE) ||
Daniel Veillard409a8142003-07-18 15:16:57 +00001354 ((reader->node->children != NULL) &&
1355 (reader->node->children->type == XML_TEXT_NODE) &&
1356 (reader->node->children->next == NULL)) ||
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001357 (reader->node->type == XML_DTD_NODE) ||
1358 (reader->node->type == XML_DOCUMENT_NODE) ||
1359 (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001360 ((reader->ctxt->node == NULL) ||
1361 (reader->ctxt->node == reader->node) ||
1362 (reader->ctxt->node == reader->node->parent)) &&
Daniel Veillardea7751d2002-12-20 00:16:24 +00001363 (reader->ctxt->instate != XML_PARSER_EOF)) {
1364 val = xmlTextReaderPushData(reader);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001365 if (val < 0){
1366 reader->mode = XML_TEXTREADER_MODE_ERROR;
1367 reader->state = XML_TEXTREADER_ERROR;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001368 return(-1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001369 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001370 if (reader->node == NULL)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001371 goto node_end;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001372 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001373 if (oldstate != XML_TEXTREADER_BACKTRACK) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001374 if ((reader->node->children != NULL) &&
1375 (reader->node->type != XML_ENTITY_REF_NODE) &&
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001376 (reader->node->type != XML_XINCLUDE_START) &&
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001377 (reader->node->type != XML_DTD_NODE)) {
1378 reader->node = reader->node->children;
1379 reader->depth++;
Daniel Veillarddf512f42002-12-23 15:56:21 +00001380 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001381 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001382 }
1383 }
1384 if (reader->node->next != NULL) {
1385 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillarddf512f42002-12-23 15:56:21 +00001386 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001387 (reader->node->children == NULL) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001388 ((reader->node->extra & NODE_IS_EMPTY) == 0)
1389#ifdef LIBXML_XINCLUDE_ENABLED
1390 && (reader->in_xinclude <= 0)
1391#endif
1392 ) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001393 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001394 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001395 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001396#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00001397 if ((reader->validate) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001398 (reader->node->type == XML_ELEMENT_NODE))
1399 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001400#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001401 if ((reader->preserves > 0) &&
1402 (reader->node->extra & NODE_IS_SPRESERVED))
1403 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001404 reader->node = reader->node->next;
1405 reader->state = XML_TEXTREADER_ELEMENT;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001406
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001407 /*
1408 * Cleanup of the old node
1409 */
Daniel Veillard1e906612003-12-05 14:57:46 +00001410 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001411#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001412 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001413#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001414 (reader->entNr == 0) &&
1415 (reader->node->prev != NULL) &&
Daniel Veillardeea38152013-01-28 16:55:30 +01001416 (reader->node->prev->type != XML_DTD_NODE)) {
Daniel Veillard4dbe77a2003-01-14 00:17:42 +00001417 xmlNodePtr tmp = reader->node->prev;
Daniel Veillarde8039df2003-10-27 11:25:13 +00001418 if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001419 xmlUnlinkNode(tmp);
1420 xmlTextReaderFreeNode(reader, tmp);
1421 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001422 }
1423
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001424 goto node_found;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001425 }
Daniel Veillardea7751d2002-12-20 00:16:24 +00001426 if ((oldstate == XML_TEXTREADER_ELEMENT) &&
Daniel Veillard571b8892002-12-30 12:37:59 +00001427 (reader->node->type == XML_ELEMENT_NODE) &&
Daniel Veillard067bae52003-01-05 01:27:54 +00001428 (reader->node->children == NULL) &&
Daniel Veillarde8039df2003-10-27 11:25:13 +00001429 ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001430 reader->state = XML_TEXTREADER_END;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001431 goto node_found;
Daniel Veillardea7751d2002-12-20 00:16:24 +00001432 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001433#ifdef LIBXML_REGEXP_ENABLED
Gaurav Guptad319eb92014-10-06 12:24:17 +08001434 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001435 xmlTextReaderValidatePop(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001436#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001437 if ((reader->preserves > 0) &&
1438 (reader->node->extra & NODE_IS_SPRESERVED))
1439 reader->preserves--;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001440 reader->node = reader->node->parent;
1441 if ((reader->node == NULL) ||
1442 (reader->node->type == XML_DOCUMENT_NODE) ||
1443#ifdef LIBXML_DOCB_ENABLED
1444 (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1445#endif
1446 (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillarda9c56772007-03-09 16:59:05 +00001447 if (reader->mode != XML_TEXTREADER_MODE_EOF) {
Daniel Veillardea7751d2002-12-20 00:16:24 +00001448 val = xmlParseChunk(reader->ctxt, "", 0, 1);
Daniel Veillarda9c56772007-03-09 16:59:05 +00001449 reader->state = XML_TEXTREADER_DONE;
William M. Brack9f797ab2004-07-28 07:40:12 +00001450 if (val != 0)
1451 return(-1);
Daniel Veillardea7751d2002-12-20 00:16:24 +00001452 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001453 reader->node = NULL;
Daniel Veillard4d8db8a2002-12-30 18:40:42 +00001454 reader->depth = -1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001455
1456 /*
1457 * Cleanup of the old node
1458 */
Daniel Veillard76d36452009-09-07 11:19:33 +02001459 if ((oldnode != NULL) && (reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001460#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001461 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001462#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001463 (reader->entNr == 0) &&
1464 (oldnode->type != XML_DTD_NODE) &&
Daniel Veillardeea38152013-01-28 16:55:30 +01001465 ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001466 xmlUnlinkNode(oldnode);
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001467 xmlTextReaderFreeNode(reader, oldnode);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001468 }
1469
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001470 goto node_end;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001471 }
Daniel Veillard1e906612003-12-05 14:57:46 +00001472 if ((reader->preserves == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001473#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard1e906612003-12-05 14:57:46 +00001474 (reader->in_xinclude == 0) &&
Daniel Veillard96b6cd22004-01-08 16:49:50 +00001475#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00001476 (reader->entNr == 0) &&
1477 (reader->node->last != NULL) &&
1478 ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1479 xmlNodePtr tmp = reader->node->last;
1480 xmlUnlinkNode(tmp);
1481 xmlTextReaderFreeNode(reader, tmp);
1482 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001483 reader->depth--;
1484 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001485
1486node_found:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001487 DUMP_READER
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001488
1489 /*
Daniel Veillarda880b122003-04-21 21:36:41 +00001490 * If we are in the middle of a piece of CDATA make sure it's finished
1491 */
1492 if ((reader->node != NULL) &&
Daniel Veillardccc4d2b2003-09-17 21:27:31 +00001493 (reader->node->next == NULL) &&
Daniel Veillarda880b122003-04-21 21:36:41 +00001494 ((reader->node->type == XML_TEXT_NODE) ||
1495 (reader->node->type == XML_CDATA_SECTION_NODE))) {
William M. Brack42331a92004-07-29 07:07:16 +00001496 if (xmlTextReaderExpand(reader) == NULL)
1497 return -1;
Daniel Veillarda880b122003-04-21 21:36:41 +00001498 }
1499
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001500#ifdef LIBXML_XINCLUDE_ENABLED
1501 /*
1502 * Handle XInclude if asked for
1503 */
1504 if ((reader->xinclude) && (reader->node != NULL) &&
1505 (reader->node->type == XML_ELEMENT_NODE) &&
1506 (reader->node->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001507 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1508 (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001509 if (reader->xincctxt == NULL) {
1510 reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001511 xmlXIncludeSetFlags(reader->xincctxt,
Daniel Veillardc14c3892004-08-16 12:34:50 +00001512 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001513 }
1514 /*
1515 * expand that node and process it
1516 */
William M. Brack42331a92004-07-29 07:07:16 +00001517 if (xmlTextReaderExpand(reader) == NULL)
1518 return -1;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001519 xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1520 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001521 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001522 reader->in_xinclude++;
1523 goto get_next_node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001524 }
Daniel Veillard11ce4002006-03-10 00:36:23 +00001525 if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001526 reader->in_xinclude--;
1527 goto get_next_node;
1528 }
1529#endif
Daniel Veillarda880b122003-04-21 21:36:41 +00001530 /*
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001531 * Handle entities enter and exit when in entity replacement mode
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001532 */
1533 if ((reader->node != NULL) &&
1534 (reader->node->type == XML_ENTITY_REF_NODE) &&
1535 (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1536 /*
1537 * Case where the underlying tree is not availble, lookup the entity
1538 * and walk it.
1539 */
1540 if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1541 (reader->ctxt->sax->getEntity != NULL)) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001542 reader->node->children = (xmlNodePtr)
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001543 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1544 }
1545
1546 if ((reader->node->children != NULL) &&
1547 (reader->node->children->type == XML_ENTITY_DECL) &&
1548 (reader->node->children->children != NULL)) {
1549 xmlTextReaderEntPush(reader, reader->node);
1550 reader->node = reader->node->children->children;
1551 }
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001552#ifdef LIBXML_REGEXP_ENABLED
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001553 } else if ((reader->node != NULL) &&
1554 (reader->node->type == XML_ENTITY_REF_NODE) &&
Daniel Veillardf4e55762003-04-15 23:32:22 +00001555 (reader->ctxt != NULL) && (reader->validate)) {
Daniel Veillarda80ff6e2003-01-03 12:52:08 +00001556 xmlTextReaderValidateEntity(reader);
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001557#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001558 }
1559 if ((reader->node != NULL) &&
1560 (reader->node->type == XML_ENTITY_DECL) &&
1561 (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1562 reader->node = xmlTextReaderEntPop(reader);
1563 reader->depth++;
1564 goto get_next_node;
1565 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001566#ifdef LIBXML_REGEXP_ENABLED
Gaurav Guptad319eb92014-10-06 12:24:17 +08001567 if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001568 xmlNodePtr node = reader->node;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001569
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001570 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001571 ((reader->state != XML_TEXTREADER_END) &&
1572 (reader->state != XML_TEXTREADER_BACKTRACK))) {
1573 xmlTextReaderValidatePush(reader);
1574 } else if ((node->type == XML_TEXT_NODE) ||
1575 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillardf4e55762003-04-15 23:32:22 +00001576 xmlTextReaderValidateCData(reader, node->content,
1577 xmlStrlen(node->content));
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001578 }
1579 }
Daniel Veillard0e298ad2003-02-04 16:14:33 +00001580#endif /* LIBXML_REGEXP_ENABLED */
Daniel Veillard1e906612003-12-05 14:57:46 +00001581#ifdef LIBXML_PATTERN_ENABLED
1582 if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1583 (reader->state != XML_TEXTREADER_BACKTRACK)) {
1584 int i;
1585 for (i = 0;i < reader->patternNr;i++) {
1586 if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1587 xmlTextReaderPreserve(reader);
1588 break;
1589 }
1590 }
1591 }
1592#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillardf10ae122005-07-10 19:03:16 +00001593#ifdef LIBXML_SCHEMAS_ENABLED
1594 if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001595 (reader->xsdValidErrors == 0) &&
Daniel Veillardf10ae122005-07-10 19:03:16 +00001596 (reader->xsdValidCtxt != NULL)) {
1597 reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1598 }
1599#endif /* LIBXML_PATTERN_ENABLED */
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001600 return(1);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001601node_end:
Daniel Veillarda9c56772007-03-09 16:59:05 +00001602 reader->state = XML_TEXTREADER_DONE;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00001603 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001604}
1605
Daniel Veillard67df8092002-12-16 22:04:11 +00001606/**
1607 * xmlTextReaderReadState:
1608 * @reader: the xmlTextReaderPtr used
1609 *
1610 * Gets the read state of the reader.
1611 *
1612 * Returns the state value, or -1 in case of error
1613 */
1614int
1615xmlTextReaderReadState(xmlTextReaderPtr reader) {
1616 if (reader == NULL)
1617 return(-1);
1618 return(reader->mode);
1619}
1620
1621/**
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001622 * xmlTextReaderExpand:
1623 * @reader: the xmlTextReaderPtr used
1624 *
1625 * Reads the contents of the current node and the full subtree. It then makes
Daniel Veillard61c52202003-04-30 12:20:34 +00001626 * the subtree available until the next xmlTextReaderRead() call
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001627 *
1628 * Returns a node pointer valid until the next xmlTextReaderRead() call
1629 * or NULL in case of error.
1630 */
1631xmlNodePtr
1632xmlTextReaderExpand(xmlTextReaderPtr reader) {
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001633 if ((reader == NULL) || (reader->node == NULL))
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001634 return(NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001635 if (reader->doc != NULL)
1636 return(reader->node);
Daniel Veillardf40c1ce2003-12-19 17:26:28 +00001637 if (reader->ctxt == NULL)
1638 return(NULL);
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001639 if (xmlTextReaderDoExpand(reader) < 0)
1640 return(NULL);
1641 return(reader->node);
1642}
1643
1644/**
1645 * xmlTextReaderNext:
1646 * @reader: the xmlTextReaderPtr used
1647 *
1648 * Skip to the node following the current one in document order while
1649 * avoiding the subtree if any.
1650 *
1651 * Returns 1 if the node was read successfully, 0 if there is no more
1652 * nodes to read, or -1 in case of error
1653 */
1654int
1655xmlTextReaderNext(xmlTextReaderPtr reader) {
1656 int ret;
1657 xmlNodePtr cur;
1658
1659 if (reader == NULL)
1660 return(-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001661 if (reader->doc != NULL)
1662 return(xmlTextReaderNextTree(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001663 cur = reader->node;
1664 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1665 return(xmlTextReaderRead(reader));
Daniel Veillard5963aa72005-03-10 12:23:24 +00001666 if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001667 return(xmlTextReaderRead(reader));
Daniel Veillarde8039df2003-10-27 11:25:13 +00001668 if (cur->extra & NODE_IS_EMPTY)
Daniel Veillard9ee35f32003-09-28 00:19:54 +00001669 return(xmlTextReaderRead(reader));
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001670 do {
1671 ret = xmlTextReaderRead(reader);
1672 if (ret != 1)
1673 return(ret);
1674 } while (reader->node != cur);
1675 return(xmlTextReaderRead(reader));
1676}
1677
Daniel Veillardd0271472006-01-02 10:22:02 +00001678#ifdef LIBXML_WRITER_ENABLED
Daniel Veillardc6cae7b2003-04-11 09:02:11 +00001679/**
Daniel Veillard67df8092002-12-16 22:04:11 +00001680 * xmlTextReaderReadInnerXml:
1681 * @reader: the xmlTextReaderPtr used
1682 *
1683 * Reads the contents of the current node, including child nodes and markup.
1684 *
1685 * Returns a string containing the XML content, or NULL if the current node
Daniel Veillardaacc2a22009-08-11 18:31:42 +02001686 * is neither an element nor attribute, or has no child nodes. The
Daniel Veillard67df8092002-12-16 22:04:11 +00001687 * string must be deallocated by the caller.
1688 */
1689xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001690xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1691{
1692 xmlChar *resbuf;
1693 xmlNodePtr node, cur_node;
1694 xmlBufferPtr buff, buff2;
1695 xmlDocPtr doc;
1696
1697 if (xmlTextReaderExpand(reader) == NULL) {
1698 return NULL;
1699 }
1700 doc = reader->doc;
1701 buff = xmlBufferCreate();
1702 for (cur_node = reader->node->children; cur_node != NULL;
1703 cur_node = cur_node->next) {
1704 node = xmlDocCopyNode(cur_node, doc, 1);
1705 buff2 = xmlBufferCreate();
1706 if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1707 xmlFreeNode(node);
1708 xmlBufferFree(buff2);
1709 xmlBufferFree(buff);
1710 return NULL;
1711 }
1712 xmlBufferCat(buff, buff2->content);
1713 xmlFreeNode(node);
1714 xmlBufferFree(buff2);
1715 }
1716 resbuf = buff->content;
Daniel Veillardbc4cc9d2005-12-12 13:26:56 +00001717 buff->content = NULL;
1718
1719 xmlBufferFree(buff);
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001720 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001721}
Daniel Veillardd0271472006-01-02 10:22:02 +00001722#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001723
Daniel Veillardd0271472006-01-02 10:22:02 +00001724#ifdef LIBXML_WRITER_ENABLED
Daniel Veillard67df8092002-12-16 22:04:11 +00001725/**
1726 * xmlTextReaderReadOuterXml:
1727 * @reader: the xmlTextReaderPtr used
1728 *
1729 * Reads the contents of the current node, including child nodes and markup.
1730 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001731 * Returns a string containing the node and any XML content, or NULL if the
1732 * current node cannot be serialized. The string must be deallocated
Rob Richards5b9dde32010-05-05 07:59:44 -04001733 * by the caller.
Daniel Veillard67df8092002-12-16 22:04:11 +00001734 */
1735xmlChar *
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001736xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1737{
1738 xmlChar *resbuf;
1739 xmlNodePtr node;
1740 xmlBufferPtr buff;
1741 xmlDocPtr doc;
1742
1743 node = reader->node;
1744 doc = reader->doc;
1745 if (xmlTextReaderExpand(reader) == NULL) {
1746 return NULL;
1747 }
Rob Richards5b9dde32010-05-05 07:59:44 -04001748 if (node->type == XML_DTD_NODE) {
1749 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1750 } else {
1751 node = xmlDocCopyNode(node, doc, 1);
1752 }
Daniel Veillardda6f4af2005-06-20 17:17:54 +00001753 buff = xmlBufferCreate();
1754 if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1755 xmlFreeNode(node);
1756 xmlBufferFree(buff);
1757 return NULL;
1758 }
1759
1760 resbuf = buff->content;
1761 buff->content = NULL;
1762
1763 xmlFreeNode(node);
1764 xmlBufferFree(buff);
1765 return resbuf;
Daniel Veillard67df8092002-12-16 22:04:11 +00001766}
Daniel Veillardd0271472006-01-02 10:22:02 +00001767#endif
Daniel Veillard67df8092002-12-16 22:04:11 +00001768
1769/**
1770 * xmlTextReaderReadString:
1771 * @reader: the xmlTextReaderPtr used
1772 *
1773 * Reads the contents of an element or a text node as a string.
1774 *
1775 * Returns a string containing the contents of the Element or Text node,
1776 * or NULL if the reader is positioned on any other type of node.
1777 * The string must be deallocated by the caller.
1778 */
1779xmlChar *
Daniel Veillarde125b312005-01-28 17:39:49 +00001780xmlTextReaderReadString(xmlTextReaderPtr reader)
1781{
1782 xmlNodePtr node;
1783
1784 if ((reader == NULL) || (reader->node == NULL))
1785 return(NULL);
1786
1787 node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1788 switch (node->type) {
1789 case XML_TEXT_NODE:
1790 if (node->content != NULL)
1791 return(xmlStrdup(node->content));
1792 break;
1793 case XML_ELEMENT_NODE:
1794 if (xmlTextReaderDoExpand(reader) != -1) {
1795 return xmlTextReaderCollectSiblings(node->children);
1796 }
Gaurav Guptad319eb92014-10-06 12:24:17 +08001797 break;
Daniel Veillarde125b312005-01-28 17:39:49 +00001798 case XML_ATTRIBUTE_NODE:
1799 TODO
1800 break;
1801 default:
1802 break;
1803 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001804 return(NULL);
1805}
1806
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001807#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001808/**
1809 * xmlTextReaderReadBase64:
1810 * @reader: the xmlTextReaderPtr used
1811 * @array: a byte array to store the content.
1812 * @offset: the zero-based index into array where the method should
1813 * begin to write.
1814 * @len: the number of bytes to write.
1815 *
1816 * Reads and decodes the Base64 encoded contents of an element and
1817 * stores the result in a byte buffer.
1818 *
1819 * Returns the number of bytes written to array, or zero if the current
1820 * instance is not positioned on an element or -1 in case of error.
1821 */
1822int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001823xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1824 unsigned char *array ATTRIBUTE_UNUSED,
1825 int offset ATTRIBUTE_UNUSED,
1826 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001827 if ((reader == NULL) || (reader->ctxt == NULL))
1828 return(-1);
1829 if (reader->ctxt->wellFormed != 1)
1830 return(-1);
1831
1832 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1833 return(0);
1834 TODO
1835 return(0);
1836}
1837
1838/**
1839 * xmlTextReaderReadBinHex:
1840 * @reader: the xmlTextReaderPtr used
1841 * @array: a byte array to store the content.
1842 * @offset: the zero-based index into array where the method should
1843 * begin to write.
1844 * @len: the number of bytes to write.
1845 *
1846 * Reads and decodes the BinHex encoded contents of an element and
1847 * stores the result in a byte buffer.
1848 *
1849 * Returns the number of bytes written to array, or zero if the current
1850 * instance is not positioned on an element or -1 in case of error.
1851 */
1852int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001853xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1854 unsigned char *array ATTRIBUTE_UNUSED,
1855 int offset ATTRIBUTE_UNUSED,
1856 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001857 if ((reader == NULL) || (reader->ctxt == NULL))
1858 return(-1);
1859 if (reader->ctxt->wellFormed != 1)
1860 return(-1);
1861
1862 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1863 return(0);
1864 TODO
1865 return(0);
1866}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001867#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001868
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001869/************************************************************************
1870 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001871 * Operating on a preparsed tree *
1872 * *
1873 ************************************************************************/
1874static int
1875xmlTextReaderNextTree(xmlTextReaderPtr reader)
1876{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001877 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001878 return(-1);
1879
1880 if (reader->state == XML_TEXTREADER_END)
1881 return(0);
1882
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001883 if (reader->node == NULL) {
1884 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001885 reader->state = XML_TEXTREADER_END;
1886 return(0);
1887 }
1888
1889 reader->node = reader->doc->children;
1890 reader->state = XML_TEXTREADER_START;
1891 return(1);
1892 }
1893
1894 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001895 /* Here removed traversal to child, because we want to skip the subtree,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001896 replace with traversal to sibling to skip subtree */
1897 if (reader->node->next != 0) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001898 /* Move to sibling if present,skipping sub-tree */
1899 reader->node = reader->node->next;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001900 reader->state = XML_TEXTREADER_START;
1901 return(1);
1902 }
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001903
1904 /* if reader->node->next is NULL mean no subtree for current node,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001905 so need to move to sibling of parent node if present */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001906 if ((reader->node->type == XML_ELEMENT_NODE) ||
1907 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1908 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001909 /* This will move to parent if present */
1910 xmlTextReaderRead(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001911 }
1912 }
1913
1914 if (reader->node->next != 0) {
1915 reader->node = reader->node->next;
1916 reader->state = XML_TEXTREADER_START;
1917 return(1);
1918 }
1919
1920 if (reader->node->parent != 0) {
1921 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1922 reader->state = XML_TEXTREADER_END;
1923 return(0);
1924 }
1925
1926 reader->node = reader->node->parent;
1927 reader->depth--;
1928 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001929 /* Repeat process to move to sibling of parent node if present */
1930 xmlTextReaderNextTree(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001931 }
1932
1933 reader->state = XML_TEXTREADER_END;
1934
1935 return(1);
1936}
1937
1938/**
1939 * xmlTextReaderReadTree:
1940 * @reader: the xmlTextReaderPtr used
1941 *
1942 * Moves the position of the current instance to the next node in
1943 * the stream, exposing its properties.
1944 *
1945 * Returns 1 if the node was read successfully, 0 if there is no more
1946 * nodes to read, or -1 in case of error
1947 */
1948static int
1949xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1950 if (reader->state == XML_TEXTREADER_END)
1951 return(0);
1952
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001953next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001954 if (reader->node == NULL) {
1955 if (reader->doc->children == NULL) {
1956 reader->state = XML_TEXTREADER_END;
1957 return(0);
1958 }
1959
1960 reader->node = reader->doc->children;
1961 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001962 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001963 }
1964
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001965 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1966 (reader->node->type != XML_DTD_NODE) &&
1967 (reader->node->type != XML_XINCLUDE_START) &&
1968 (reader->node->type != XML_ENTITY_REF_NODE)) {
1969 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001970 reader->node = reader->node->children;
1971 reader->depth++;
1972 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001973 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001974 }
1975
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001976 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001977 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001978 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001979 }
1980 }
1981
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001982 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001983 reader->node = reader->node->next;
1984 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001985 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001986 }
1987
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001988 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001989 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1990 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1991 reader->state = XML_TEXTREADER_END;
1992 return(0);
1993 }
1994
1995 reader->node = reader->node->parent;
1996 reader->depth--;
1997 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001998 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001999 }
2000
2001 reader->state = XML_TEXTREADER_END;
2002
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002003found_node:
2004 if ((reader->node->type == XML_XINCLUDE_START) ||
2005 (reader->node->type == XML_XINCLUDE_END))
2006 goto next_node;
2007
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002008 return(1);
2009}
2010
2011/**
William M. Brackb1d53162003-11-18 06:54:40 +00002012 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002013 * @reader: the xmlTextReaderPtr used
2014 *
2015 * Skip to the node following the current one in document order while
2016 * avoiding the subtree if any.
2017 * Currently implemented only for Readers built on a document
2018 *
2019 * Returns 1 if the node was read successfully, 0 if there is no more
2020 * nodes to read, or -1 in case of error
2021 */
2022int
2023xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2024 if (reader == NULL)
2025 return(-1);
2026 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002027 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002028 return(-1);
2029 }
2030
2031 if (reader->state == XML_TEXTREADER_END)
2032 return(0);
2033
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002034 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002035 return(xmlTextReaderNextTree(reader));
2036
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002037 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002038 reader->node = reader->node->next;
2039 reader->state = XML_TEXTREADER_START;
2040 return(1);
2041 }
2042
2043 return(0);
2044}
2045
2046/************************************************************************
2047 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002048 * Constructor and destructors *
2049 * *
2050 ************************************************************************/
2051/**
2052 * xmlNewTextReader:
2053 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002054 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002055 *
2056 * Create an xmlTextReader structure fed with @input
2057 *
2058 * Returns the new xmlTextReaderPtr or NULL in case of error
2059 */
2060xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002061xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002062 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002063
2064 if (input == NULL)
2065 return(NULL);
2066 ret = xmlMalloc(sizeof(xmlTextReader));
2067 if (ret == NULL) {
2068 xmlGenericError(xmlGenericErrorContext,
2069 "xmlNewTextReader : malloc failed\n");
2070 return(NULL);
2071 }
2072 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002073 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002074 ret->entTab = NULL;
2075 ret->entMax = 0;
2076 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002077 ret->input = input;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002078 ret->buffer = xmlBufCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002079 if (ret->buffer == NULL) {
2080 xmlFree(ret);
2081 xmlGenericError(xmlGenericErrorContext,
2082 "xmlNewTextReader : malloc failed\n");
2083 return(NULL);
2084 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002085 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2086 if (ret->sax == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08002087 xmlBufFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002088 xmlFree(ret);
2089 xmlGenericError(xmlGenericErrorContext,
2090 "xmlNewTextReader : malloc failed\n");
2091 return(NULL);
2092 }
Daniel Veillard81273902003-09-30 00:43:48 +00002093 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002094 ret->startElement = ret->sax->startElement;
2095 ret->sax->startElement = xmlTextReaderStartElement;
2096 ret->endElement = ret->sax->endElement;
2097 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002098#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002099 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002100#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002101 ret->startElementNs = ret->sax->startElementNs;
2102 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2103 ret->endElementNs = ret->sax->endElementNs;
2104 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002105#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002106 } else {
2107 ret->startElementNs = NULL;
2108 ret->endElementNs = NULL;
2109 }
Daniel Veillard81273902003-09-30 00:43:48 +00002110#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002111 ret->characters = ret->sax->characters;
2112 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002113 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002114 ret->cdataBlock = ret->sax->cdataBlock;
2115 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002116
Daniel Veillard67df8092002-12-16 22:04:11 +00002117 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002118 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002119 ret->curnode = NULL;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002120 if (xmlBufUse(ret->input->buffer) < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002121 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002122 }
Daniel Veillard8aebce32012-07-16 14:42:31 +08002123 if (xmlBufUse(ret->input->buffer) >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002124 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08002125 (const char *) xmlBufContent(ret->input->buffer),
2126 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002127 ret->base = 0;
2128 ret->cur = 4;
2129 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002130 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002131 ret->base = 0;
2132 ret->cur = 0;
2133 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002134
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002135 if (ret->ctxt == NULL) {
2136 xmlGenericError(xmlGenericErrorContext,
2137 "xmlNewTextReader : malloc failed\n");
Daniel Veillard8aebce32012-07-16 14:42:31 +08002138 xmlBufFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002139 xmlFree(ret->sax);
2140 xmlFree(ret);
2141 return(NULL);
2142 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002143 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002144 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002145 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002146 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002147 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002148 /*
2149 * use the parser dictionnary to allocate all elements and attributes names
2150 */
2151 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002152 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002153#ifdef LIBXML_XINCLUDE_ENABLED
2154 ret->xinclude = 0;
2155#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002156#ifdef LIBXML_PATTERN_ENABLED
2157 ret->patternMax = 0;
2158 ret->patternTab = NULL;
2159#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002160 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002161}
2162
2163/**
2164 * xmlNewTextReaderFilename:
2165 * @URI: the URI of the resource to process
2166 *
2167 * Create an xmlTextReader structure fed with the resource at @URI
2168 *
2169 * Returns the new xmlTextReaderPtr or NULL in case of error
2170 */
2171xmlTextReaderPtr
2172xmlNewTextReaderFilename(const char *URI) {
2173 xmlParserInputBufferPtr input;
2174 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002175 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002176
2177 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2178 if (input == NULL)
2179 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002180 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002181 if (ret == NULL) {
2182 xmlFreeParserInputBuffer(input);
2183 return(NULL);
2184 }
2185 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002186 if (ret->ctxt->directory == NULL)
2187 directory = xmlParserGetDirectory(URI);
2188 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2189 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2190 if (directory != NULL)
2191 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002192 return(ret);
2193}
2194
2195/**
2196 * xmlFreeTextReader:
2197 * @reader: the xmlTextReaderPtr
2198 *
2199 * Deallocate all the resources associated to the reader
2200 */
2201void
2202xmlFreeTextReader(xmlTextReaderPtr reader) {
2203 if (reader == NULL)
2204 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002205#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002206 if (reader->rngSchemas != NULL) {
2207 xmlRelaxNGFree(reader->rngSchemas);
2208 reader->rngSchemas = NULL;
2209 }
2210 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08002211 if (! reader->rngPreserveCtxt)
2212 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillardf4e55762003-04-15 23:32:22 +00002213 reader->rngValidCtxt = NULL;
2214 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002215 if (reader->xsdPlug != NULL) {
2216 xmlSchemaSAXUnplug(reader->xsdPlug);
2217 reader->xsdPlug = NULL;
2218 }
2219 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002220 if (! reader->xsdPreserveCtxt)
2221 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002222 reader->xsdValidCtxt = NULL;
2223 }
2224 if (reader->xsdSchemas != NULL) {
2225 xmlSchemaFree(reader->xsdSchemas);
2226 reader->xsdSchemas = NULL;
2227 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002228#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002229#ifdef LIBXML_XINCLUDE_ENABLED
2230 if (reader->xincctxt != NULL)
2231 xmlXIncludeFreeContext(reader->xincctxt);
2232#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002233#ifdef LIBXML_PATTERN_ENABLED
2234 if (reader->patternTab != NULL) {
2235 int i;
2236 for (i = 0;i < reader->patternNr;i++) {
2237 if (reader->patternTab[i] != NULL)
2238 xmlFreePattern(reader->patternTab[i]);
2239 }
2240 xmlFree(reader->patternTab);
2241 }
2242#endif
Daniel Veillardf4653dc2009-08-21 18:40:50 +02002243 if (reader->faketext != NULL) {
2244 xmlFreeNode(reader->faketext);
2245 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002246 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002247 if (reader->dict == reader->ctxt->dict)
2248 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002249 if (reader->ctxt->myDoc != NULL) {
2250 if (reader->preserve == 0)
2251 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2252 reader->ctxt->myDoc = NULL;
2253 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002254 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2255 (reader->ctxt->vctxt.vstateMax > 0)){
2256 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002257 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002258 reader->ctxt->vctxt.vstateMax = 0;
2259 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002260 if (reader->allocs & XML_TEXTREADER_CTXT)
2261 xmlFreeParserCtxt(reader->ctxt);
2262 }
2263 if (reader->sax != NULL)
2264 xmlFree(reader->sax);
2265 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2266 xmlFreeParserInputBuffer(reader->input);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002267 if (reader->buffer != NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08002268 xmlBufFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002269 if (reader->entTab != NULL)
2270 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002271 if (reader->dict != NULL)
2272 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002273 xmlFree(reader);
2274}
2275
2276/************************************************************************
2277 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002278 * Methods for XmlTextReader *
2279 * *
2280 ************************************************************************/
2281/**
2282 * xmlTextReaderClose:
2283 * @reader: the xmlTextReaderPtr used
2284 *
2285 * This method releases any resources allocated by the current instance
2286 * changes the state to Closed and close any underlying input.
2287 *
2288 * Returns 0 or -1 in case of error
2289 */
2290int
2291xmlTextReaderClose(xmlTextReaderPtr reader) {
2292 if (reader == NULL)
2293 return(-1);
2294 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002295 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002296 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2297 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002298 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002299 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002300 if (reader->preserve == 0)
2301 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002302 reader->ctxt->myDoc = NULL;
2303 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002304 }
2305 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2306 xmlFreeParserInputBuffer(reader->input);
2307 reader->allocs -= XML_TEXTREADER_INPUT;
2308 }
2309 return(0);
2310}
2311
2312/**
2313 * xmlTextReaderGetAttributeNo:
2314 * @reader: the xmlTextReaderPtr used
2315 * @no: the zero-based index of the attribute relative to the containing element
2316 *
2317 * Provides the value of the attribute with the specified index relative
2318 * to the containing element.
2319 *
2320 * Returns a string containing the value of the specified attribute, or NULL
2321 * in case of error. The string must be deallocated by the caller.
2322 */
2323xmlChar *
2324xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2325 xmlChar *ret;
2326 int i;
2327 xmlAttrPtr cur;
2328 xmlNsPtr ns;
2329
2330 if (reader == NULL)
2331 return(NULL);
2332 if (reader->node == NULL)
2333 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002334 if (reader->curnode != NULL)
2335 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002336 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002337 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002338 return(NULL);
2339
2340 ns = reader->node->nsDef;
2341 for (i = 0;(i < no) && (ns != NULL);i++) {
2342 ns = ns->next;
2343 }
2344 if (ns != NULL)
2345 return(xmlStrdup(ns->href));
2346
2347 cur = reader->node->properties;
2348 if (cur == NULL)
2349 return(NULL);
2350 for (;i < no;i++) {
2351 cur = cur->next;
2352 if (cur == NULL)
2353 return(NULL);
2354 }
2355 /* TODO walk the DTD if present */
2356
2357 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2358 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2359 return(ret);
2360}
2361
2362/**
2363 * xmlTextReaderGetAttribute:
2364 * @reader: the xmlTextReaderPtr used
2365 * @name: the qualified name of the attribute.
2366 *
2367 * Provides the value of the attribute with the specified qualified name.
2368 *
2369 * Returns a string containing the value of the specified attribute, or NULL
2370 * in case of error. The string must be deallocated by the caller.
2371 */
2372xmlChar *
2373xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2374 xmlChar *prefix = NULL;
2375 xmlChar *localname;
2376 xmlNsPtr ns;
2377 xmlChar *ret = NULL;
2378
2379 if ((reader == NULL) || (name == NULL))
2380 return(NULL);
2381 if (reader->node == NULL)
2382 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002383 if (reader->curnode != NULL)
2384 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002385
2386 /* TODO: handle the xmlDecl */
2387 if (reader->node->type != XML_ELEMENT_NODE)
2388 return(NULL);
2389
2390 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002391 if (localname == NULL) {
2392 /*
2393 * Namespace default decl
2394 */
2395 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2396 ns = reader->node->nsDef;
2397 while (ns != NULL) {
2398 if (ns->prefix == NULL) {
2399 return(xmlStrdup(ns->href));
2400 }
2401 ns = ns->next;
2402 }
2403 return NULL;
2404 }
2405 return(xmlGetNoNsProp(reader->node, name));
2406 }
2407
2408 /*
2409 * Namespace default decl
2410 */
2411 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2412 ns = reader->node->nsDef;
2413 while (ns != NULL) {
2414 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2415 ret = xmlStrdup(ns->href);
2416 break;
2417 }
2418 ns = ns->next;
2419 }
2420 } else {
2421 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2422 if (ns != NULL)
2423 ret = xmlGetNsProp(reader->node, localname, ns->href);
2424 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002425
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002426 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002427 if (prefix != NULL)
2428 xmlFree(prefix);
2429 return(ret);
2430}
2431
2432
2433/**
2434 * xmlTextReaderGetAttributeNs:
2435 * @reader: the xmlTextReaderPtr used
2436 * @localName: the local name of the attribute.
2437 * @namespaceURI: the namespace URI of the attribute.
2438 *
2439 * Provides the value of the specified attribute
2440 *
2441 * Returns a string containing the value of the specified attribute, or NULL
2442 * in case of error. The string must be deallocated by the caller.
2443 */
2444xmlChar *
2445xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2446 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002447 xmlChar *prefix = NULL;
2448 xmlNsPtr ns;
2449
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002450 if ((reader == NULL) || (localName == NULL))
2451 return(NULL);
2452 if (reader->node == NULL)
2453 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002454 if (reader->curnode != NULL)
2455 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002456
2457 /* TODO: handle the xmlDecl */
2458 if (reader->node->type != XML_ELEMENT_NODE)
2459 return(NULL);
2460
Daniel Veillard45b97e72005-08-20 21:14:28 +00002461 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2462 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2463 prefix = BAD_CAST localName;
2464 }
2465 ns = reader->node->nsDef;
2466 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002467 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002468 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2469 return xmlStrdup(ns->href);
2470 }
2471 ns = ns->next;
2472 }
2473 return NULL;
2474 }
2475
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002476 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2477}
2478
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002479/**
2480 * xmlTextReaderGetRemainder:
2481 * @reader: the xmlTextReaderPtr used
2482 *
2483 * Method to get the remainder of the buffered XML. this method stops the
2484 * parser, set its state to End Of File and return the input stream with
2485 * what is left that the parser did not use.
2486 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002487 * The implementation is not good, the parser certainly procgressed past
2488 * what's left in reader->input, and there is an allocation problem. Best
2489 * would be to rewrite it differently.
2490 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002491 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2492 * in case of error.
2493 */
2494xmlParserInputBufferPtr
2495xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2496 xmlParserInputBufferPtr ret = NULL;
2497
2498 if (reader == NULL)
2499 return(NULL);
2500 if (reader->node == NULL)
2501 return(NULL);
2502
2503 reader->node = NULL;
2504 reader->curnode = NULL;
2505 reader->mode = XML_TEXTREADER_MODE_EOF;
2506 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002507 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002508 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002509 if (reader->preserve == 0)
2510 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002511 reader->ctxt->myDoc = NULL;
2512 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002513 }
2514 if (reader->allocs & XML_TEXTREADER_INPUT) {
2515 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002516 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002517 reader->allocs -= XML_TEXTREADER_INPUT;
2518 } else {
2519 /*
2520 * Hum, one may need to duplicate the data structure because
2521 * without reference counting the input may be freed twice:
2522 * - by the layer which allocated it.
2523 * - by the layer to which would have been returned to.
2524 */
2525 TODO
2526 return(NULL);
2527 }
2528 return(ret);
2529}
2530
2531/**
2532 * xmlTextReaderLookupNamespace:
2533 * @reader: the xmlTextReaderPtr used
2534 * @prefix: the prefix whose namespace URI is to be resolved. To return
2535 * the default namespace, specify NULL
2536 *
2537 * Resolves a namespace prefix in the scope of the current element.
2538 *
2539 * Returns a string containing the namespace URI to which the prefix maps
2540 * or NULL in case of error. The string must be deallocated by the caller.
2541 */
2542xmlChar *
2543xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2544 xmlNsPtr ns;
2545
2546 if (reader == NULL)
2547 return(NULL);
2548 if (reader->node == NULL)
2549 return(NULL);
2550
2551 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2552 if (ns == NULL)
2553 return(NULL);
2554 return(xmlStrdup(ns->href));
2555}
2556
2557/**
2558 * xmlTextReaderMoveToAttributeNo:
2559 * @reader: the xmlTextReaderPtr used
2560 * @no: the zero-based index of the attribute relative to the containing
2561 * element.
2562 *
2563 * Moves the position of the current instance to the attribute with
2564 * the specified index relative to the containing element.
2565 *
2566 * Returns 1 in case of success, -1 in case of error, 0 if not found
2567 */
2568int
2569xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2570 int i;
2571 xmlAttrPtr cur;
2572 xmlNsPtr ns;
2573
2574 if (reader == NULL)
2575 return(-1);
2576 if (reader->node == NULL)
2577 return(-1);
2578 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002579 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002580 return(-1);
2581
2582 reader->curnode = NULL;
2583
2584 ns = reader->node->nsDef;
2585 for (i = 0;(i < no) && (ns != NULL);i++) {
2586 ns = ns->next;
2587 }
2588 if (ns != NULL) {
2589 reader->curnode = (xmlNodePtr) ns;
2590 return(1);
2591 }
2592
2593 cur = reader->node->properties;
2594 if (cur == NULL)
2595 return(0);
2596 for (;i < no;i++) {
2597 cur = cur->next;
2598 if (cur == NULL)
2599 return(0);
2600 }
2601 /* TODO walk the DTD if present */
2602
2603 reader->curnode = (xmlNodePtr) cur;
2604 return(1);
2605}
2606
2607/**
2608 * xmlTextReaderMoveToAttribute:
2609 * @reader: the xmlTextReaderPtr used
2610 * @name: the qualified name of the attribute.
2611 *
2612 * Moves the position of the current instance to the attribute with
2613 * the specified qualified name.
2614 *
2615 * Returns 1 in case of success, -1 in case of error, 0 if not found
2616 */
2617int
2618xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2619 xmlChar *prefix = NULL;
2620 xmlChar *localname;
2621 xmlNsPtr ns;
2622 xmlAttrPtr prop;
2623
2624 if ((reader == NULL) || (name == NULL))
2625 return(-1);
2626 if (reader->node == NULL)
2627 return(-1);
2628
2629 /* TODO: handle the xmlDecl */
2630 if (reader->node->type != XML_ELEMENT_NODE)
2631 return(0);
2632
2633 localname = xmlSplitQName2(name, &prefix);
2634 if (localname == NULL) {
2635 /*
2636 * Namespace default decl
2637 */
2638 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2639 ns = reader->node->nsDef;
2640 while (ns != NULL) {
2641 if (ns->prefix == NULL) {
2642 reader->curnode = (xmlNodePtr) ns;
2643 return(1);
2644 }
2645 ns = ns->next;
2646 }
2647 return(0);
2648 }
2649
2650 prop = reader->node->properties;
2651 while (prop != NULL) {
2652 /*
2653 * One need to have
2654 * - same attribute names
2655 * - and the attribute carrying that namespace
2656 */
2657 if ((xmlStrEqual(prop->name, name)) &&
2658 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2659 reader->curnode = (xmlNodePtr) prop;
2660 return(1);
2661 }
2662 prop = prop->next;
2663 }
2664 return(0);
2665 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002666
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002667 /*
2668 * Namespace default decl
2669 */
2670 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2671 ns = reader->node->nsDef;
2672 while (ns != NULL) {
2673 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2674 reader->curnode = (xmlNodePtr) ns;
2675 goto found;
2676 }
2677 ns = ns->next;
2678 }
2679 goto not_found;
2680 }
2681 prop = reader->node->properties;
2682 while (prop != NULL) {
2683 /*
2684 * One need to have
2685 * - same attribute names
2686 * - and the attribute carrying that namespace
2687 */
2688 if ((xmlStrEqual(prop->name, localname)) &&
2689 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2690 reader->curnode = (xmlNodePtr) prop;
2691 goto found;
2692 }
2693 prop = prop->next;
2694 }
2695not_found:
2696 if (localname != NULL)
2697 xmlFree(localname);
2698 if (prefix != NULL)
2699 xmlFree(prefix);
2700 return(0);
2701
2702found:
2703 if (localname != NULL)
2704 xmlFree(localname);
2705 if (prefix != NULL)
2706 xmlFree(prefix);
2707 return(1);
2708}
2709
2710/**
2711 * xmlTextReaderMoveToAttributeNs:
2712 * @reader: the xmlTextReaderPtr used
2713 * @localName: the local name of the attribute.
2714 * @namespaceURI: the namespace URI of the attribute.
2715 *
2716 * Moves the position of the current instance to the attribute with the
2717 * specified local name and namespace URI.
2718 *
2719 * Returns 1 in case of success, -1 in case of error, 0 if not found
2720 */
2721int
2722xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2723 const xmlChar *localName, const xmlChar *namespaceURI) {
2724 xmlAttrPtr prop;
2725 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002726 xmlNsPtr ns;
2727 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002728
2729 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2730 return(-1);
2731 if (reader->node == NULL)
2732 return(-1);
2733 if (reader->node->type != XML_ELEMENT_NODE)
2734 return(0);
2735 node = reader->node;
2736
Daniel Veillard45b97e72005-08-20 21:14:28 +00002737 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2738 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2739 prefix = BAD_CAST localName;
2740 }
2741 ns = reader->node->nsDef;
2742 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002743 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002744 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2745 reader->curnode = (xmlNodePtr) ns;
2746 return(1);
2747 }
2748 ns = ns->next;
2749 }
2750 return(0);
2751 }
2752
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002753 prop = node->properties;
2754 while (prop != NULL) {
2755 /*
2756 * One need to have
2757 * - same attribute names
2758 * - and the attribute carrying that namespace
2759 */
2760 if (xmlStrEqual(prop->name, localName) &&
2761 ((prop->ns != NULL) &&
2762 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2763 reader->curnode = (xmlNodePtr) prop;
2764 return(1);
2765 }
2766 prop = prop->next;
2767 }
2768 return(0);
2769}
2770
2771/**
2772 * xmlTextReaderMoveToFirstAttribute:
2773 * @reader: the xmlTextReaderPtr used
2774 *
2775 * Moves the position of the current instance to the first attribute
2776 * associated with the current node.
2777 *
2778 * Returns 1 in case of success, -1 in case of error, 0 if not found
2779 */
2780int
2781xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2782 if (reader == NULL)
2783 return(-1);
2784 if (reader->node == NULL)
2785 return(-1);
2786 if (reader->node->type != XML_ELEMENT_NODE)
2787 return(0);
2788
2789 if (reader->node->nsDef != NULL) {
2790 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2791 return(1);
2792 }
2793 if (reader->node->properties != NULL) {
2794 reader->curnode = (xmlNodePtr) reader->node->properties;
2795 return(1);
2796 }
2797 return(0);
2798}
2799
2800/**
2801 * xmlTextReaderMoveToNextAttribute:
2802 * @reader: the xmlTextReaderPtr used
2803 *
2804 * Moves the position of the current instance to the next attribute
2805 * associated with the current node.
2806 *
2807 * Returns 1 in case of success, -1 in case of error, 0 if not found
2808 */
2809int
2810xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2811 if (reader == NULL)
2812 return(-1);
2813 if (reader->node == NULL)
2814 return(-1);
2815 if (reader->node->type != XML_ELEMENT_NODE)
2816 return(0);
2817 if (reader->curnode == NULL)
2818 return(xmlTextReaderMoveToFirstAttribute(reader));
2819
2820 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2821 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2822 if (ns->next != NULL) {
2823 reader->curnode = (xmlNodePtr) ns->next;
2824 return(1);
2825 }
2826 if (reader->node->properties != NULL) {
2827 reader->curnode = (xmlNodePtr) reader->node->properties;
2828 return(1);
2829 }
2830 return(0);
2831 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2832 (reader->curnode->next != NULL)) {
2833 reader->curnode = reader->curnode->next;
2834 return(1);
2835 }
2836 return(0);
2837}
2838
2839/**
2840 * xmlTextReaderMoveToElement:
2841 * @reader: the xmlTextReaderPtr used
2842 *
2843 * Moves the position of the current instance to the node that
2844 * contains the current Attribute node.
2845 *
2846 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2847 */
2848int
2849xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2850 if (reader == NULL)
2851 return(-1);
2852 if (reader->node == NULL)
2853 return(-1);
2854 if (reader->node->type != XML_ELEMENT_NODE)
2855 return(0);
2856 if (reader->curnode != NULL) {
2857 reader->curnode = NULL;
2858 return(1);
2859 }
2860 return(0);
2861}
2862
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002863/**
2864 * xmlTextReaderReadAttributeValue:
2865 * @reader: the xmlTextReaderPtr used
2866 *
2867 * Parses an attribute value into one or more Text and EntityReference nodes.
2868 *
2869 * Returns 1 in case of success, 0 if the reader was not positionned on an
2870 * ttribute node or all the attribute values have been read, or -1
2871 * in case of error.
2872 */
2873int
2874xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2875 if (reader == NULL)
2876 return(-1);
2877 if (reader->node == NULL)
2878 return(-1);
2879 if (reader->curnode == NULL)
2880 return(0);
2881 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2882 if (reader->curnode->children == NULL)
2883 return(0);
2884 reader->curnode = reader->curnode->children;
2885 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2886 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2887
2888 if (reader->faketext == NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002889 reader->faketext = xmlNewDocText(reader->node->doc,
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002890 ns->href);
2891 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002892 if ((reader->faketext->content != NULL) &&
2893 (reader->faketext->content !=
2894 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002895 xmlFree(reader->faketext->content);
2896 reader->faketext->content = xmlStrdup(ns->href);
2897 }
2898 reader->curnode = reader->faketext;
2899 } else {
2900 if (reader->curnode->next == NULL)
2901 return(0);
2902 reader->curnode = reader->curnode->next;
2903 }
2904 return(1);
2905}
2906
Daniel Veillarde2811272004-10-19 09:04:23 +00002907/**
2908 * xmlTextReaderConstEncoding:
2909 * @reader: the xmlTextReaderPtr used
2910 *
2911 * Determine the encoding of the document being read.
2912 *
2913 * Returns a string containing the encoding of the document or NULL in
2914 * case of error. The string is deallocated with the reader.
2915 */
2916const xmlChar *
2917xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2918 xmlDocPtr doc = NULL;
2919 if (reader == NULL)
2920 return(NULL);
2921 if (reader->doc != NULL)
2922 doc = reader->doc;
2923 else if (reader->ctxt != NULL)
2924 doc = reader->ctxt->myDoc;
2925 if (doc == NULL)
2926 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002927
Daniel Veillarde2811272004-10-19 09:04:23 +00002928 if (doc->encoding == NULL)
2929 return(NULL);
2930 else
2931 return(CONSTSTR(doc->encoding));
2932}
2933
2934
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002935/************************************************************************
2936 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002937 * Acces API to the current node *
2938 * *
2939 ************************************************************************/
2940/**
2941 * xmlTextReaderAttributeCount:
2942 * @reader: the xmlTextReaderPtr used
2943 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002944 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002945 *
2946 * Returns 0 i no attributes, -1 in case of error or the attribute count
2947 */
2948int
2949xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2950 int ret;
2951 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002952 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002953 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002954
2955 if (reader == NULL)
2956 return(-1);
2957 if (reader->node == NULL)
2958 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002959
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002960 if (reader->curnode != NULL)
2961 node = reader->curnode;
2962 else
2963 node = reader->node;
2964
2965 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002966 return(0);
2967 if ((reader->state == XML_TEXTREADER_END) ||
2968 (reader->state == XML_TEXTREADER_BACKTRACK))
2969 return(0);
2970 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002971 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002972 while (attr != NULL) {
2973 ret++;
2974 attr = attr->next;
2975 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002976 ns = node->nsDef;
2977 while (ns != NULL) {
2978 ret++;
2979 ns = ns->next;
2980 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002981 return(ret);
2982}
2983
2984/**
2985 * xmlTextReaderNodeType:
2986 * @reader: the xmlTextReaderPtr used
2987 *
2988 * Get the node type of the current node
2989 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002990 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002991 *
2992 * Returns the xmlNodeType of the current node or -1 in case of error
2993 */
2994int
2995xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002996 xmlNodePtr node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002997
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002998 if (reader == NULL)
2999 return(-1);
3000 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00003001 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003002 if (reader->curnode != NULL)
3003 node = reader->curnode;
3004 else
3005 node = reader->node;
3006 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003007 case XML_ELEMENT_NODE:
3008 if ((reader->state == XML_TEXTREADER_END) ||
3009 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00003010 return(XML_READER_TYPE_END_ELEMENT);
3011 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00003012 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003013 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003014 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003015 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003016 if (xmlIsBlankNode(reader->node)) {
3017 if (xmlNodeGetSpacePreserve(reader->node))
3018 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3019 else
3020 return(XML_READER_TYPE_WHITESPACE);
3021 } else {
3022 return(XML_READER_TYPE_TEXT);
3023 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003024 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003025 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003026 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003027 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003028 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003029 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003030 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003031 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003032 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003033 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003034 case XML_DOCUMENT_NODE:
3035 case XML_HTML_DOCUMENT_NODE:
3036#ifdef LIBXML_DOCB_ENABLED
3037 case XML_DOCB_DOCUMENT_NODE:
3038#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00003039 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003040 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003041 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003042 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003043 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003044 case XML_DOCUMENT_TYPE_NODE:
3045 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003046 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003047
3048 case XML_ELEMENT_DECL:
3049 case XML_ATTRIBUTE_DECL:
3050 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003051 case XML_XINCLUDE_START:
3052 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003053 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003054 }
3055 return(-1);
3056}
3057
3058/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003059 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003060 * @reader: the xmlTextReaderPtr used
3061 *
3062 * Check if the current node is empty
3063 *
3064 * Returns 1 if empty, 0 if not and -1 in case of error
3065 */
3066int
3067xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3068 if ((reader == NULL) || (reader->node == NULL))
3069 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003070 if (reader->node->type != XML_ELEMENT_NODE)
3071 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003072 if (reader->curnode != NULL)
3073 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003074 if (reader->node->children != NULL)
3075 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003076 if (reader->state == XML_TEXTREADER_END)
3077 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003078 if (reader->doc != NULL)
3079 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003080#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003081 if (reader->in_xinclude > 0)
3082 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003083#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003084 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003085}
3086
3087/**
3088 * xmlTextReaderLocalName:
3089 * @reader: the xmlTextReaderPtr used
3090 *
3091 * The local name of the node.
3092 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003093 * Returns the local name or NULL if not available,
3094 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003095 */
3096xmlChar *
3097xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003098 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003099 if ((reader == NULL) || (reader->node == NULL))
3100 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003101 if (reader->curnode != NULL)
3102 node = reader->curnode;
3103 else
3104 node = reader->node;
3105 if (node->type == XML_NAMESPACE_DECL) {
3106 xmlNsPtr ns = (xmlNsPtr) node;
3107 if (ns->prefix == NULL)
3108 return(xmlStrdup(BAD_CAST "xmlns"));
3109 else
3110 return(xmlStrdup(ns->prefix));
3111 }
3112 if ((node->type != XML_ELEMENT_NODE) &&
3113 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003114 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003115 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003116}
3117
3118/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003119 * xmlTextReaderConstLocalName:
3120 * @reader: the xmlTextReaderPtr used
3121 *
3122 * The local name of the node.
3123 *
3124 * Returns the local name or NULL if not available, the
3125 * string will be deallocated with the reader.
3126 */
3127const xmlChar *
3128xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3129 xmlNodePtr node;
3130 if ((reader == NULL) || (reader->node == NULL))
3131 return(NULL);
3132 if (reader->curnode != NULL)
3133 node = reader->curnode;
3134 else
3135 node = reader->node;
3136 if (node->type == XML_NAMESPACE_DECL) {
3137 xmlNsPtr ns = (xmlNsPtr) node;
3138 if (ns->prefix == NULL)
3139 return(CONSTSTR(BAD_CAST "xmlns"));
3140 else
3141 return(ns->prefix);
3142 }
3143 if ((node->type != XML_ELEMENT_NODE) &&
3144 (node->type != XML_ATTRIBUTE_NODE))
3145 return(xmlTextReaderConstName(reader));
3146 return(node->name);
3147}
3148
3149/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003150 * xmlTextReaderName:
3151 * @reader: the xmlTextReaderPtr used
3152 *
3153 * The qualified name of the node, equal to Prefix :LocalName.
3154 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003155 * Returns the local name or NULL if not available,
3156 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003157 */
3158xmlChar *
3159xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003160 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003161 xmlChar *ret;
3162
3163 if ((reader == NULL) || (reader->node == NULL))
3164 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003165 if (reader->curnode != NULL)
3166 node = reader->curnode;
3167 else
3168 node = reader->node;
3169 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003170 case XML_ELEMENT_NODE:
3171 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003172 if ((node->ns == NULL) ||
3173 (node->ns->prefix == NULL))
3174 return(xmlStrdup(node->name));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003175
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003176 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003177 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003178 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003179 return(ret);
3180 case XML_TEXT_NODE:
3181 return(xmlStrdup(BAD_CAST "#text"));
3182 case XML_CDATA_SECTION_NODE:
3183 return(xmlStrdup(BAD_CAST "#cdata-section"));
3184 case XML_ENTITY_NODE:
3185 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003186 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003187 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003188 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003189 case XML_COMMENT_NODE:
3190 return(xmlStrdup(BAD_CAST "#comment"));
3191 case XML_DOCUMENT_NODE:
3192 case XML_HTML_DOCUMENT_NODE:
3193#ifdef LIBXML_DOCB_ENABLED
3194 case XML_DOCB_DOCUMENT_NODE:
3195#endif
3196 return(xmlStrdup(BAD_CAST "#document"));
3197 case XML_DOCUMENT_FRAG_NODE:
3198 return(xmlStrdup(BAD_CAST "#document-fragment"));
3199 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003200 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003201 case XML_DOCUMENT_TYPE_NODE:
3202 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003203 return(xmlStrdup(node->name));
3204 case XML_NAMESPACE_DECL: {
3205 xmlNsPtr ns = (xmlNsPtr) node;
3206
3207 ret = xmlStrdup(BAD_CAST "xmlns");
3208 if (ns->prefix == NULL)
3209 return(ret);
3210 ret = xmlStrcat(ret, BAD_CAST ":");
3211 ret = xmlStrcat(ret, ns->prefix);
3212 return(ret);
3213 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003214
3215 case XML_ELEMENT_DECL:
3216 case XML_ATTRIBUTE_DECL:
3217 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003218 case XML_XINCLUDE_START:
3219 case XML_XINCLUDE_END:
3220 return(NULL);
3221 }
3222 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003223}
3224
3225/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003226 * xmlTextReaderConstName:
3227 * @reader: the xmlTextReaderPtr used
3228 *
3229 * The qualified name of the node, equal to Prefix :LocalName.
3230 *
3231 * Returns the local name or NULL if not available, the string is
3232 * deallocated with the reader.
3233 */
3234const xmlChar *
3235xmlTextReaderConstName(xmlTextReaderPtr reader) {
3236 xmlNodePtr node;
3237
3238 if ((reader == NULL) || (reader->node == NULL))
3239 return(NULL);
3240 if (reader->curnode != NULL)
3241 node = reader->curnode;
3242 else
3243 node = reader->node;
3244 switch (node->type) {
3245 case XML_ELEMENT_NODE:
3246 case XML_ATTRIBUTE_NODE:
3247 if ((node->ns == NULL) ||
3248 (node->ns->prefix == NULL))
3249 return(node->name);
3250 return(CONSTQSTR(node->ns->prefix, node->name));
3251 case XML_TEXT_NODE:
3252 return(CONSTSTR(BAD_CAST "#text"));
3253 case XML_CDATA_SECTION_NODE:
3254 return(CONSTSTR(BAD_CAST "#cdata-section"));
3255 case XML_ENTITY_NODE:
3256 case XML_ENTITY_REF_NODE:
3257 return(CONSTSTR(node->name));
3258 case XML_PI_NODE:
3259 return(CONSTSTR(node->name));
3260 case XML_COMMENT_NODE:
3261 return(CONSTSTR(BAD_CAST "#comment"));
3262 case XML_DOCUMENT_NODE:
3263 case XML_HTML_DOCUMENT_NODE:
3264#ifdef LIBXML_DOCB_ENABLED
3265 case XML_DOCB_DOCUMENT_NODE:
3266#endif
3267 return(CONSTSTR(BAD_CAST "#document"));
3268 case XML_DOCUMENT_FRAG_NODE:
3269 return(CONSTSTR(BAD_CAST "#document-fragment"));
3270 case XML_NOTATION_NODE:
3271 return(CONSTSTR(node->name));
3272 case XML_DOCUMENT_TYPE_NODE:
3273 case XML_DTD_NODE:
3274 return(CONSTSTR(node->name));
3275 case XML_NAMESPACE_DECL: {
3276 xmlNsPtr ns = (xmlNsPtr) node;
3277
3278 if (ns->prefix == NULL)
3279 return(CONSTSTR(BAD_CAST "xmlns"));
3280 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3281 }
3282
3283 case XML_ELEMENT_DECL:
3284 case XML_ATTRIBUTE_DECL:
3285 case XML_ENTITY_DECL:
3286 case XML_XINCLUDE_START:
3287 case XML_XINCLUDE_END:
3288 return(NULL);
3289 }
3290 return(NULL);
3291}
3292
3293/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003294 * xmlTextReaderPrefix:
3295 * @reader: the xmlTextReaderPtr used
3296 *
3297 * A shorthand reference to the namespace associated with the node.
3298 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003299 * Returns the prefix or NULL if not available,
3300 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003301 */
3302xmlChar *
3303xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003304 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003305 if ((reader == NULL) || (reader->node == NULL))
3306 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003307 if (reader->curnode != NULL)
3308 node = reader->curnode;
3309 else
3310 node = reader->node;
3311 if (node->type == XML_NAMESPACE_DECL) {
3312 xmlNsPtr ns = (xmlNsPtr) node;
3313 if (ns->prefix == NULL)
3314 return(NULL);
3315 return(xmlStrdup(BAD_CAST "xmlns"));
3316 }
3317 if ((node->type != XML_ELEMENT_NODE) &&
3318 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003319 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003320 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003321 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003322 return(NULL);
3323}
3324
3325/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003326 * xmlTextReaderConstPrefix:
3327 * @reader: the xmlTextReaderPtr used
3328 *
3329 * A shorthand reference to the namespace associated with the node.
3330 *
3331 * Returns the prefix or NULL if not available, the string is deallocated
3332 * with the reader.
3333 */
3334const xmlChar *
3335xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3336 xmlNodePtr node;
3337 if ((reader == NULL) || (reader->node == NULL))
3338 return(NULL);
3339 if (reader->curnode != NULL)
3340 node = reader->curnode;
3341 else
3342 node = reader->node;
3343 if (node->type == XML_NAMESPACE_DECL) {
3344 xmlNsPtr ns = (xmlNsPtr) node;
3345 if (ns->prefix == NULL)
3346 return(NULL);
3347 return(CONSTSTR(BAD_CAST "xmlns"));
3348 }
3349 if ((node->type != XML_ELEMENT_NODE) &&
3350 (node->type != XML_ATTRIBUTE_NODE))
3351 return(NULL);
3352 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3353 return(CONSTSTR(node->ns->prefix));
3354 return(NULL);
3355}
3356
3357/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003358 * xmlTextReaderNamespaceUri:
3359 * @reader: the xmlTextReaderPtr used
3360 *
3361 * The URI defining the namespace associated with the node.
3362 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003363 * Returns the namespace URI or NULL if not available,
3364 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003365 */
3366xmlChar *
3367xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003368 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003369 if ((reader == NULL) || (reader->node == NULL))
3370 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003371 if (reader->curnode != NULL)
3372 node = reader->curnode;
3373 else
3374 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003375 if (node->type == XML_NAMESPACE_DECL)
3376 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003377 if ((node->type != XML_ELEMENT_NODE) &&
3378 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003379 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003380 if (node->ns != NULL)
3381 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003382 return(NULL);
3383}
3384
3385/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003386 * xmlTextReaderConstNamespaceUri:
3387 * @reader: the xmlTextReaderPtr used
3388 *
3389 * The URI defining the namespace associated with the node.
3390 *
3391 * Returns the namespace URI or NULL if not available, the string
3392 * will be deallocated with the reader
3393 */
3394const xmlChar *
3395xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3396 xmlNodePtr node;
3397 if ((reader == NULL) || (reader->node == NULL))
3398 return(NULL);
3399 if (reader->curnode != NULL)
3400 node = reader->curnode;
3401 else
3402 node = reader->node;
3403 if (node->type == XML_NAMESPACE_DECL)
3404 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3405 if ((node->type != XML_ELEMENT_NODE) &&
3406 (node->type != XML_ATTRIBUTE_NODE))
3407 return(NULL);
3408 if (node->ns != NULL)
3409 return(CONSTSTR(node->ns->href));
3410 return(NULL);
3411}
3412
3413/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003414 * xmlTextReaderBaseUri:
3415 * @reader: the xmlTextReaderPtr used
3416 *
3417 * The base URI of the node.
3418 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003419 * Returns the base URI or NULL if not available,
3420 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003421 */
3422xmlChar *
3423xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3424 if ((reader == NULL) || (reader->node == NULL))
3425 return(NULL);
3426 return(xmlNodeGetBase(NULL, reader->node));
3427}
3428
3429/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003430 * xmlTextReaderConstBaseUri:
3431 * @reader: the xmlTextReaderPtr used
3432 *
3433 * The base URI of the node.
3434 *
3435 * Returns the base URI or NULL if not available, the string
3436 * will be deallocated with the reader
3437 */
3438const xmlChar *
3439xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3440 xmlChar *tmp;
3441 const xmlChar *ret;
3442
3443 if ((reader == NULL) || (reader->node == NULL))
3444 return(NULL);
3445 tmp = xmlNodeGetBase(NULL, reader->node);
3446 if (tmp == NULL)
3447 return(NULL);
3448 ret = CONSTSTR(tmp);
3449 xmlFree(tmp);
3450 return(ret);
3451}
3452
3453/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003454 * xmlTextReaderDepth:
3455 * @reader: the xmlTextReaderPtr used
3456 *
3457 * The depth of the node in the tree.
3458 *
3459 * Returns the depth or -1 in case of error
3460 */
3461int
3462xmlTextReaderDepth(xmlTextReaderPtr reader) {
3463 if (reader == NULL)
3464 return(-1);
3465 if (reader->node == NULL)
3466 return(0);
3467
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003468 if (reader->curnode != NULL) {
3469 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3470 (reader->curnode->type == XML_NAMESPACE_DECL))
3471 return(reader->depth + 1);
3472 return(reader->depth + 2);
3473 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003474 return(reader->depth);
3475}
3476
3477/**
3478 * xmlTextReaderHasAttributes:
3479 * @reader: the xmlTextReaderPtr used
3480 *
3481 * Whether the node has attributes.
3482 *
3483 * Returns 1 if true, 0 if false, and -1 in case or error
3484 */
3485int
3486xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003487 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003488 if (reader == NULL)
3489 return(-1);
3490 if (reader->node == NULL)
3491 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003492 if (reader->curnode != NULL)
3493 node = reader->curnode;
3494 else
3495 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003496
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003497 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003498 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003499 return(1);
3500 /* TODO: handle the xmlDecl */
3501 return(0);
3502}
3503
3504/**
3505 * xmlTextReaderHasValue:
3506 * @reader: the xmlTextReaderPtr used
3507 *
3508 * Whether the node can have a text value.
3509 *
3510 * Returns 1 if true, 0 if false, and -1 in case or error
3511 */
3512int
3513xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003514 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003515 if (reader == NULL)
3516 return(-1);
3517 if (reader->node == NULL)
3518 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003519 if (reader->curnode != NULL)
3520 node = reader->curnode;
3521 else
3522 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003523
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003524 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003525 case XML_ATTRIBUTE_NODE:
3526 case XML_TEXT_NODE:
3527 case XML_CDATA_SECTION_NODE:
3528 case XML_PI_NODE:
3529 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003530 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003531 return(1);
3532 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003533 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003534 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003535 return(0);
3536}
3537
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003538/**
3539 * xmlTextReaderValue:
3540 * @reader: the xmlTextReaderPtr used
3541 *
3542 * Provides the text value of the node if present
3543 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003544 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003545 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003546 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003547xmlChar *
3548xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003549 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003550 if (reader == NULL)
3551 return(NULL);
3552 if (reader->node == NULL)
3553 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003554 if (reader->curnode != NULL)
3555 node = reader->curnode;
3556 else
3557 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003558
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003559 switch (node->type) {
3560 case XML_NAMESPACE_DECL:
3561 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003562 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003563 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003564
3565 if (attr->parent != NULL)
3566 return (xmlNodeListGetString
3567 (attr->parent->doc, attr->children, 1));
3568 else
3569 return (xmlNodeListGetString(NULL, attr->children, 1));
3570 break;
3571 }
3572 case XML_TEXT_NODE:
3573 case XML_CDATA_SECTION_NODE:
3574 case XML_PI_NODE:
3575 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003576 if (node->content != NULL)
3577 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003578 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003579 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003580 }
3581 return(NULL);
3582}
3583
3584/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003585 * xmlTextReaderConstValue:
3586 * @reader: the xmlTextReaderPtr used
3587 *
3588 * Provides the text value of the node if present
3589 *
3590 * Returns the string or NULL if not available. The result will be
3591 * deallocated on the next Read() operation.
3592 */
3593const xmlChar *
3594xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3595 xmlNodePtr node;
3596 if (reader == NULL)
3597 return(NULL);
3598 if (reader->node == NULL)
3599 return(NULL);
3600 if (reader->curnode != NULL)
3601 node = reader->curnode;
3602 else
3603 node = reader->node;
3604
3605 switch (node->type) {
3606 case XML_NAMESPACE_DECL:
3607 return(((xmlNsPtr) node)->href);
3608 case XML_ATTRIBUTE_NODE:{
3609 xmlAttrPtr attr = (xmlAttrPtr) node;
3610
3611 if ((attr->children != NULL) &&
3612 (attr->children->type == XML_TEXT_NODE) &&
3613 (attr->children->next == NULL))
3614 return(attr->children->content);
3615 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003616 if (reader->buffer == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08003617 reader->buffer = xmlBufCreateSize(100);
3618 if (reader->buffer == NULL) {
3619 xmlGenericError(xmlGenericErrorContext,
3620 "xmlTextReaderSetup : malloc failed\n");
3621 return (NULL);
3622 }
3623 } else
3624 xmlBufEmpty(reader->buffer);
3625 xmlBufGetNodeContent(reader->buffer, node);
3626 return(xmlBufContent(reader->buffer));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003627 }
3628 break;
3629 }
3630 case XML_TEXT_NODE:
3631 case XML_CDATA_SECTION_NODE:
3632 case XML_PI_NODE:
3633 case XML_COMMENT_NODE:
3634 return(node->content);
3635 default:
3636 break;
3637 }
3638 return(NULL);
3639}
3640
3641/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003642 * xmlTextReaderIsDefault:
3643 * @reader: the xmlTextReaderPtr used
3644 *
3645 * Whether an Attribute node was generated from the default value
3646 * defined in the DTD or schema.
3647 *
3648 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3649 */
3650int
3651xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3652 if (reader == NULL)
3653 return(-1);
3654 return(0);
3655}
3656
3657/**
3658 * xmlTextReaderQuoteChar:
3659 * @reader: the xmlTextReaderPtr used
3660 *
3661 * The quotation mark character used to enclose the value of an attribute.
3662 *
3663 * Returns " or ' and -1 in case of error
3664 */
3665int
3666xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3667 if (reader == NULL)
3668 return(-1);
3669 /* TODO maybe lookup the attribute value for " first */
3670 return((int) '"');
3671}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003672
3673/**
3674 * xmlTextReaderXmlLang:
3675 * @reader: the xmlTextReaderPtr used
3676 *
3677 * The xml:lang scope within which the node resides.
3678 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003679 * Returns the xml:lang value or NULL if none exists.,
3680 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003681 */
3682xmlChar *
3683xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3684 if (reader == NULL)
3685 return(NULL);
3686 if (reader->node == NULL)
3687 return(NULL);
3688 return(xmlNodeGetLang(reader->node));
3689}
3690
Daniel Veillard67df8092002-12-16 22:04:11 +00003691/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003692 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003693 * @reader: the xmlTextReaderPtr used
3694 *
3695 * The xml:lang scope within which the node resides.
3696 *
3697 * Returns the xml:lang value or NULL if none exists.
3698 */
3699const xmlChar *
3700xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3701 xmlChar *tmp;
3702 const xmlChar *ret;
3703
3704 if (reader == NULL)
3705 return(NULL);
3706 if (reader->node == NULL)
3707 return(NULL);
3708 tmp = xmlNodeGetLang(reader->node);
3709 if (tmp == NULL)
3710 return(NULL);
3711 ret = CONSTSTR(tmp);
3712 xmlFree(tmp);
3713 return(ret);
3714}
3715
3716/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003717 * xmlTextReaderConstString:
3718 * @reader: the xmlTextReaderPtr used
3719 * @str: the string to intern.
3720 *
3721 * Get an interned string from the reader, allows for example to
3722 * speedup string name comparisons
3723 *
3724 * Returns an interned copy of the string or NULL in case of error. The
3725 * string will be deallocated with the reader.
3726 */
3727const xmlChar *
3728xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3729 if (reader == NULL)
3730 return(NULL);
3731 return(CONSTSTR(str));
3732}
3733
3734/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003735 * xmlTextReaderNormalization:
3736 * @reader: the xmlTextReaderPtr used
3737 *
3738 * The value indicating whether to normalize white space and attribute values.
3739 * Since attribute value and end of line normalizations are a MUST in the XML
3740 * specification only the value true is accepted. The broken bahaviour of
3741 * accepting out of range character entities like &#0; is of course not
3742 * supported either.
3743 *
3744 * Returns 1 or -1 in case of error.
3745 */
3746int
3747xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3748 if (reader == NULL)
3749 return(-1);
3750 return(1);
3751}
3752
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003753/************************************************************************
3754 * *
3755 * Extensions to the base APIs *
3756 * *
3757 ************************************************************************/
3758
3759/**
3760 * xmlTextReaderSetParserProp:
3761 * @reader: the xmlTextReaderPtr used
3762 * @prop: the xmlParserProperties to set
3763 * @value: usually 0 or 1 to (de)activate it
3764 *
3765 * Change the parser processing behaviour by changing some of its internal
3766 * properties. Note that some properties can only be changed before any
3767 * read has been done.
3768 *
3769 * Returns 0 if the call was successful, or -1 in case of error
3770 */
3771int
3772xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3773 xmlParserProperties p = (xmlParserProperties) prop;
3774 xmlParserCtxtPtr ctxt;
3775
3776 if ((reader == NULL) || (reader->ctxt == NULL))
3777 return(-1);
3778 ctxt = reader->ctxt;
3779
3780 switch (p) {
3781 case XML_PARSER_LOADDTD:
3782 if (value != 0) {
3783 if (ctxt->loadsubset == 0) {
3784 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3785 return(-1);
3786 ctxt->loadsubset = XML_DETECT_IDS;
3787 }
3788 } else {
3789 ctxt->loadsubset = 0;
3790 }
3791 return(0);
3792 case XML_PARSER_DEFAULTATTRS:
3793 if (value != 0) {
3794 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3795 } else {
3796 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3797 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3798 }
3799 return(0);
3800 case XML_PARSER_VALIDATE:
3801 if (value != 0) {
3802 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003803 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003804 } else {
3805 ctxt->validate = 0;
3806 }
3807 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003808 case XML_PARSER_SUBST_ENTITIES:
3809 if (value != 0) {
3810 ctxt->replaceEntities = 1;
3811 } else {
3812 ctxt->replaceEntities = 0;
3813 }
3814 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003815 }
3816 return(-1);
3817}
3818
3819/**
3820 * xmlTextReaderGetParserProp:
3821 * @reader: the xmlTextReaderPtr used
3822 * @prop: the xmlParserProperties to get
3823 *
3824 * Read the parser internal property.
3825 *
3826 * Returns the value, usually 0 or 1, or -1 in case of error.
3827 */
3828int
3829xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3830 xmlParserProperties p = (xmlParserProperties) prop;
3831 xmlParserCtxtPtr ctxt;
3832
3833 if ((reader == NULL) || (reader->ctxt == NULL))
3834 return(-1);
3835 ctxt = reader->ctxt;
3836
3837 switch (p) {
3838 case XML_PARSER_LOADDTD:
3839 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3840 return(1);
3841 return(0);
3842 case XML_PARSER_DEFAULTATTRS:
3843 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3844 return(1);
3845 return(0);
3846 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003847 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003848 case XML_PARSER_SUBST_ENTITIES:
3849 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003850 }
3851 return(-1);
3852}
3853
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003854
Daniel Veillarde18fc182002-12-28 22:56:33 +00003855/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003856 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003857 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003858 *
3859 * Provide the line number of the current parsing point.
3860 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003861 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003862 */
3863int
3864xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3865{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003866 if ((reader == NULL) || (reader->ctxt == NULL) ||
3867 (reader->ctxt->input == NULL)) {
3868 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003869 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003870 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003871}
3872
3873/**
3874 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003875 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003876 *
3877 * Provide the column number of the current parsing point.
3878 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003879 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003880 */
3881int
3882xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3883{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003884 if ((reader == NULL) || (reader->ctxt == NULL) ||
3885 (reader->ctxt->input == NULL)) {
3886 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003887 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003888 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003889}
3890
3891/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003892 * xmlTextReaderCurrentNode:
3893 * @reader: the xmlTextReaderPtr used
3894 *
3895 * Hacking interface allowing to get the xmlNodePtr correponding to the
3896 * current node being accessed by the xmlTextReader. This is dangerous
3897 * because the underlying node may be destroyed on the next Reads.
3898 *
3899 * Returns the xmlNodePtr or NULL in case of error.
3900 */
3901xmlNodePtr
3902xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3903 if (reader == NULL)
3904 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003905
Daniel Veillarde18fc182002-12-28 22:56:33 +00003906 if (reader->curnode != NULL)
3907 return(reader->curnode);
3908 return(reader->node);
3909}
3910
3911/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003912 * xmlTextReaderPreserve:
3913 * @reader: the xmlTextReaderPtr used
3914 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003915 * This tells the XML Reader to preserve the current node.
3916 * The caller must also use xmlTextReaderCurrentDoc() to
3917 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003918 *
3919 * Returns the xmlNodePtr or NULL in case of error.
3920 */
3921xmlNodePtr
3922xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3923 xmlNodePtr cur, parent;
3924
3925 if (reader == NULL)
3926 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003927
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003928 if (reader->curnode != NULL)
3929 cur = reader->curnode;
3930 else
3931 cur = reader->node;
3932 if (cur == NULL)
3933 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003934
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003935 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003936 cur->extra |= NODE_IS_PRESERVED;
3937 cur->extra |= NODE_IS_SPRESERVED;
3938 }
3939 reader->preserves++;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003940
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003941 parent = cur->parent;;
3942 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003943 if (parent->type == XML_ELEMENT_NODE)
3944 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003945 parent = parent->parent;
3946 }
3947 return(cur);
3948}
3949
Daniel Veillard1e906612003-12-05 14:57:46 +00003950#ifdef LIBXML_PATTERN_ENABLED
3951/**
3952 * xmlTextReaderPreservePattern:
3953 * @reader: the xmlTextReaderPtr used
3954 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003955 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003956 *
Daniel Veillard1e906612003-12-05 14:57:46 +00003957 * This tells the XML Reader to preserve all nodes matched by the
3958 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3959 * keep an handle on the resulting document once parsing has finished
3960 *
3961 * Returns a positive number in case of success and -1 in case of error
3962 */
3963int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003964xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3965 const xmlChar **namespaces)
3966{
Daniel Veillard1e906612003-12-05 14:57:46 +00003967 xmlPatternPtr comp;
3968
3969 if ((reader == NULL) || (pattern == NULL))
3970 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003971
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003972 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003973 if (comp == NULL)
3974 return(-1);
3975
3976 if (reader->patternMax <= 0) {
3977 reader->patternMax = 4;
3978 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3979 sizeof(reader->patternTab[0]));
3980 if (reader->patternTab == NULL) {
3981 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3982 return (-1);
3983 }
3984 }
3985 if (reader->patternNr >= reader->patternMax) {
3986 xmlPatternPtr *tmp;
3987 reader->patternMax *= 2;
3988 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3989 reader->patternMax *
3990 sizeof(reader->patternTab[0]));
3991 if (tmp == NULL) {
3992 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3993 reader->patternMax /= 2;
3994 return (-1);
3995 }
3996 reader->patternTab = tmp;
3997 }
3998 reader->patternTab[reader->patternNr] = comp;
3999 return(reader->patternNr++);
4000}
4001#endif
4002
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004003/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00004004 * xmlTextReaderCurrentDoc:
4005 * @reader: the xmlTextReaderPtr used
4006 *
4007 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004008 * current document being accessed by the xmlTextReader.
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004009 * NOTE: as a result of this call, the reader will not destroy the
4010 * associated XML document and calling xmlFreeDoc() on the result
4011 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00004012 *
4013 * Returns the xmlDocPtr or NULL in case of error.
4014 */
4015xmlDocPtr
4016xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004017 if (reader == NULL)
4018 return(NULL);
4019 if (reader->doc != NULL)
4020 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00004021 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00004022 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004023
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004024 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00004025 return(reader->ctxt->myDoc);
4026}
4027
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004028#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004029static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004030
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004031static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004032xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4033
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004034static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004035xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4036
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004037static void XMLCDECL
4038xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004039{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004040 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004041
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004042 char *str;
4043
4044 va_list ap;
4045
4046 va_start(ap, msg);
4047 str = xmlTextReaderBuildMessage(msg, ap);
4048 if (!reader->errorFunc) {
4049 xmlTextReaderValidityError(ctx, "%s", str);
4050 } else {
4051 reader->errorFunc(reader->errorFuncArg, str,
4052 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4053 NULL /* locator */ );
4054 }
4055 if (str != NULL)
4056 xmlFree(str);
4057 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004058}
4059
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004060static void XMLCDECL
4061xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004062{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004063 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004064
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004065 char *str;
4066
4067 va_list ap;
4068
4069 va_start(ap, msg);
4070 str = xmlTextReaderBuildMessage(msg, ap);
4071 if (!reader->errorFunc) {
4072 xmlTextReaderValidityWarning(ctx, "%s", str);
4073 } else {
4074 reader->errorFunc(reader->errorFuncArg, str,
4075 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4076 NULL /* locator */ );
4077 }
4078 if (str != NULL)
4079 xmlFree(str);
4080 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004081}
4082
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004083static void
4084 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004085
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004086static void
4087xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004088{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004089 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004090
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004091 if (reader->sErrorFunc) {
4092 reader->sErrorFunc(reader->errorFuncArg, error);
4093 } else {
4094 xmlTextReaderStructuredError(reader, error);
4095 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004096}
Daniel Veillardf4e55762003-04-15 23:32:22 +00004097/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004098 * xmlTextReaderRelaxNGSetSchema:
4099 * @reader: the xmlTextReaderPtr used
4100 * @schema: a precompiled RelaxNG schema
4101 *
4102 * Use RelaxNG to validate the document as it is processed.
4103 * Activation is only possible before the first Read().
4104 * if @schema is NULL, then RelaxNG validation is desactivated.
4105 @ The @schema should not be freed until the reader is deallocated
4106 * or its use has been deactivated.
4107 *
4108 * Returns 0 in case the RelaxNG validation could be (des)activated and
4109 * -1 in case of error.
4110 */
4111int
4112xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004113 if (reader == NULL)
4114 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004115 if (schema == NULL) {
4116 if (reader->rngSchemas != NULL) {
4117 xmlRelaxNGFree(reader->rngSchemas);
4118 reader->rngSchemas = NULL;
4119 }
4120 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004121 if (! reader->rngPreserveCtxt)
4122 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004123 reader->rngValidCtxt = NULL;
4124 }
Noam Postavsky15794992012-03-19 16:08:16 +08004125 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004126 return(0);
4127 }
4128 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4129 return(-1);
4130 if (reader->rngSchemas != NULL) {
4131 xmlRelaxNGFree(reader->rngSchemas);
4132 reader->rngSchemas = NULL;
4133 }
4134 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004135 if (! reader->rngPreserveCtxt)
4136 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004137 reader->rngValidCtxt = NULL;
4138 }
Noam Postavsky15794992012-03-19 16:08:16 +08004139 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004140 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4141 if (reader->rngValidCtxt == NULL)
4142 return(-1);
4143 if (reader->errorFunc != NULL) {
4144 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004145 xmlTextReaderValidityErrorRelay,
4146 xmlTextReaderValidityWarningRelay,
4147 reader);
4148 }
4149 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004150 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004151 xmlTextReaderValidityStructuredRelay,
4152 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004153 }
4154 reader->rngValidErrors = 0;
4155 reader->rngFullNode = NULL;
4156 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4157 return(0);
4158}
4159
4160/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004161 * xmlTextReaderLocator:
4162 * @ctx: the xmlTextReaderPtr used
4163 * @file: returned file information
4164 * @line: returned line information
4165 *
4166 * Internal locator function for the readers
4167 *
4168 * Returns 0 in case the Schema validation could be (des)activated and
4169 * -1 in case of error.
4170 */
4171static int
4172xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4173 xmlTextReaderPtr reader;
4174
4175 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4176 return(-1);
4177
4178 if (file != NULL)
4179 *file = NULL;
4180 if (line != NULL)
4181 *line = 0;
4182
4183 reader = (xmlTextReaderPtr) ctx;
4184 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4185 if (file != NULL)
4186 *file = reader->ctxt->input->filename;
4187 if (line != NULL)
4188 *line = reader->ctxt->input->line;
4189 return(0);
4190 }
4191 if (reader->node != NULL) {
4192 long res;
4193 int ret = 0;
4194
4195 if (line != NULL) {
4196 res = xmlGetLineNo(reader->node);
4197 if (res > 0)
4198 *line = (unsigned long) res;
4199 else
4200 ret = -1;
4201 }
4202 if (file != NULL) {
4203 xmlDocPtr doc = reader->node->doc;
4204 if ((doc != NULL) && (doc->URL != NULL))
4205 *file = (const char *) doc->URL;
4206 else
4207 ret = -1;
4208 }
4209 return(ret);
4210 }
4211 return(-1);
4212}
4213
4214/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004215 * xmlTextReaderSetSchema:
4216 * @reader: the xmlTextReaderPtr used
4217 * @schema: a precompiled Schema schema
4218 *
4219 * Use XSD Schema to validate the document as it is processed.
4220 * Activation is only possible before the first Read().
4221 * if @schema is NULL, then Schema validation is desactivated.
4222 @ The @schema should not be freed until the reader is deallocated
4223 * or its use has been deactivated.
4224 *
4225 * Returns 0 in case the Schema validation could be (des)activated and
4226 * -1 in case of error.
4227 */
4228int
4229xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4230 if (reader == NULL)
4231 return(-1);
4232 if (schema == NULL) {
4233 if (reader->xsdPlug != NULL) {
4234 xmlSchemaSAXUnplug(reader->xsdPlug);
4235 reader->xsdPlug = NULL;
4236 }
4237 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004238 if (! reader->xsdPreserveCtxt)
4239 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004240 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004241 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004242 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004243 if (reader->xsdSchemas != NULL) {
4244 xmlSchemaFree(reader->xsdSchemas);
4245 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004246 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004247 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004248 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004249 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4250 return(-1);
4251 if (reader->xsdPlug != NULL) {
4252 xmlSchemaSAXUnplug(reader->xsdPlug);
4253 reader->xsdPlug = NULL;
4254 }
4255 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004256 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004257 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004258 reader->xsdValidCtxt = NULL;
4259 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004260 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004261 if (reader->xsdSchemas != NULL) {
4262 xmlSchemaFree(reader->xsdSchemas);
4263 reader->xsdSchemas = NULL;
4264 }
4265 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4266 if (reader->xsdValidCtxt == NULL) {
4267 xmlSchemaFree(reader->xsdSchemas);
4268 reader->xsdSchemas = NULL;
4269 return(-1);
4270 }
4271 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4272 &(reader->ctxt->sax),
4273 &(reader->ctxt->userData));
4274 if (reader->xsdPlug == NULL) {
4275 xmlSchemaFree(reader->xsdSchemas);
4276 reader->xsdSchemas = NULL;
4277 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4278 reader->xsdValidCtxt = NULL;
4279 return(-1);
4280 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004281 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4282 xmlTextReaderLocator,
4283 (void *) reader);
4284
Daniel Veillardf10ae122005-07-10 19:03:16 +00004285 if (reader->errorFunc != NULL) {
4286 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004287 xmlTextReaderValidityErrorRelay,
4288 xmlTextReaderValidityWarningRelay,
4289 reader);
4290 }
4291 if (reader->sErrorFunc != NULL) {
4292 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4293 xmlTextReaderValidityStructuredRelay,
4294 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004295 }
4296 reader->xsdValidErrors = 0;
4297 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4298 return(0);
4299}
4300
4301/**
Noam Postavsky15794992012-03-19 16:08:16 +08004302 * xmlTextReaderRelaxNGValidateInternal:
Daniel Veillardf4e55762003-04-15 23:32:22 +00004303 * @reader: the xmlTextReaderPtr used
4304 * @rng: the path to a RelaxNG schema or NULL
Noam Postavsky15794992012-03-19 16:08:16 +08004305 * @ctxt: the RelaxNG schema validation context or NULL
4306 * @options: options (not yet used)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004307 *
4308 * Use RelaxNG to validate the document as it is processed.
4309 * Activation is only possible before the first Read().
Noam Postavsky15794992012-03-19 16:08:16 +08004310 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004311 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004312 * Returns 0 in case the RelaxNG validation could be (de)activated and
Noam Postavsky15794992012-03-19 16:08:16 +08004313 * -1 in case of error.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004314 */
Noam Postavsky15794992012-03-19 16:08:16 +08004315static int
4316xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4317 const char *rng,
4318 xmlRelaxNGValidCtxtPtr ctxt,
4319 int options ATTRIBUTE_UNUSED)
4320{
Daniel Veillardf4e55762003-04-15 23:32:22 +00004321 if (reader == NULL)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004322 return(-1);
Noam Postavsky15794992012-03-19 16:08:16 +08004323
4324 if ((rng != NULL) && (ctxt != NULL))
4325 return (-1);
4326
4327 if (((rng != NULL) || (ctxt != NULL)) &&
4328 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4329 (reader->ctxt == NULL)))
4330 return(-1);
4331
4332 /* Cleanup previous validation stuff. */
4333 if (reader->rngValidCtxt != NULL) {
4334 if ( !reader->rngPreserveCtxt)
4335 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4336 reader->rngValidCtxt = NULL;
4337 }
4338 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004339 if (reader->rngSchemas != NULL) {
4340 xmlRelaxNGFree(reader->rngSchemas);
4341 reader->rngSchemas = NULL;
4342 }
Noam Postavsky15794992012-03-19 16:08:16 +08004343
4344 if ((rng == NULL) && (ctxt == NULL)) {
4345 /* We just want to deactivate the validation, so get out. */
4346 return(0);
Daniel Veillard33300b42003-04-17 09:09:19 +00004347 }
Noam Postavsky15794992012-03-19 16:08:16 +08004348
4349
4350 if (rng != NULL) {
4351 xmlRelaxNGParserCtxtPtr pctxt;
4352 /* Parse the schema and create validation environment. */
4353
4354 pctxt = xmlRelaxNGNewParserCtxt(rng);
4355 if (reader->errorFunc != NULL) {
4356 xmlRelaxNGSetParserErrors(pctxt,
4357 xmlTextReaderValidityErrorRelay,
4358 xmlTextReaderValidityWarningRelay,
4359 reader);
4360 }
4361 if (reader->sErrorFunc != NULL) {
4362 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4363 xmlTextReaderValidityStructuredRelay,
4364 reader);
4365 }
4366 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4367 xmlRelaxNGFreeParserCtxt(pctxt);
4368 if (reader->rngSchemas == NULL)
4369 return(-1);
4370 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4371 if (reader->rngValidCtxt == NULL) {
4372 xmlRelaxNGFree(reader->rngSchemas);
4373 reader->rngSchemas = NULL;
4374 return(-1);
4375 }
4376 } else {
4377 /* Use the given validation context. */
4378 reader->rngValidCtxt = ctxt;
4379 reader->rngPreserveCtxt = 1;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004380 }
Noam Postavsky15794992012-03-19 16:08:16 +08004381 /*
4382 * Redirect the validation context's error channels to use
4383 * the reader channels.
4384 * TODO: In case the user provides the validation context we
4385 * could make this redirection optional.
4386 */
Daniel Veillardf4e55762003-04-15 23:32:22 +00004387 if (reader->errorFunc != NULL) {
4388 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004389 xmlTextReaderValidityErrorRelay,
4390 xmlTextReaderValidityWarningRelay,
4391 reader);
4392 }
4393 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004394 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004395 xmlTextReaderValidityStructuredRelay,
4396 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004397 }
4398 reader->rngValidErrors = 0;
4399 reader->rngFullNode = NULL;
4400 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4401 return(0);
4402}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004403
4404/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004405 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004406 * @reader: the xmlTextReaderPtr used
4407 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004408 * @ctxt: the XML Schema validation context or NULL
4409 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004410 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004411 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004412 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004413 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004414 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004415 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004416 * -1 in case of error.
4417 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004418static int
4419xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4420 const char *xsd,
4421 xmlSchemaValidCtxtPtr ctxt,
4422 int options ATTRIBUTE_UNUSED)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004423{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004424 if (reader == NULL)
4425 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004426
4427 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004428 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004429
4430 if (((xsd != NULL) || (ctxt != NULL)) &&
4431 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4432 (reader->ctxt == NULL)))
4433 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004434
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004435 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004436 if (reader->xsdPlug != NULL) {
4437 xmlSchemaSAXUnplug(reader->xsdPlug);
4438 reader->xsdPlug = NULL;
4439 }
4440 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004441 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004442 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004443 reader->xsdValidCtxt = NULL;
4444 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004445 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004446 if (reader->xsdSchemas != NULL) {
4447 xmlSchemaFree(reader->xsdSchemas);
4448 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004449 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004450
4451 if ((xsd == NULL) && (ctxt == NULL)) {
4452 /* We just want to deactivate the validation, so get out. */
4453 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004454 }
4455
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004456 if (xsd != NULL) {
4457 xmlSchemaParserCtxtPtr pctxt;
4458 /* Parse the schema and create validation environment. */
4459 pctxt = xmlSchemaNewParserCtxt(xsd);
4460 if (reader->errorFunc != NULL) {
4461 xmlSchemaSetParserErrors(pctxt,
4462 xmlTextReaderValidityErrorRelay,
4463 xmlTextReaderValidityWarningRelay,
4464 reader);
4465 }
4466 reader->xsdSchemas = xmlSchemaParse(pctxt);
4467 xmlSchemaFreeParserCtxt(pctxt);
4468 if (reader->xsdSchemas == NULL)
4469 return(-1);
4470 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4471 if (reader->xsdValidCtxt == NULL) {
4472 xmlSchemaFree(reader->xsdSchemas);
4473 reader->xsdSchemas = NULL;
4474 return(-1);
4475 }
4476 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4477 &(reader->ctxt->sax),
4478 &(reader->ctxt->userData));
4479 if (reader->xsdPlug == NULL) {
4480 xmlSchemaFree(reader->xsdSchemas);
4481 reader->xsdSchemas = NULL;
4482 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4483 reader->xsdValidCtxt = NULL;
4484 return(-1);
4485 }
4486 } else {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004487 /* Use the given validation context. */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004488 reader->xsdValidCtxt = ctxt;
4489 reader->xsdPreserveCtxt = 1;
4490 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4491 &(reader->ctxt->sax),
4492 &(reader->ctxt->userData));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004493 if (reader->xsdPlug == NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004494 reader->xsdValidCtxt = NULL;
4495 reader->xsdPreserveCtxt = 0;
4496 return(-1);
4497 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004498 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004499 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4500 xmlTextReaderLocator,
4501 (void *) reader);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004502 /*
4503 * Redirect the validation context's error channels to use
4504 * the reader channels.
4505 * TODO: In case the user provides the validation context we
4506 * could make this redirection optional.
4507 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004508 if (reader->errorFunc != NULL) {
4509 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004510 xmlTextReaderValidityErrorRelay,
4511 xmlTextReaderValidityWarningRelay,
4512 reader);
4513 }
4514 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004515 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004516 xmlTextReaderValidityStructuredRelay,
4517 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004518 }
4519 reader->xsdValidErrors = 0;
4520 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4521 return(0);
4522}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004523
4524/**
4525 * xmlTextReaderSchemaValidateCtxt:
4526 * @reader: the xmlTextReaderPtr used
4527 * @ctxt: the XML Schema validation context or NULL
4528 * @options: options (not used yet)
4529 *
4530 * Use W3C XSD schema context to validate the document as it is processed.
4531 * Activation is only possible before the first Read().
4532 * If @ctxt is NULL, then XML Schema validation is deactivated.
4533 *
4534 * Returns 0 in case the schemas validation could be (de)activated and
4535 * -1 in case of error.
4536 */
4537int
4538xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4539 xmlSchemaValidCtxtPtr ctxt,
4540 int options)
4541{
4542 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4543}
4544
4545/**
4546 * xmlTextReaderSchemaValidate:
4547 * @reader: the xmlTextReaderPtr used
4548 * @xsd: the path to a W3C XSD schema or NULL
4549 *
4550 * Use W3C XSD schema to validate the document as it is processed.
4551 * Activation is only possible before the first Read().
4552 * If @xsd is NULL, then XML Schema validation is deactivated.
4553 *
4554 * Returns 0 in case the schemas validation could be (de)activated and
4555 * -1 in case of error.
4556 */
4557int
4558xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4559{
4560 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4561}
Noam Postavsky15794992012-03-19 16:08:16 +08004562
4563/**
4564 * xmlTextReaderRelaxNGValidateCtxt:
4565 * @reader: the xmlTextReaderPtr used
4566 * @ctxt: the RelaxNG schema validation context or NULL
4567 * @options: options (not used yet)
4568 *
4569 * Use RelaxNG schema context to validate the document as it is processed.
4570 * Activation is only possible before the first Read().
4571 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4572 *
4573 * Returns 0 in case the schemas validation could be (de)activated and
4574 * -1 in case of error.
4575 */
4576int
4577xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4578 xmlRelaxNGValidCtxtPtr ctxt,
4579 int options)
4580{
4581 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4582}
4583
4584/**
4585 * xmlTextReaderRelaxNGValidate:
4586 * @reader: the xmlTextReaderPtr used
4587 * @rng: the path to a RelaxNG schema or NULL
4588 *
4589 * Use RelaxNG schema to validate the document as it is processed.
4590 * Activation is only possible before the first Read().
4591 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4592 *
4593 * Returns 0 in case the schemas validation could be (de)activated and
4594 * -1 in case of error.
4595 */
4596int
4597xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4598{
4599 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4600}
4601
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004602#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004603
Daniel Veillarde2811272004-10-19 09:04:23 +00004604/**
4605 * xmlTextReaderIsNamespaceDecl:
4606 * @reader: the xmlTextReaderPtr used
4607 *
4608 * Determine whether the current node is a namespace declaration
4609 * rather than a regular attribute.
4610 *
4611 * Returns 1 if the current node is a namespace declaration, 0 if it
4612 * is a regular attribute or other type of node, or -1 in case of
4613 * error.
4614 */
4615int
4616xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4617 xmlNodePtr node;
4618 if (reader == NULL)
4619 return(-1);
4620 if (reader->node == NULL)
4621 return(-1);
4622 if (reader->curnode != NULL)
4623 node = reader->curnode;
4624 else
4625 node = reader->node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004626
Daniel Veillarde2811272004-10-19 09:04:23 +00004627 if (XML_NAMESPACE_DECL == node->type)
4628 return(1);
4629 else
4630 return(0);
4631}
4632
4633/**
4634 * xmlTextReaderConstXmlVersion:
4635 * @reader: the xmlTextReaderPtr used
4636 *
4637 * Determine the XML version of the document being read.
4638 *
4639 * Returns a string containing the XML version of the document or NULL
4640 * in case of error. The string is deallocated with the reader.
4641 */
4642const xmlChar *
4643xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4644 xmlDocPtr doc = NULL;
4645 if (reader == NULL)
4646 return(NULL);
4647 if (reader->doc != NULL)
4648 doc = reader->doc;
4649 else if (reader->ctxt != NULL)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004650 doc = reader->ctxt->myDoc;
Daniel Veillarde2811272004-10-19 09:04:23 +00004651 if (doc == NULL)
4652 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004653
Daniel Veillarde2811272004-10-19 09:04:23 +00004654 if (doc->version == NULL)
4655 return(NULL);
4656 else
4657 return(CONSTSTR(doc->version));
4658}
4659
4660/**
4661 * xmlTextReaderStandalone:
4662 * @reader: the xmlTextReaderPtr used
4663 *
4664 * Determine the standalone status of the document being read.
4665 *
4666 * Returns 1 if the document was declared to be standalone, 0 if it
4667 * was declared to be not standalone, or -1 if the document did not
4668 * specify its standalone status or in case of error.
4669 */
4670int
4671xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4672 xmlDocPtr doc = NULL;
4673 if (reader == NULL)
4674 return(-1);
4675 if (reader->doc != NULL)
4676 doc = reader->doc;
4677 else if (reader->ctxt != NULL)
4678 doc = reader->ctxt->myDoc;
4679 if (doc == NULL)
4680 return(-1);
4681
4682 return(doc->standalone);
4683}
4684
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004685/************************************************************************
4686 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004687 * Error Handling Extensions *
4688 * *
4689 ************************************************************************/
4690
4691/* helper to build a xmlMalloc'ed string from a format and va_list */
4692static char *
4693xmlTextReaderBuildMessage(const char *msg, va_list ap) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004694 int size = 0;
Daniel Veillard26f70262003-01-16 22:45:08 +00004695 int chars;
4696 char *larger;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004697 char *str = NULL;
4698 va_list aq;
Daniel Veillard26f70262003-01-16 22:45:08 +00004699
4700 while (1) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004701 VA_COPY(aq, ap);
4702 chars = vsnprintf(str, size, msg, aq);
4703 va_end(aq);
4704 if (chars < 0) {
4705 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004706 if (str)
4707 xmlFree(str);
4708 return NULL;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004709 }
4710 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
Daniel Veillard26f70262003-01-16 22:45:08 +00004711 break;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004712 if (chars < MAX_ERR_MSG_SIZE)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004713 size = chars + 1;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004714 else
4715 size = MAX_ERR_MSG_SIZE;
Daniel Veillard26f70262003-01-16 22:45:08 +00004716 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4717 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004718 if (str)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004719 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004720 return NULL;
4721 }
4722 str = larger;
4723 }
4724
4725 return str;
4726}
4727
Daniel Veillard417be3a2003-01-20 21:26:34 +00004728/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004729 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004730 * @locator: the xmlTextReaderLocatorPtr used
4731 *
4732 * Obtain the line number for the given locator.
4733 *
4734 * Returns the line number or -1 in case of error.
4735 */
4736int
4737xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4738 /* we know that locator is a xmlParserCtxtPtr */
4739 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4740 int ret = -1;
4741
Daniel Veillardce682bc2004-11-05 17:22:25 +00004742 if (locator == NULL)
4743 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004744 if (ctx->node != NULL) {
4745 ret = xmlGetLineNo(ctx->node);
4746 }
4747 else {
4748 /* inspired from error.c */
4749 xmlParserInputPtr input;
4750 input = ctx->input;
4751 if ((input->filename == NULL) && (ctx->inputNr > 1))
4752 input = ctx->inputTab[ctx->inputNr - 2];
4753 if (input != NULL) {
4754 ret = input->line;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004755 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004756 else {
4757 ret = -1;
4758 }
4759 }
4760
4761 return ret;
4762}
4763
4764/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004765 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004766 * @locator: the xmlTextReaderLocatorPtr used
4767 *
4768 * Obtain the base URI for the given locator.
4769 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004770 * Returns the base URI or NULL in case of error,
4771 * if non NULL it need to be freed by the caller.
Daniel Veillard417be3a2003-01-20 21:26:34 +00004772 */
4773xmlChar *
4774xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4775 /* we know that locator is a xmlParserCtxtPtr */
4776 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4777 xmlChar *ret = NULL;
4778
Daniel Veillardce682bc2004-11-05 17:22:25 +00004779 if (locator == NULL)
4780 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004781 if (ctx->node != NULL) {
4782 ret = xmlNodeGetBase(NULL,ctx->node);
4783 }
4784 else {
4785 /* inspired from error.c */
4786 xmlParserInputPtr input;
4787 input = ctx->input;
4788 if ((input->filename == NULL) && (ctx->inputNr > 1))
4789 input = ctx->inputTab[ctx->inputNr - 2];
4790 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004791 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004792 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004793 else {
4794 ret = NULL;
4795 }
4796 }
4797
4798 return ret;
4799}
4800
Daniel Veillard26f70262003-01-16 22:45:08 +00004801static void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004802xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4803 char *str)
4804{
4805 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4806
4807 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
Daniel Veillard26f70262003-01-16 22:45:08 +00004808
William M. Bracka3215c72004-07-31 16:24:01 +00004809 if (str != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004810 if (reader->errorFunc)
4811 reader->errorFunc(reader->errorFuncArg, str, severity,
4812 (xmlTextReaderLocatorPtr) ctx);
4813 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004814 }
4815}
4816
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004817static void
4818xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4819{
4820 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
William M. Brack93d004f2004-02-03 00:14:10 +00004821
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004822 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4823
4824 if (error && reader->sErrorFunc) {
4825 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4826 }
William M. Brack93d004f2004-02-03 00:14:10 +00004827}
4828
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004829static void XMLCDECL
4830xmlTextReaderError(void *ctxt, const char *msg, ...)
4831{
Daniel Veillard26f70262003-01-16 22:45:08 +00004832 va_list ap;
4833
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004834 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004835 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004836 XML_PARSER_SEVERITY_ERROR,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004837 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004838 va_end(ap);
4839
4840}
4841
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004842static void XMLCDECL
4843xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4844{
Daniel Veillard26f70262003-01-16 22:45:08 +00004845 va_list ap;
4846
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004847 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004848 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004849 XML_PARSER_SEVERITY_WARNING,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004850 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004851 va_end(ap);
4852}
4853
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004854static void XMLCDECL
4855xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4856{
Daniel Veillard26f70262003-01-16 22:45:08 +00004857 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004858
Daniel Veillard417be3a2003-01-20 21:26:34 +00004859 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004860
Daniel Veillard417be3a2003-01-20 21:26:34 +00004861 if ((len > 1) && (msg[len - 2] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004862 /*
4863 * some callbacks only report locator information:
4864 * skip them (mimicking behaviour in error.c)
4865 */
4866 va_start(ap, msg);
4867 xmlTextReaderGenericError(ctxt,
4868 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4869 xmlTextReaderBuildMessage(msg, ap));
4870 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004871 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004872}
4873
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004874static void XMLCDECL
4875xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4876{
Daniel Veillard26f70262003-01-16 22:45:08 +00004877 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004878
Daniel Veillard417be3a2003-01-20 21:26:34 +00004879 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004880
Daniel Veillard417be3a2003-01-20 21:26:34 +00004881 if ((len != 0) && (msg[len - 1] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004882 /*
4883 * some callbacks only report locator information:
4884 * skip them (mimicking behaviour in error.c)
4885 */
4886 va_start(ap, msg);
4887 xmlTextReaderGenericError(ctxt,
4888 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4889 xmlTextReaderBuildMessage(msg, ap));
4890 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004891 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004892}
4893
4894/**
4895 * xmlTextReaderSetErrorHandler:
4896 * @reader: the xmlTextReaderPtr used
4897 * @f: the callback function to call on error and warnings
4898 * @arg: a user argument to pass to the callback function
4899 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004900 * Register a callback function that will be called on error and warnings.
4901 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004902 * If @f is NULL, the default error and warning handlers are restored.
4903 */
4904void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004905xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4906 xmlTextReaderErrorFunc f, void *arg)
4907{
Daniel Veillard26f70262003-01-16 22:45:08 +00004908 if (f != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004909 reader->ctxt->sax->error = xmlTextReaderError;
4910 reader->ctxt->sax->serror = NULL;
4911 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4912 reader->ctxt->sax->warning = xmlTextReaderWarning;
4913 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4914 reader->errorFunc = f;
4915 reader->sErrorFunc = NULL;
4916 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004917#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004918 if (reader->rngValidCtxt) {
4919 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4920 xmlTextReaderValidityErrorRelay,
4921 xmlTextReaderValidityWarningRelay,
4922 reader);
4923 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4924 reader);
4925 }
4926 if (reader->xsdValidCtxt) {
4927 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4928 xmlTextReaderValidityErrorRelay,
4929 xmlTextReaderValidityWarningRelay,
4930 reader);
4931 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4932 reader);
4933 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004934#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004935 } else {
4936 /* restore defaults */
4937 reader->ctxt->sax->error = xmlParserError;
4938 reader->ctxt->vctxt.error = xmlParserValidityError;
4939 reader->ctxt->sax->warning = xmlParserWarning;
4940 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4941 reader->errorFunc = NULL;
4942 reader->sErrorFunc = NULL;
4943 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004944#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004945 if (reader->rngValidCtxt) {
4946 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4947 reader);
4948 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4949 reader);
4950 }
4951 if (reader->xsdValidCtxt) {
4952 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4953 reader);
4954 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4955 reader);
4956 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004957#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004958 }
4959}
4960
Daniel Veillard417be3a2003-01-20 21:26:34 +00004961/**
William M. Brack93d004f2004-02-03 00:14:10 +00004962* xmlTextReaderSetStructuredErrorHandler:
4963 * @reader: the xmlTextReaderPtr used
4964 * @f: the callback function to call on error and warnings
4965 * @arg: a user argument to pass to the callback function
4966 *
4967 * Register a callback function that will be called on error and warnings.
4968 *
4969 * If @f is NULL, the default error and warning handlers are restored.
4970 */
4971void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004972xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4973 xmlStructuredErrorFunc f, void *arg)
4974{
4975 if (f != NULL) {
4976 reader->ctxt->sax->error = NULL;
4977 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4978 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4979 reader->ctxt->sax->warning = xmlTextReaderWarning;
4980 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4981 reader->sErrorFunc = f;
4982 reader->errorFunc = NULL;
4983 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004984#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004985 if (reader->rngValidCtxt) {
4986 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4987 reader);
4988 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4989 xmlTextReaderValidityStructuredRelay,
4990 reader);
4991 }
4992 if (reader->xsdValidCtxt) {
4993 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4994 reader);
4995 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4996 xmlTextReaderValidityStructuredRelay,
4997 reader);
4998 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004999#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005000 } else {
5001 /* restore defaults */
5002 reader->ctxt->sax->error = xmlParserError;
5003 reader->ctxt->sax->serror = NULL;
5004 reader->ctxt->vctxt.error = xmlParserValidityError;
5005 reader->ctxt->sax->warning = xmlParserWarning;
5006 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5007 reader->errorFunc = NULL;
5008 reader->sErrorFunc = NULL;
5009 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005010#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005011 if (reader->rngValidCtxt) {
5012 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5013 reader);
5014 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5015 reader);
5016 }
5017 if (reader->xsdValidCtxt) {
5018 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5019 reader);
5020 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5021 reader);
5022 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005023#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005024 }
William M. Brack93d004f2004-02-03 00:14:10 +00005025}
5026
5027/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00005028 * xmlTextReaderIsValid:
5029 * @reader: the xmlTextReaderPtr used
5030 *
5031 * Retrieve the validity status from the parser context
5032 *
5033 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5034 */
5035int
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005036xmlTextReaderIsValid(xmlTextReaderPtr reader)
5037{
5038 if (reader == NULL)
5039 return (-1);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005040#ifdef LIBXML_SCHEMAS_ENABLED
5041 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005042 return (reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00005043 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005044 return (reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005045#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00005046 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005047 return (reader->ctxt->valid);
5048 return (0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00005049}
5050
5051/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00005052 * xmlTextReaderGetErrorHandler:
5053 * @reader: the xmlTextReaderPtr used
5054 * @f: the callback function or NULL is no callback has been registered
5055 * @arg: a user argument
5056 *
5057 * Retrieve the error callback function and user argument.
5058 */
Daniel Veillard26f70262003-01-16 22:45:08 +00005059void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005060xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5061 xmlTextReaderErrorFunc * f, void **arg)
5062{
5063 if (f != NULL)
5064 *f = reader->errorFunc;
5065 if (arg != NULL)
5066 *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00005067}
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005068/************************************************************************
5069 * *
5070 * New set (2.6.0) of simpler and more flexible APIs *
5071 * *
5072 ************************************************************************/
5073
5074/**
5075 * xmlTextReaderSetup:
5076 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00005077 * @input: xmlParserInputBufferPtr used to feed the reader, will
5078 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005079 * @URL: the base URL to use for the document
5080 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005081 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005082 *
5083 * Setup an XML reader with new options
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005084 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005085 * Returns 0 in case of success and -1 in case of error.
5086 */
Aleksey Sanind8377642007-01-03 23:13:12 +00005087int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005088xmlTextReaderSetup(xmlTextReaderPtr reader,
5089 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005090 const char *encoding, int options)
5091{
William M. Brackd46c1ca2007-02-08 23:34:34 +00005092 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00005093 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00005094 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00005095 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00005096 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005097
Daniel Veillard8874b942005-08-25 13:19:21 +00005098 /*
5099 * we force the generation of compact text nodes on the reader
5100 * since usr applications should never modify the tree
5101 */
5102 options |= XML_PARSE_COMPACT;
5103
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005104 reader->doc = NULL;
5105 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00005106 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00005107 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005108 if ((input != NULL) && (reader->input != NULL) &&
5109 (reader->allocs & XML_TEXTREADER_INPUT)) {
5110 xmlFreeParserInputBuffer(reader->input);
5111 reader->input = NULL;
5112 reader->allocs -= XML_TEXTREADER_INPUT;
5113 }
5114 if (input != NULL) {
5115 reader->input = input;
5116 reader->allocs |= XML_TEXTREADER_INPUT;
5117 }
5118 if (reader->buffer == NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08005119 reader->buffer = xmlBufCreateSize(100);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005120 if (reader->buffer == NULL) {
5121 xmlGenericError(xmlGenericErrorContext,
5122 "xmlTextReaderSetup : malloc failed\n");
5123 return (-1);
5124 }
5125 if (reader->sax == NULL)
5126 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5127 if (reader->sax == NULL) {
5128 xmlGenericError(xmlGenericErrorContext,
5129 "xmlTextReaderSetup : malloc failed\n");
5130 return (-1);
5131 }
5132 xmlSAXVersion(reader->sax, 2);
5133 reader->startElement = reader->sax->startElement;
5134 reader->sax->startElement = xmlTextReaderStartElement;
5135 reader->endElement = reader->sax->endElement;
5136 reader->sax->endElement = xmlTextReaderEndElement;
5137#ifdef LIBXML_SAX1_ENABLED
5138 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5139#endif /* LIBXML_SAX1_ENABLED */
5140 reader->startElementNs = reader->sax->startElementNs;
5141 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5142 reader->endElementNs = reader->sax->endElementNs;
5143 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5144#ifdef LIBXML_SAX1_ENABLED
5145 } else {
5146 reader->startElementNs = NULL;
5147 reader->endElementNs = NULL;
5148 }
5149#endif /* LIBXML_SAX1_ENABLED */
5150 reader->characters = reader->sax->characters;
5151 reader->sax->characters = xmlTextReaderCharacters;
5152 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5153 reader->cdataBlock = reader->sax->cdataBlock;
5154 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5155
5156 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5157 reader->node = NULL;
5158 reader->curnode = NULL;
5159 if (input != NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005160 if (xmlBufUse(reader->input->buffer) < 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005161 xmlParserInputBufferRead(input, 4);
5162 }
5163 if (reader->ctxt == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005164 if (xmlBufUse(reader->input->buffer) >= 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005165 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08005166 (const char *) xmlBufContent(reader->input->buffer),
5167 4, URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005168 reader->base = 0;
5169 reader->cur = 4;
5170 } else {
5171 reader->ctxt =
5172 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5173 reader->base = 0;
5174 reader->cur = 0;
5175 }
5176 } else {
5177 xmlParserInputPtr inputStream;
5178 xmlParserInputBufferPtr buf;
5179 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5180
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005181 xmlCtxtReset(reader->ctxt);
5182 buf = xmlAllocParserInputBuffer(enc);
5183 if (buf == NULL) return(-1);
5184 inputStream = xmlNewInputStream(reader->ctxt);
5185 if (inputStream == NULL) {
5186 xmlFreeParserInputBuffer(buf);
5187 return(-1);
5188 }
5189
5190 if (URL == NULL)
5191 inputStream->filename = NULL;
5192 else
5193 inputStream->filename = (char *)
5194 xmlCanonicPath((const xmlChar *) URL);
5195 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +08005196 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005197
5198 inputPush(reader->ctxt, inputStream);
5199 reader->cur = 0;
5200 }
5201 if (reader->ctxt == NULL) {
5202 xmlGenericError(xmlGenericErrorContext,
5203 "xmlTextReaderSetup : malloc failed\n");
5204 return (-1);
5205 }
5206 }
5207 if (reader->dict != NULL) {
5208 if (reader->ctxt->dict != NULL) {
5209 if (reader->dict != reader->ctxt->dict) {
5210 xmlDictFree(reader->dict);
5211 reader->dict = reader->ctxt->dict;
5212 }
5213 } else {
5214 reader->ctxt->dict = reader->dict;
5215 }
5216 } else {
5217 if (reader->ctxt->dict == NULL)
5218 reader->ctxt->dict = xmlDictCreate();
5219 reader->dict = reader->ctxt->dict;
5220 }
5221 reader->ctxt->_private = reader;
5222 reader->ctxt->linenumbers = 1;
5223 reader->ctxt->dictNames = 1;
5224 /*
5225 * use the parser dictionnary to allocate all elements and attributes names
5226 */
5227 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005228 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005229
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005230#ifdef LIBXML_XINCLUDE_ENABLED
5231 if (reader->xincctxt != NULL) {
5232 xmlXIncludeFreeContext(reader->xincctxt);
5233 reader->xincctxt = NULL;
5234 }
5235 if (options & XML_PARSE_XINCLUDE) {
5236 reader->xinclude = 1;
5237 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5238 options -= XML_PARSE_XINCLUDE;
5239 } else
5240 reader->xinclude = 0;
5241 reader->in_xinclude = 0;
5242#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005243#ifdef LIBXML_PATTERN_ENABLED
5244 if (reader->patternTab == NULL) {
5245 reader->patternNr = 0;
5246 reader->patternMax = 0;
5247 }
5248 while (reader->patternNr > 0) {
5249 reader->patternNr--;
5250 if (reader->patternTab[reader->patternNr] != NULL) {
5251 xmlFreePattern(reader->patternTab[reader->patternNr]);
5252 reader->patternTab[reader->patternNr] = NULL;
5253 }
5254 }
5255#endif
5256
Daniel Veillardc36965d2003-12-02 10:28:48 +00005257 if (options & XML_PARSE_DTDVALID)
5258 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5259
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005260 xmlCtxtUseOptions(reader->ctxt, options);
5261 if (encoding != NULL) {
5262 xmlCharEncodingHandlerPtr hdlr;
5263
5264 hdlr = xmlFindCharEncodingHandler(encoding);
5265 if (hdlr != NULL)
5266 xmlSwitchToEncoding(reader->ctxt, hdlr);
5267 }
5268 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5269 (reader->ctxt->input->filename == NULL))
5270 reader->ctxt->input->filename = (char *)
5271 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005272
5273 reader->doc = NULL;
5274
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005275 return (0);
5276}
5277
5278/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005279 * xmlTextReaderByteConsumed:
5280 * @reader: an XML reader
5281 *
5282 * This function provides the current index of the parser used
5283 * by the reader, relative to the start of the current entity.
5284 * This function actually just wraps a call to xmlBytesConsumed()
5285 * for the parser context associated with the reader.
5286 * See xmlBytesConsumed() for more information.
5287 *
5288 * Returns the index in bytes from the beginning of the entity or -1
5289 * in case the index could not be computed.
5290 */
5291long
5292xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5293 if ((reader == NULL) || (reader->ctxt == NULL))
5294 return(-1);
5295 return(xmlByteConsumed(reader->ctxt));
5296}
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005297
Daniel Veillard5e094142005-02-18 19:36:12 +00005298
5299/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005300 * xmlReaderWalker:
5301 * @doc: a preparsed document
5302 *
5303 * Create an xmltextReader for a preparsed document.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005304 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005305 * Returns the new reader or NULL in case of error.
5306 */
5307xmlTextReaderPtr
5308xmlReaderWalker(xmlDocPtr doc)
5309{
5310 xmlTextReaderPtr ret;
5311
5312 if (doc == NULL)
5313 return(NULL);
5314
5315 ret = xmlMalloc(sizeof(xmlTextReader));
5316 if (ret == NULL) {
5317 xmlGenericError(xmlGenericErrorContext,
5318 "xmlNewTextReader : malloc failed\n");
5319 return(NULL);
5320 }
5321 memset(ret, 0, sizeof(xmlTextReader));
5322 ret->entNr = 0;
5323 ret->input = NULL;
5324 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5325 ret->node = NULL;
5326 ret->curnode = NULL;
5327 ret->base = 0;
5328 ret->cur = 0;
5329 ret->allocs = XML_TEXTREADER_CTXT;
5330 ret->doc = doc;
5331 ret->state = XML_TEXTREADER_START;
5332 ret->dict = xmlDictCreate();
5333 return(ret);
5334}
5335
5336/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005337 * xmlReaderForDoc:
5338 * @cur: a pointer to a zero terminated string
5339 * @URL: the base URL to use for the document
5340 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005341 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005342 *
5343 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005344 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005345 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005346 * Returns the new reader or NULL in case of error.
5347 */
5348xmlTextReaderPtr
5349xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5350 int options)
5351{
5352 int len;
5353
5354 if (cur == NULL)
5355 return (NULL);
5356 len = xmlStrlen(cur);
5357
5358 return (xmlReaderForMemory
5359 ((const char *) cur, len, URL, encoding, options));
5360}
5361
5362/**
5363 * xmlReaderForFile:
5364 * @filename: a file or URL
5365 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005366 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005367 *
5368 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005369 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005370 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005371 * Returns the new reader or NULL in case of error.
5372 */
5373xmlTextReaderPtr
5374xmlReaderForFile(const char *filename, const char *encoding, int options)
5375{
5376 xmlTextReaderPtr reader;
5377
5378 reader = xmlNewTextReaderFilename(filename);
5379 if (reader == NULL)
5380 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005381 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005382 return (reader);
5383}
5384
5385/**
5386 * xmlReaderForMemory:
5387 * @buffer: a pointer to a char array
5388 * @size: the size of the array
5389 * @URL: the base URL to use for the document
5390 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005391 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005392 *
5393 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005394 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005395 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005396 * Returns the new reader or NULL in case of error.
5397 */
5398xmlTextReaderPtr
5399xmlReaderForMemory(const char *buffer, int size, const char *URL,
5400 const char *encoding, int options)
5401{
5402 xmlTextReaderPtr reader;
5403 xmlParserInputBufferPtr buf;
5404
Daniel Veillard21924522004-02-19 16:37:07 +00005405 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005406 XML_CHAR_ENCODING_NONE);
5407 if (buf == NULL) {
5408 return (NULL);
5409 }
5410 reader = xmlNewTextReader(buf, URL);
5411 if (reader == NULL) {
5412 xmlFreeParserInputBuffer(buf);
5413 return (NULL);
5414 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005415 reader->allocs |= XML_TEXTREADER_INPUT;
5416 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005417 return (reader);
5418}
5419
5420/**
5421 * xmlReaderForFd:
5422 * @fd: an open file descriptor
5423 * @URL: the base URL to use for the document
5424 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005425 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005426 *
5427 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005428 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005429 * NOTE that the file descriptor will not be closed when the
5430 * reader is closed or reset.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005431 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005432 * Returns the new reader or NULL in case of error.
5433 */
5434xmlTextReaderPtr
5435xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5436{
5437 xmlTextReaderPtr reader;
5438 xmlParserInputBufferPtr input;
5439
5440 if (fd < 0)
5441 return (NULL);
5442
5443 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5444 if (input == NULL)
5445 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005446 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005447 reader = xmlNewTextReader(input, URL);
5448 if (reader == NULL) {
5449 xmlFreeParserInputBuffer(input);
5450 return (NULL);
5451 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005452 reader->allocs |= XML_TEXTREADER_INPUT;
5453 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005454 return (reader);
5455}
5456
5457/**
5458 * xmlReaderForIO:
5459 * @ioread: an I/O read function
5460 * @ioclose: an I/O close function
5461 * @ioctx: an I/O handler
5462 * @URL: the base URL to use for the document
5463 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005464 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005465 *
5466 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005467 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005468 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005469 * Returns the new reader or NULL in case of error.
5470 */
5471xmlTextReaderPtr
5472xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5473 void *ioctx, const char *URL, const char *encoding,
5474 int options)
5475{
5476 xmlTextReaderPtr reader;
5477 xmlParserInputBufferPtr input;
5478
5479 if (ioread == NULL)
5480 return (NULL);
5481
5482 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5483 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005484 if (input == NULL) {
5485 if (ioclose != NULL)
5486 ioclose(ioctx);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005487 return (NULL);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005488 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005489 reader = xmlNewTextReader(input, URL);
5490 if (reader == NULL) {
5491 xmlFreeParserInputBuffer(input);
5492 return (NULL);
5493 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005494 reader->allocs |= XML_TEXTREADER_INPUT;
5495 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005496 return (reader);
5497}
5498
5499/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005500 * xmlReaderNewWalker:
5501 * @reader: an XML reader
5502 * @doc: a preparsed document
5503 *
5504 * Setup an xmltextReader to parse a preparsed XML document.
5505 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005506 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005507 * Returns 0 in case of success and -1 in case of error
5508 */
5509int
5510xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5511{
5512 if (doc == NULL)
5513 return (-1);
5514 if (reader == NULL)
5515 return (-1);
5516
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005517 if (reader->input != NULL) {
5518 xmlFreeParserInputBuffer(reader->input);
5519 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005520 if (reader->ctxt != NULL) {
5521 xmlCtxtReset(reader->ctxt);
5522 }
5523
5524 reader->entNr = 0;
5525 reader->input = NULL;
5526 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5527 reader->node = NULL;
5528 reader->curnode = NULL;
5529 reader->base = 0;
5530 reader->cur = 0;
5531 reader->allocs = XML_TEXTREADER_CTXT;
5532 reader->doc = doc;
5533 reader->state = XML_TEXTREADER_START;
5534 if (reader->dict == NULL) {
5535 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5536 reader->dict = reader->ctxt->dict;
5537 else
5538 reader->dict = xmlDictCreate();
5539 }
5540 return(0);
5541}
5542
5543/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005544 * xmlReaderNewDoc:
5545 * @reader: an XML reader
5546 * @cur: a pointer to a zero terminated string
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
5558xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5559 const char *URL, const char *encoding, int options)
5560{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005561
5562 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005563
5564 if (cur == NULL)
5565 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005566 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005567 return (-1);
5568
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005569 len = xmlStrlen(cur);
5570 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5571 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005572}
5573
5574/**
5575 * xmlReaderNewFile:
5576 * @reader: an XML reader
5577 * @filename: a file or URL
5578 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005579 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005580 *
5581 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005582 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005583 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005584 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005585 * Returns 0 in case of success and -1 in case of error
5586 */
5587int
5588xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5589 const char *encoding, int options)
5590{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005591 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005592
5593 if (filename == NULL)
5594 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005595 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005596 return (-1);
5597
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005598 input =
5599 xmlParserInputBufferCreateFilename(filename,
5600 XML_CHAR_ENCODING_NONE);
5601 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005602 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005603 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005604}
5605
5606/**
5607 * xmlReaderNewMemory:
5608 * @reader: an XML reader
5609 * @buffer: a pointer to a char array
5610 * @size: the size of the array
5611 * @URL: the base URL to use for the document
5612 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005613 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005614 *
5615 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005616 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005617 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005618 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005619 * Returns 0 in case of success and -1 in case of error
5620 */
5621int
5622xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5623 const char *URL, const char *encoding, int options)
5624{
5625 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005626
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005627 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005628 return (-1);
5629 if (buffer == NULL)
5630 return (-1);
5631
Daniel Veillard21924522004-02-19 16:37:07 +00005632 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005633 XML_CHAR_ENCODING_NONE);
5634 if (input == NULL) {
5635 return (-1);
5636 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005637 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005638}
5639
5640/**
5641 * xmlReaderNewFd:
5642 * @reader: an XML reader
5643 * @fd: an open file descriptor
5644 * @URL: the base URL to use for the document
5645 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005646 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005647 *
5648 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005649 * NOTE that the file descriptor will not be closed when the
5650 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005651 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005652 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005653 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005654 * Returns 0 in case of success and -1 in case of error
5655 */
5656int
5657xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5658 const char *URL, const char *encoding, int options)
5659{
5660 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005661
5662 if (fd < 0)
5663 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005664 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005665 return (-1);
5666
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005667 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5668 if (input == NULL)
5669 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005670 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005671 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005672}
5673
5674/**
5675 * xmlReaderNewIO:
5676 * @reader: an XML reader
5677 * @ioread: an I/O read function
5678 * @ioclose: an I/O close function
5679 * @ioctx: an I/O handler
5680 * @URL: the base URL to use for the document
5681 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005682 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005683 *
5684 * Setup an xmltextReader to parse an XML document from I/O functions
5685 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005686 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005687 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005688 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005689 * Returns 0 in case of success and -1 in case of error
5690 */
5691int
5692xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5693 xmlInputCloseCallback ioclose, void *ioctx,
5694 const char *URL, const char *encoding, int options)
5695{
5696 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005697
5698 if (ioread == NULL)
5699 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005700 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005701 return (-1);
5702
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005703 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5704 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005705 if (input == NULL) {
5706 if (ioclose != NULL)
5707 ioclose(ioctx);
Daniel Veillard2c437da2012-05-11 12:08:15 +08005708 return (-1);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005709 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005710 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005711}
Lin Yi-Li24464be2012-05-10 16:14:55 +08005712
Daniel Veillard26f70262003-01-16 22:45:08 +00005713/************************************************************************
5714 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005715 * Utilities *
5716 * *
5717 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005718#ifdef NOT_USED_YET
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005719
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005720/**
5721 * xmlBase64Decode:
5722 * @in: the input buffer
5723 * @inlen: the size of the input (in), the size read from it (out)
5724 * @to: the output buffer
5725 * @tolen: the size of the output (in), the size written to (out)
5726 *
5727 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005728 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005729 *
5730 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5731 * 2 if there wasn't enough space on the output or -1 in case of error.
5732 */
5733static int
5734xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005735 unsigned char *to, unsigned long *tolen)
5736{
5737 unsigned long incur; /* current index in in[] */
5738
5739 unsigned long inblk; /* last block index in in[] */
5740
5741 unsigned long outcur; /* current index in out[] */
5742
5743 unsigned long inmax; /* size of in[] */
5744
5745 unsigned long outmax; /* size of out[] */
5746
5747 unsigned char cur; /* the current value read from in[] */
5748
5749 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5750
5751 int nbintmp; /* number of byte in intmp[] */
5752
5753 int is_ignore; /* cur should be ignored */
5754
5755 int is_end = 0; /* the end of the base64 was found */
5756
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005757 int retval = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005758
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005759 int i;
5760
5761 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005762 return (-1);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005763
5764 incur = 0;
5765 inblk = 0;
5766 outcur = 0;
5767 inmax = *inlen;
5768 outmax = *tolen;
5769 nbintmp = 0;
5770
5771 while (1) {
5772 if (incur >= inmax)
5773 break;
5774 cur = in[incur++];
5775 is_ignore = 0;
5776 if ((cur >= 'A') && (cur <= 'Z'))
5777 cur = cur - 'A';
5778 else if ((cur >= 'a') && (cur <= 'z'))
5779 cur = cur - 'a' + 26;
5780 else if ((cur >= '0') && (cur <= '9'))
5781 cur = cur - '0' + 52;
5782 else if (cur == '+')
5783 cur = 62;
5784 else if (cur == '/')
5785 cur = 63;
5786 else if (cur == '.')
5787 cur = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005788 else if (cur == '=') /*no op , end of the base64 stream */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005789 is_end = 1;
5790 else {
5791 is_ignore = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005792 if (nbintmp == 0)
5793 inblk = incur;
5794 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005795
5796 if (!is_ignore) {
5797 int nbouttmp = 3;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005798
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005799 int is_break = 0;
5800
5801 if (is_end) {
5802 if (nbintmp == 0)
5803 break;
5804 if ((nbintmp == 1) || (nbintmp == 2))
5805 nbouttmp = 1;
5806 else
5807 nbouttmp = 2;
5808 nbintmp = 3;
5809 is_break = 1;
5810 }
5811 intmp[nbintmp++] = cur;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005812 /*
5813 * if intmp is full, push the 4byte sequence as a 3 byte
5814 * sequence out
5815 */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005816 if (nbintmp == 4) {
5817 nbintmp = 0;
5818 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5819 outtmp[1] =
5820 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5821 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005822 if (outcur + 3 >= outmax) {
5823 retval = 2;
5824 break;
5825 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005826
5827 for (i = 0; i < nbouttmp; i++)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005828 to[outcur++] = outtmp[i];
5829 inblk = incur;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005830 }
5831
5832 if (is_break) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005833 retval = 0;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005834 break;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005835 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005836 }
5837 }
5838
5839 *tolen = outcur;
5840 *inlen = inblk;
5841 return (retval);
5842}
5843
5844/*
5845 * Test routine for the xmlBase64Decode function
5846 */
5847#if 0
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005848int
5849main(int argc, char **argv)
5850{
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005851 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005852
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005853 char output[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005854
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005855 char output2[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005856
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005857 char output3[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005858
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005859 unsigned long inlen = strlen(input);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005860
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005861 unsigned long outlen = 100;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005862
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005863 int ret;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005864
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005865 unsigned long cons, tmp, tmp2, prod;
5866
5867 /*
5868 * Direct
5869 */
5870 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5871
5872 output[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005873 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5874 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5875;
5876
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005877 /*
5878 * output chunking
5879 */
5880 cons = 0;
5881 prod = 0;
5882 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005883 tmp = 5;
5884 tmp2 = inlen - cons;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005885
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005886 printf("%ld %ld\n", cons, prod);
5887 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5888 cons += tmp2;
5889 prod += tmp;
5890 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005891 }
5892 output2[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005893 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5894 prod, output2);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005895
5896 /*
5897 * input chunking
5898 */
5899 cons = 0;
5900 prod = 0;
5901 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005902 tmp = 100 - prod;
5903 tmp2 = inlen - cons;
5904 if (tmp2 > 5)
5905 tmp2 = 5;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005906
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005907 printf("%ld %ld\n", cons, prod);
5908 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5909 cons += tmp2;
5910 prod += tmp;
5911 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005912 }
5913 output3[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005914 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5915 prod, output3);
5916 return (0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005917
5918}
5919#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005920#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005921#define bottom_xmlreader
5922#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005923#endif /* LIBXML_READER_ENABLED */