blob: c5b683dc33a55fd97856854ccf10f03a97988d8e [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
Daniel Veillardf4e55762003-04-15 23:32:22 +00001434 if ((reader->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
Daniel Veillardf4e55762003-04-15 23:32:22 +00001567 if ((reader->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 }
1797 case XML_ATTRIBUTE_NODE:
1798 TODO
1799 break;
1800 default:
1801 break;
1802 }
Daniel Veillard67df8092002-12-16 22:04:11 +00001803 return(NULL);
1804}
1805
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001806#if 0
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001807/**
1808 * xmlTextReaderReadBase64:
1809 * @reader: the xmlTextReaderPtr used
1810 * @array: a byte array to store the content.
1811 * @offset: the zero-based index into array where the method should
1812 * begin to write.
1813 * @len: the number of bytes to write.
1814 *
1815 * Reads and decodes the Base64 encoded contents of an element and
1816 * stores the result in a byte buffer.
1817 *
1818 * Returns the number of bytes written to array, or zero if the current
1819 * instance is not positioned on an element or -1 in case of error.
1820 */
1821int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001822xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1823 unsigned char *array ATTRIBUTE_UNUSED,
1824 int offset ATTRIBUTE_UNUSED,
1825 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001826 if ((reader == NULL) || (reader->ctxt == NULL))
1827 return(-1);
1828 if (reader->ctxt->wellFormed != 1)
1829 return(-1);
1830
1831 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1832 return(0);
1833 TODO
1834 return(0);
1835}
1836
1837/**
1838 * xmlTextReaderReadBinHex:
1839 * @reader: the xmlTextReaderPtr used
1840 * @array: a byte array to store the content.
1841 * @offset: the zero-based index into array where the method should
1842 * begin to write.
1843 * @len: the number of bytes to write.
1844 *
1845 * Reads and decodes the BinHex encoded contents of an element and
1846 * stores the result in a byte buffer.
1847 *
1848 * Returns the number of bytes written to array, or zero if the current
1849 * instance is not positioned on an element or -1 in case of error.
1850 */
1851int
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001852xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1853 unsigned char *array ATTRIBUTE_UNUSED,
1854 int offset ATTRIBUTE_UNUSED,
1855 int len ATTRIBUTE_UNUSED) {
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001856 if ((reader == NULL) || (reader->ctxt == NULL))
1857 return(-1);
1858 if (reader->ctxt->wellFormed != 1)
1859 return(-1);
1860
1861 if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1862 return(0);
1863 TODO
1864 return(0);
1865}
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00001866#endif
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00001867
Daniel Veillarde1ca5032002-12-09 14:13:43 +00001868/************************************************************************
1869 * *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001870 * Operating on a preparsed tree *
1871 * *
1872 ************************************************************************/
1873static int
1874xmlTextReaderNextTree(xmlTextReaderPtr reader)
1875{
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001876 if (reader == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001877 return(-1);
1878
1879 if (reader->state == XML_TEXTREADER_END)
1880 return(0);
1881
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001882 if (reader->node == NULL) {
1883 if (reader->doc->children == NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001884 reader->state = XML_TEXTREADER_END;
1885 return(0);
1886 }
1887
1888 reader->node = reader->doc->children;
1889 reader->state = XML_TEXTREADER_START;
1890 return(1);
1891 }
1892
1893 if (reader->state != XML_TEXTREADER_BACKTRACK) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001894 /* Here removed traversal to child, because we want to skip the subtree,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001895 replace with traversal to sibling to skip subtree */
1896 if (reader->node->next != 0) {
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001897 /* Move to sibling if present,skipping sub-tree */
1898 reader->node = reader->node->next;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001899 reader->state = XML_TEXTREADER_START;
1900 return(1);
1901 }
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001902
1903 /* if reader->node->next is NULL mean no subtree for current node,
Daniel Veillardaa6de472008-08-25 14:53:31 +00001904 so need to move to sibling of parent node if present */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001905 if ((reader->node->type == XML_ELEMENT_NODE) ||
1906 (reader->node->type == XML_ATTRIBUTE_NODE)) {
1907 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001908 /* This will move to parent if present */
1909 xmlTextReaderRead(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001910 }
1911 }
1912
1913 if (reader->node->next != 0) {
1914 reader->node = reader->node->next;
1915 reader->state = XML_TEXTREADER_START;
1916 return(1);
1917 }
1918
1919 if (reader->node->parent != 0) {
1920 if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1921 reader->state = XML_TEXTREADER_END;
1922 return(0);
1923 }
1924
1925 reader->node = reader->node->parent;
1926 reader->depth--;
1927 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillardbfa5cf12008-08-27 15:33:28 +00001928 /* Repeat process to move to sibling of parent node if present */
1929 xmlTextReaderNextTree(reader);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001930 }
1931
1932 reader->state = XML_TEXTREADER_END;
1933
1934 return(1);
1935}
1936
1937/**
1938 * xmlTextReaderReadTree:
1939 * @reader: the xmlTextReaderPtr used
1940 *
1941 * Moves the position of the current instance to the next node in
1942 * the stream, exposing its properties.
1943 *
1944 * Returns 1 if the node was read successfully, 0 if there is no more
1945 * nodes to read, or -1 in case of error
1946 */
1947static int
1948xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1949 if (reader->state == XML_TEXTREADER_END)
1950 return(0);
1951
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001952next_node:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001953 if (reader->node == NULL) {
1954 if (reader->doc->children == NULL) {
1955 reader->state = XML_TEXTREADER_END;
1956 return(0);
1957 }
1958
1959 reader->node = reader->doc->children;
1960 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001961 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001962 }
1963
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001964 if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1965 (reader->node->type != XML_DTD_NODE) &&
1966 (reader->node->type != XML_XINCLUDE_START) &&
1967 (reader->node->type != XML_ENTITY_REF_NODE)) {
1968 if (reader->node->children != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001969 reader->node = reader->node->children;
1970 reader->depth++;
1971 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001972 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001973 }
1974
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001975 if (reader->node->type == XML_ATTRIBUTE_NODE) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001976 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001977 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001978 }
1979 }
1980
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001981 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001982 reader->node = reader->node->next;
1983 reader->state = XML_TEXTREADER_START;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001984 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001985 }
1986
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001987 if (reader->node->parent != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001988 if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1989 (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
1990 reader->state = XML_TEXTREADER_END;
1991 return(0);
1992 }
1993
1994 reader->node = reader->node->parent;
1995 reader->depth--;
1996 reader->state = XML_TEXTREADER_BACKTRACK;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00001997 goto found_node;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00001998 }
1999
2000 reader->state = XML_TEXTREADER_END;
2001
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002002found_node:
2003 if ((reader->node->type == XML_XINCLUDE_START) ||
2004 (reader->node->type == XML_XINCLUDE_END))
2005 goto next_node;
2006
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002007 return(1);
2008}
2009
2010/**
William M. Brackb1d53162003-11-18 06:54:40 +00002011 * xmlTextReaderNextSibling:
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002012 * @reader: the xmlTextReaderPtr used
2013 *
2014 * Skip to the node following the current one in document order while
2015 * avoiding the subtree if any.
2016 * Currently implemented only for Readers built on a document
2017 *
2018 * Returns 1 if the node was read successfully, 0 if there is no more
2019 * nodes to read, or -1 in case of error
2020 */
2021int
2022xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2023 if (reader == NULL)
2024 return(-1);
2025 if (reader->doc == NULL) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +00002026 /* TODO */
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002027 return(-1);
2028 }
2029
2030 if (reader->state == XML_TEXTREADER_END)
2031 return(0);
2032
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002033 if (reader->node == NULL)
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002034 return(xmlTextReaderNextTree(reader));
2035
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002036 if (reader->node->next != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002037 reader->node = reader->node->next;
2038 reader->state = XML_TEXTREADER_START;
2039 return(1);
2040 }
2041
2042 return(0);
2043}
2044
2045/************************************************************************
2046 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002047 * Constructor and destructors *
2048 * *
2049 ************************************************************************/
2050/**
2051 * xmlNewTextReader:
2052 * @input: the xmlParserInputBufferPtr used to read data
Daniel Veillardea7751d2002-12-20 00:16:24 +00002053 * @URI: the URI information for the source if available
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002054 *
2055 * Create an xmlTextReader structure fed with @input
2056 *
2057 * Returns the new xmlTextReaderPtr or NULL in case of error
2058 */
2059xmlTextReaderPtr
Daniel Veillardea7751d2002-12-20 00:16:24 +00002060xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002061 xmlTextReaderPtr ret;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002062
2063 if (input == NULL)
2064 return(NULL);
2065 ret = xmlMalloc(sizeof(xmlTextReader));
2066 if (ret == NULL) {
2067 xmlGenericError(xmlGenericErrorContext,
2068 "xmlNewTextReader : malloc failed\n");
2069 return(NULL);
2070 }
2071 memset(ret, 0, sizeof(xmlTextReader));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002072 ret->doc = NULL;
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002073 ret->entTab = NULL;
2074 ret->entMax = 0;
2075 ret->entNr = 0;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002076 ret->input = input;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002077 ret->buffer = xmlBufCreateSize(100);
William M. Bracka3215c72004-07-31 16:24:01 +00002078 if (ret->buffer == NULL) {
2079 xmlFree(ret);
2080 xmlGenericError(xmlGenericErrorContext,
2081 "xmlNewTextReader : malloc failed\n");
2082 return(NULL);
2083 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002084 ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2085 if (ret->sax == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08002086 xmlBufFree(ret->buffer);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002087 xmlFree(ret);
2088 xmlGenericError(xmlGenericErrorContext,
2089 "xmlNewTextReader : malloc failed\n");
2090 return(NULL);
2091 }
Daniel Veillard81273902003-09-30 00:43:48 +00002092 xmlSAXVersion(ret->sax, 2);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002093 ret->startElement = ret->sax->startElement;
2094 ret->sax->startElement = xmlTextReaderStartElement;
2095 ret->endElement = ret->sax->endElement;
2096 ret->sax->endElement = xmlTextReaderEndElement;
Daniel Veillard81273902003-09-30 00:43:48 +00002097#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002098 if (ret->sax->initialized == XML_SAX2_MAGIC) {
Daniel Veillard81273902003-09-30 00:43:48 +00002099#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard07cb8222003-09-10 10:51:05 +00002100 ret->startElementNs = ret->sax->startElementNs;
2101 ret->sax->startElementNs = xmlTextReaderStartElementNs;
2102 ret->endElementNs = ret->sax->endElementNs;
2103 ret->sax->endElementNs = xmlTextReaderEndElementNs;
Daniel Veillard81273902003-09-30 00:43:48 +00002104#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard07cb8222003-09-10 10:51:05 +00002105 } else {
2106 ret->startElementNs = NULL;
2107 ret->endElementNs = NULL;
2108 }
Daniel Veillard81273902003-09-30 00:43:48 +00002109#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardea7751d2002-12-20 00:16:24 +00002110 ret->characters = ret->sax->characters;
2111 ret->sax->characters = xmlTextReaderCharacters;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002112 ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002113 ret->cdataBlock = ret->sax->cdataBlock;
2114 ret->sax->cdataBlock = xmlTextReaderCDataBlock;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002115
Daniel Veillard67df8092002-12-16 22:04:11 +00002116 ret->mode = XML_TEXTREADER_MODE_INITIAL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002117 ret->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002118 ret->curnode = NULL;
Daniel Veillard8aebce32012-07-16 14:42:31 +08002119 if (xmlBufUse(ret->input->buffer) < 4) {
William M. Brack899e64a2003-09-26 18:03:42 +00002120 xmlParserInputBufferRead(input, 4);
Daniel Veillard53350552003-09-18 13:35:51 +00002121 }
Daniel Veillard8aebce32012-07-16 14:42:31 +08002122 if (xmlBufUse(ret->input->buffer) >= 4) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002123 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08002124 (const char *) xmlBufContent(ret->input->buffer),
2125 4, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002126 ret->base = 0;
2127 ret->cur = 4;
2128 } else {
Daniel Veillardea7751d2002-12-20 00:16:24 +00002129 ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002130 ret->base = 0;
2131 ret->cur = 0;
2132 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002133
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002134 if (ret->ctxt == NULL) {
2135 xmlGenericError(xmlGenericErrorContext,
2136 "xmlNewTextReader : malloc failed\n");
Daniel Veillard8aebce32012-07-16 14:42:31 +08002137 xmlBufFree(ret->buffer);
Daniel Veillarda76fe5c2003-04-24 16:06:47 +00002138 xmlFree(ret->sax);
2139 xmlFree(ret);
2140 return(NULL);
2141 }
Daniel Veillard0df3bc32004-06-08 12:03:41 +00002142 ret->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002143 ret->ctxt->_private = ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002144 ret->ctxt->linenumbers = 1;
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002145 ret->ctxt->dictNames = 1;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002146 ret->allocs = XML_TEXTREADER_CTXT;
Daniel Veillard40412cd2003-09-03 13:28:32 +00002147 /*
2148 * use the parser dictionnary to allocate all elements and attributes names
2149 */
2150 ret->ctxt->docdict = 1;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002151 ret->dict = ret->ctxt->dict;
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002152#ifdef LIBXML_XINCLUDE_ENABLED
2153 ret->xinclude = 0;
2154#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002155#ifdef LIBXML_PATTERN_ENABLED
2156 ret->patternMax = 0;
2157 ret->patternTab = NULL;
2158#endif
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002159 return(ret);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002160}
2161
2162/**
2163 * xmlNewTextReaderFilename:
2164 * @URI: the URI of the resource to process
2165 *
2166 * Create an xmlTextReader structure fed with the resource at @URI
2167 *
2168 * Returns the new xmlTextReaderPtr or NULL in case of error
2169 */
2170xmlTextReaderPtr
2171xmlNewTextReaderFilename(const char *URI) {
2172 xmlParserInputBufferPtr input;
2173 xmlTextReaderPtr ret;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002174 char *directory = NULL;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002175
2176 input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2177 if (input == NULL)
2178 return(NULL);
Daniel Veillardea7751d2002-12-20 00:16:24 +00002179 ret = xmlNewTextReader(input, URI);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002180 if (ret == NULL) {
2181 xmlFreeParserInputBuffer(input);
2182 return(NULL);
2183 }
2184 ret->allocs |= XML_TEXTREADER_INPUT;
Daniel Veillardea7751d2002-12-20 00:16:24 +00002185 if (ret->ctxt->directory == NULL)
2186 directory = xmlParserGetDirectory(URI);
2187 if ((ret->ctxt->directory == NULL) && (directory != NULL))
2188 ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2189 if (directory != NULL)
2190 xmlFree(directory);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002191 return(ret);
2192}
2193
2194/**
2195 * xmlFreeTextReader:
2196 * @reader: the xmlTextReaderPtr
2197 *
2198 * Deallocate all the resources associated to the reader
2199 */
2200void
2201xmlFreeTextReader(xmlTextReaderPtr reader) {
2202 if (reader == NULL)
2203 return;
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002204#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardf4e55762003-04-15 23:32:22 +00002205 if (reader->rngSchemas != NULL) {
2206 xmlRelaxNGFree(reader->rngSchemas);
2207 reader->rngSchemas = NULL;
2208 }
2209 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08002210 if (! reader->rngPreserveCtxt)
2211 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillardf4e55762003-04-15 23:32:22 +00002212 reader->rngValidCtxt = NULL;
2213 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00002214 if (reader->xsdPlug != NULL) {
2215 xmlSchemaSAXUnplug(reader->xsdPlug);
2216 reader->xsdPlug = NULL;
2217 }
2218 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00002219 if (! reader->xsdPreserveCtxt)
2220 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00002221 reader->xsdValidCtxt = NULL;
2222 }
2223 if (reader->xsdSchemas != NULL) {
2224 xmlSchemaFree(reader->xsdSchemas);
2225 reader->xsdSchemas = NULL;
2226 }
Daniel Veillard37fc84d2003-05-09 19:38:15 +00002227#endif
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002228#ifdef LIBXML_XINCLUDE_ENABLED
2229 if (reader->xincctxt != NULL)
2230 xmlXIncludeFreeContext(reader->xincctxt);
2231#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00002232#ifdef LIBXML_PATTERN_ENABLED
2233 if (reader->patternTab != NULL) {
2234 int i;
2235 for (i = 0;i < reader->patternNr;i++) {
2236 if (reader->patternTab[i] != NULL)
2237 xmlFreePattern(reader->patternTab[i]);
2238 }
2239 xmlFree(reader->patternTab);
2240 }
2241#endif
Daniel Veillardf4653dc2009-08-21 18:40:50 +02002242 if (reader->faketext != NULL) {
2243 xmlFreeNode(reader->faketext);
2244 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002245 if (reader->ctxt != NULL) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002246 if (reader->dict == reader->ctxt->dict)
2247 reader->dict = NULL;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002248 if (reader->ctxt->myDoc != NULL) {
2249 if (reader->preserve == 0)
2250 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2251 reader->ctxt->myDoc = NULL;
2252 }
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002253 if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2254 (reader->ctxt->vctxt.vstateMax > 0)){
2255 xmlFree(reader->ctxt->vctxt.vstateTab);
Daniel Veillard75e389d2005-07-29 22:02:24 +00002256 reader->ctxt->vctxt.vstateTab = NULL;
Daniel Veillard336fc7d2002-12-27 19:37:04 +00002257 reader->ctxt->vctxt.vstateMax = 0;
2258 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002259 if (reader->allocs & XML_TEXTREADER_CTXT)
2260 xmlFreeParserCtxt(reader->ctxt);
2261 }
2262 if (reader->sax != NULL)
2263 xmlFree(reader->sax);
2264 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
2265 xmlFreeParserInputBuffer(reader->input);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002266 if (reader->buffer != NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08002267 xmlBufFree(reader->buffer);
Daniel Veillard1fdfd112003-01-03 01:18:43 +00002268 if (reader->entTab != NULL)
2269 xmlFree(reader->entTab);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00002270 if (reader->dict != NULL)
2271 xmlDictFree(reader->dict);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002272 xmlFree(reader);
2273}
2274
2275/************************************************************************
2276 * *
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002277 * Methods for XmlTextReader *
2278 * *
2279 ************************************************************************/
2280/**
2281 * xmlTextReaderClose:
2282 * @reader: the xmlTextReaderPtr used
2283 *
2284 * This method releases any resources allocated by the current instance
2285 * changes the state to Closed and close any underlying input.
2286 *
2287 * Returns 0 or -1 in case of error
2288 */
2289int
2290xmlTextReaderClose(xmlTextReaderPtr reader) {
2291 if (reader == NULL)
2292 return(-1);
2293 reader->node = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002294 reader->curnode = NULL;
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002295 reader->mode = XML_TEXTREADER_MODE_CLOSED;
2296 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002297 xmlStopParser(reader->ctxt);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002298 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002299 if (reader->preserve == 0)
2300 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002301 reader->ctxt->myDoc = NULL;
2302 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002303 }
2304 if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
2305 xmlFreeParserInputBuffer(reader->input);
2306 reader->allocs -= XML_TEXTREADER_INPUT;
2307 }
2308 return(0);
2309}
2310
2311/**
2312 * xmlTextReaderGetAttributeNo:
2313 * @reader: the xmlTextReaderPtr used
2314 * @no: the zero-based index of the attribute relative to the containing element
2315 *
2316 * Provides the value of the attribute with the specified index relative
2317 * to the containing element.
2318 *
2319 * Returns a string containing the value of the specified attribute, or NULL
2320 * in case of error. The string must be deallocated by the caller.
2321 */
2322xmlChar *
2323xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2324 xmlChar *ret;
2325 int i;
2326 xmlAttrPtr cur;
2327 xmlNsPtr ns;
2328
2329 if (reader == NULL)
2330 return(NULL);
2331 if (reader->node == NULL)
2332 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002333 if (reader->curnode != NULL)
2334 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002335 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002336 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002337 return(NULL);
2338
2339 ns = reader->node->nsDef;
2340 for (i = 0;(i < no) && (ns != NULL);i++) {
2341 ns = ns->next;
2342 }
2343 if (ns != NULL)
2344 return(xmlStrdup(ns->href));
2345
2346 cur = reader->node->properties;
2347 if (cur == NULL)
2348 return(NULL);
2349 for (;i < no;i++) {
2350 cur = cur->next;
2351 if (cur == NULL)
2352 return(NULL);
2353 }
2354 /* TODO walk the DTD if present */
2355
2356 ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2357 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2358 return(ret);
2359}
2360
2361/**
2362 * xmlTextReaderGetAttribute:
2363 * @reader: the xmlTextReaderPtr used
2364 * @name: the qualified name of the attribute.
2365 *
2366 * Provides the value of the attribute with the specified qualified name.
2367 *
2368 * Returns a string containing the value of the specified attribute, or NULL
2369 * in case of error. The string must be deallocated by the caller.
2370 */
2371xmlChar *
2372xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2373 xmlChar *prefix = NULL;
2374 xmlChar *localname;
2375 xmlNsPtr ns;
2376 xmlChar *ret = NULL;
2377
2378 if ((reader == NULL) || (name == NULL))
2379 return(NULL);
2380 if (reader->node == NULL)
2381 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002382 if (reader->curnode != NULL)
2383 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002384
2385 /* TODO: handle the xmlDecl */
2386 if (reader->node->type != XML_ELEMENT_NODE)
2387 return(NULL);
2388
2389 localname = xmlSplitQName2(name, &prefix);
Daniel Veillard3c40e612005-08-17 07:07:44 +00002390 if (localname == NULL) {
2391 /*
2392 * Namespace default decl
2393 */
2394 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2395 ns = reader->node->nsDef;
2396 while (ns != NULL) {
2397 if (ns->prefix == NULL) {
2398 return(xmlStrdup(ns->href));
2399 }
2400 ns = ns->next;
2401 }
2402 return NULL;
2403 }
2404 return(xmlGetNoNsProp(reader->node, name));
2405 }
2406
2407 /*
2408 * Namespace default decl
2409 */
2410 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2411 ns = reader->node->nsDef;
2412 while (ns != NULL) {
2413 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2414 ret = xmlStrdup(ns->href);
2415 break;
2416 }
2417 ns = ns->next;
2418 }
2419 } else {
2420 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2421 if (ns != NULL)
2422 ret = xmlGetNsProp(reader->node, localname, ns->href);
2423 }
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002424
Daniel Veillardc4ff8322005-08-08 07:45:23 +00002425 xmlFree(localname);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002426 if (prefix != NULL)
2427 xmlFree(prefix);
2428 return(ret);
2429}
2430
2431
2432/**
2433 * xmlTextReaderGetAttributeNs:
2434 * @reader: the xmlTextReaderPtr used
2435 * @localName: the local name of the attribute.
2436 * @namespaceURI: the namespace URI of the attribute.
2437 *
2438 * Provides the value of the specified attribute
2439 *
2440 * Returns a string containing the value of the specified attribute, or NULL
2441 * in case of error. The string must be deallocated by the caller.
2442 */
2443xmlChar *
2444xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2445 const xmlChar *namespaceURI) {
Daniel Veillard45b97e72005-08-20 21:14:28 +00002446 xmlChar *prefix = NULL;
2447 xmlNsPtr ns;
2448
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002449 if ((reader == NULL) || (localName == NULL))
2450 return(NULL);
2451 if (reader->node == NULL)
2452 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002453 if (reader->curnode != NULL)
2454 return(NULL);
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002455
2456 /* TODO: handle the xmlDecl */
2457 if (reader->node->type != XML_ELEMENT_NODE)
2458 return(NULL);
2459
Daniel Veillard45b97e72005-08-20 21:14:28 +00002460 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2461 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2462 prefix = BAD_CAST localName;
2463 }
2464 ns = reader->node->nsDef;
2465 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002466 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002467 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2468 return xmlStrdup(ns->href);
2469 }
2470 ns = ns->next;
2471 }
2472 return NULL;
2473 }
2474
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002475 return(xmlGetNsProp(reader->node, localName, namespaceURI));
2476}
2477
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002478/**
2479 * xmlTextReaderGetRemainder:
2480 * @reader: the xmlTextReaderPtr used
2481 *
2482 * Method to get the remainder of the buffered XML. this method stops the
2483 * parser, set its state to End Of File and return the input stream with
2484 * what is left that the parser did not use.
2485 *
Daniel Veillardee1d6922004-04-18 14:58:57 +00002486 * The implementation is not good, the parser certainly procgressed past
2487 * what's left in reader->input, and there is an allocation problem. Best
2488 * would be to rewrite it differently.
2489 *
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002490 * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2491 * in case of error.
2492 */
2493xmlParserInputBufferPtr
2494xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2495 xmlParserInputBufferPtr ret = NULL;
2496
2497 if (reader == NULL)
2498 return(NULL);
2499 if (reader->node == NULL)
2500 return(NULL);
2501
2502 reader->node = NULL;
2503 reader->curnode = NULL;
2504 reader->mode = XML_TEXTREADER_MODE_EOF;
2505 if (reader->ctxt != NULL) {
Daniel Veillardee1d6922004-04-18 14:58:57 +00002506 xmlStopParser(reader->ctxt);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002507 if (reader->ctxt->myDoc != NULL) {
Daniel Veillard9ee35f32003-09-28 00:19:54 +00002508 if (reader->preserve == 0)
2509 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002510 reader->ctxt->myDoc = NULL;
2511 }
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002512 }
2513 if (reader->allocs & XML_TEXTREADER_INPUT) {
2514 ret = reader->input;
Daniel Veillardee1d6922004-04-18 14:58:57 +00002515 reader->input = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002516 reader->allocs -= XML_TEXTREADER_INPUT;
2517 } else {
2518 /*
2519 * Hum, one may need to duplicate the data structure because
2520 * without reference counting the input may be freed twice:
2521 * - by the layer which allocated it.
2522 * - by the layer to which would have been returned to.
2523 */
2524 TODO
2525 return(NULL);
2526 }
2527 return(ret);
2528}
2529
2530/**
2531 * xmlTextReaderLookupNamespace:
2532 * @reader: the xmlTextReaderPtr used
2533 * @prefix: the prefix whose namespace URI is to be resolved. To return
2534 * the default namespace, specify NULL
2535 *
2536 * Resolves a namespace prefix in the scope of the current element.
2537 *
2538 * Returns a string containing the namespace URI to which the prefix maps
2539 * or NULL in case of error. The string must be deallocated by the caller.
2540 */
2541xmlChar *
2542xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2543 xmlNsPtr ns;
2544
2545 if (reader == NULL)
2546 return(NULL);
2547 if (reader->node == NULL)
2548 return(NULL);
2549
2550 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2551 if (ns == NULL)
2552 return(NULL);
2553 return(xmlStrdup(ns->href));
2554}
2555
2556/**
2557 * xmlTextReaderMoveToAttributeNo:
2558 * @reader: the xmlTextReaderPtr used
2559 * @no: the zero-based index of the attribute relative to the containing
2560 * element.
2561 *
2562 * Moves the position of the current instance to the attribute with
2563 * the specified index relative to the containing element.
2564 *
2565 * Returns 1 in case of success, -1 in case of error, 0 if not found
2566 */
2567int
2568xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2569 int i;
2570 xmlAttrPtr cur;
2571 xmlNsPtr ns;
2572
2573 if (reader == NULL)
2574 return(-1);
2575 if (reader->node == NULL)
2576 return(-1);
2577 /* TODO: handle the xmlDecl */
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002578 if (reader->node->type != XML_ELEMENT_NODE)
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002579 return(-1);
2580
2581 reader->curnode = NULL;
2582
2583 ns = reader->node->nsDef;
2584 for (i = 0;(i < no) && (ns != NULL);i++) {
2585 ns = ns->next;
2586 }
2587 if (ns != NULL) {
2588 reader->curnode = (xmlNodePtr) ns;
2589 return(1);
2590 }
2591
2592 cur = reader->node->properties;
2593 if (cur == NULL)
2594 return(0);
2595 for (;i < no;i++) {
2596 cur = cur->next;
2597 if (cur == NULL)
2598 return(0);
2599 }
2600 /* TODO walk the DTD if present */
2601
2602 reader->curnode = (xmlNodePtr) cur;
2603 return(1);
2604}
2605
2606/**
2607 * xmlTextReaderMoveToAttribute:
2608 * @reader: the xmlTextReaderPtr used
2609 * @name: the qualified name of the attribute.
2610 *
2611 * Moves the position of the current instance to the attribute with
2612 * the specified qualified name.
2613 *
2614 * Returns 1 in case of success, -1 in case of error, 0 if not found
2615 */
2616int
2617xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2618 xmlChar *prefix = NULL;
2619 xmlChar *localname;
2620 xmlNsPtr ns;
2621 xmlAttrPtr prop;
2622
2623 if ((reader == NULL) || (name == NULL))
2624 return(-1);
2625 if (reader->node == NULL)
2626 return(-1);
2627
2628 /* TODO: handle the xmlDecl */
2629 if (reader->node->type != XML_ELEMENT_NODE)
2630 return(0);
2631
2632 localname = xmlSplitQName2(name, &prefix);
2633 if (localname == NULL) {
2634 /*
2635 * Namespace default decl
2636 */
2637 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2638 ns = reader->node->nsDef;
2639 while (ns != NULL) {
2640 if (ns->prefix == NULL) {
2641 reader->curnode = (xmlNodePtr) ns;
2642 return(1);
2643 }
2644 ns = ns->next;
2645 }
2646 return(0);
2647 }
2648
2649 prop = reader->node->properties;
2650 while (prop != NULL) {
2651 /*
2652 * One need to have
2653 * - same attribute names
2654 * - and the attribute carrying that namespace
2655 */
2656 if ((xmlStrEqual(prop->name, name)) &&
2657 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2658 reader->curnode = (xmlNodePtr) prop;
2659 return(1);
2660 }
2661 prop = prop->next;
2662 }
2663 return(0);
2664 }
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002665
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002666 /*
2667 * Namespace default decl
2668 */
2669 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2670 ns = reader->node->nsDef;
2671 while (ns != NULL) {
2672 if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2673 reader->curnode = (xmlNodePtr) ns;
2674 goto found;
2675 }
2676 ns = ns->next;
2677 }
2678 goto not_found;
2679 }
2680 prop = reader->node->properties;
2681 while (prop != NULL) {
2682 /*
2683 * One need to have
2684 * - same attribute names
2685 * - and the attribute carrying that namespace
2686 */
2687 if ((xmlStrEqual(prop->name, localname)) &&
2688 (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2689 reader->curnode = (xmlNodePtr) prop;
2690 goto found;
2691 }
2692 prop = prop->next;
2693 }
2694not_found:
2695 if (localname != NULL)
2696 xmlFree(localname);
2697 if (prefix != NULL)
2698 xmlFree(prefix);
2699 return(0);
2700
2701found:
2702 if (localname != NULL)
2703 xmlFree(localname);
2704 if (prefix != NULL)
2705 xmlFree(prefix);
2706 return(1);
2707}
2708
2709/**
2710 * xmlTextReaderMoveToAttributeNs:
2711 * @reader: the xmlTextReaderPtr used
2712 * @localName: the local name of the attribute.
2713 * @namespaceURI: the namespace URI of the attribute.
2714 *
2715 * Moves the position of the current instance to the attribute with the
2716 * specified local name and namespace URI.
2717 *
2718 * Returns 1 in case of success, -1 in case of error, 0 if not found
2719 */
2720int
2721xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2722 const xmlChar *localName, const xmlChar *namespaceURI) {
2723 xmlAttrPtr prop;
2724 xmlNodePtr node;
Daniel Veillard45b97e72005-08-20 21:14:28 +00002725 xmlNsPtr ns;
2726 xmlChar *prefix = NULL;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002727
2728 if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2729 return(-1);
2730 if (reader->node == NULL)
2731 return(-1);
2732 if (reader->node->type != XML_ELEMENT_NODE)
2733 return(0);
2734 node = reader->node;
2735
Daniel Veillard45b97e72005-08-20 21:14:28 +00002736 if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2737 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2738 prefix = BAD_CAST localName;
2739 }
2740 ns = reader->node->nsDef;
2741 while (ns != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002742 if ((prefix == NULL && ns->prefix == NULL) ||
Daniel Veillard45b97e72005-08-20 21:14:28 +00002743 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2744 reader->curnode = (xmlNodePtr) ns;
2745 return(1);
2746 }
2747 ns = ns->next;
2748 }
2749 return(0);
2750 }
2751
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002752 prop = node->properties;
2753 while (prop != NULL) {
2754 /*
2755 * One need to have
2756 * - same attribute names
2757 * - and the attribute carrying that namespace
2758 */
2759 if (xmlStrEqual(prop->name, localName) &&
2760 ((prop->ns != NULL) &&
2761 (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2762 reader->curnode = (xmlNodePtr) prop;
2763 return(1);
2764 }
2765 prop = prop->next;
2766 }
2767 return(0);
2768}
2769
2770/**
2771 * xmlTextReaderMoveToFirstAttribute:
2772 * @reader: the xmlTextReaderPtr used
2773 *
2774 * Moves the position of the current instance to the first attribute
2775 * associated with the current node.
2776 *
2777 * Returns 1 in case of success, -1 in case of error, 0 if not found
2778 */
2779int
2780xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2781 if (reader == NULL)
2782 return(-1);
2783 if (reader->node == NULL)
2784 return(-1);
2785 if (reader->node->type != XML_ELEMENT_NODE)
2786 return(0);
2787
2788 if (reader->node->nsDef != NULL) {
2789 reader->curnode = (xmlNodePtr) reader->node->nsDef;
2790 return(1);
2791 }
2792 if (reader->node->properties != NULL) {
2793 reader->curnode = (xmlNodePtr) reader->node->properties;
2794 return(1);
2795 }
2796 return(0);
2797}
2798
2799/**
2800 * xmlTextReaderMoveToNextAttribute:
2801 * @reader: the xmlTextReaderPtr used
2802 *
2803 * Moves the position of the current instance to the next attribute
2804 * associated with the current node.
2805 *
2806 * Returns 1 in case of success, -1 in case of error, 0 if not found
2807 */
2808int
2809xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2810 if (reader == NULL)
2811 return(-1);
2812 if (reader->node == NULL)
2813 return(-1);
2814 if (reader->node->type != XML_ELEMENT_NODE)
2815 return(0);
2816 if (reader->curnode == NULL)
2817 return(xmlTextReaderMoveToFirstAttribute(reader));
2818
2819 if (reader->curnode->type == XML_NAMESPACE_DECL) {
2820 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2821 if (ns->next != NULL) {
2822 reader->curnode = (xmlNodePtr) ns->next;
2823 return(1);
2824 }
2825 if (reader->node->properties != NULL) {
2826 reader->curnode = (xmlNodePtr) reader->node->properties;
2827 return(1);
2828 }
2829 return(0);
2830 } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2831 (reader->curnode->next != NULL)) {
2832 reader->curnode = reader->curnode->next;
2833 return(1);
2834 }
2835 return(0);
2836}
2837
2838/**
2839 * xmlTextReaderMoveToElement:
2840 * @reader: the xmlTextReaderPtr used
2841 *
2842 * Moves the position of the current instance to the node that
2843 * contains the current Attribute node.
2844 *
2845 * Returns 1 in case of success, -1 in case of error, 0 if not moved
2846 */
2847int
2848xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2849 if (reader == NULL)
2850 return(-1);
2851 if (reader->node == NULL)
2852 return(-1);
2853 if (reader->node->type != XML_ELEMENT_NODE)
2854 return(0);
2855 if (reader->curnode != NULL) {
2856 reader->curnode = NULL;
2857 return(1);
2858 }
2859 return(0);
2860}
2861
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002862/**
2863 * xmlTextReaderReadAttributeValue:
2864 * @reader: the xmlTextReaderPtr used
2865 *
2866 * Parses an attribute value into one or more Text and EntityReference nodes.
2867 *
2868 * Returns 1 in case of success, 0 if the reader was not positionned on an
2869 * ttribute node or all the attribute values have been read, or -1
2870 * in case of error.
2871 */
2872int
2873xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2874 if (reader == NULL)
2875 return(-1);
2876 if (reader->node == NULL)
2877 return(-1);
2878 if (reader->curnode == NULL)
2879 return(0);
2880 if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2881 if (reader->curnode->children == NULL)
2882 return(0);
2883 reader->curnode = reader->curnode->children;
2884 } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2885 xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2886
2887 if (reader->faketext == NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002888 reader->faketext = xmlNewDocText(reader->node->doc,
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002889 ns->href);
2890 } else {
Daniel Veillard8874b942005-08-25 13:19:21 +00002891 if ((reader->faketext->content != NULL) &&
2892 (reader->faketext->content !=
2893 (xmlChar *) &(reader->faketext->properties)))
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00002894 xmlFree(reader->faketext->content);
2895 reader->faketext->content = xmlStrdup(ns->href);
2896 }
2897 reader->curnode = reader->faketext;
2898 } else {
2899 if (reader->curnode->next == NULL)
2900 return(0);
2901 reader->curnode = reader->curnode->next;
2902 }
2903 return(1);
2904}
2905
Daniel Veillarde2811272004-10-19 09:04:23 +00002906/**
2907 * xmlTextReaderConstEncoding:
2908 * @reader: the xmlTextReaderPtr used
2909 *
2910 * Determine the encoding of the document being read.
2911 *
2912 * Returns a string containing the encoding of the document or NULL in
2913 * case of error. The string is deallocated with the reader.
2914 */
2915const xmlChar *
2916xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2917 xmlDocPtr doc = NULL;
2918 if (reader == NULL)
2919 return(NULL);
2920 if (reader->doc != NULL)
2921 doc = reader->doc;
2922 else if (reader->ctxt != NULL)
2923 doc = reader->ctxt->myDoc;
2924 if (doc == NULL)
2925 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002926
Daniel Veillarde2811272004-10-19 09:04:23 +00002927 if (doc->encoding == NULL)
2928 return(NULL);
2929 else
2930 return(CONSTSTR(doc->encoding));
2931}
2932
2933
Daniel Veillard0eb38c72002-12-14 23:00:35 +00002934/************************************************************************
2935 * *
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002936 * Acces API to the current node *
2937 * *
2938 ************************************************************************/
2939/**
2940 * xmlTextReaderAttributeCount:
2941 * @reader: the xmlTextReaderPtr used
2942 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +00002943 * Provides the number of attributes of the current node
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002944 *
2945 * Returns 0 i no attributes, -1 in case of error or the attribute count
2946 */
2947int
2948xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2949 int ret;
2950 xmlAttrPtr attr;
Daniel Veillard67df8092002-12-16 22:04:11 +00002951 xmlNsPtr ns;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002952 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002953
2954 if (reader == NULL)
2955 return(-1);
2956 if (reader->node == NULL)
2957 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002958
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002959 if (reader->curnode != NULL)
2960 node = reader->curnode;
2961 else
2962 node = reader->node;
2963
2964 if (node->type != XML_ELEMENT_NODE)
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002965 return(0);
2966 if ((reader->state == XML_TEXTREADER_END) ||
2967 (reader->state == XML_TEXTREADER_BACKTRACK))
2968 return(0);
2969 ret = 0;
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002970 attr = node->properties;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002971 while (attr != NULL) {
2972 ret++;
2973 attr = attr->next;
2974 }
Daniel Veillard67df8092002-12-16 22:04:11 +00002975 ns = node->nsDef;
2976 while (ns != NULL) {
2977 ret++;
2978 ns = ns->next;
2979 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002980 return(ret);
2981}
2982
2983/**
2984 * xmlTextReaderNodeType:
2985 * @reader: the xmlTextReaderPtr used
2986 *
2987 * Get the node type of the current node
2988 * Reference:
Daniel Veillard354cf5c2008-04-07 12:46:48 +00002989 * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002990 *
2991 * Returns the xmlNodeType of the current node or -1 in case of error
2992 */
2993int
2994xmlTextReaderNodeType(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00002995 xmlNodePtr node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02002996
Daniel Veillarde1ca5032002-12-09 14:13:43 +00002997 if (reader == NULL)
2998 return(-1);
2999 if (reader->node == NULL)
Daniel Veillardd6038e02003-07-30 16:37:18 +00003000 return(XML_READER_TYPE_NONE);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003001 if (reader->curnode != NULL)
3002 node = reader->curnode;
3003 else
3004 node = reader->node;
3005 switch (node->type) {
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003006 case XML_ELEMENT_NODE:
3007 if ((reader->state == XML_TEXTREADER_END) ||
3008 (reader->state == XML_TEXTREADER_BACKTRACK))
Daniel Veillardd6038e02003-07-30 16:37:18 +00003009 return(XML_READER_TYPE_END_ELEMENT);
3010 return(XML_READER_TYPE_ELEMENT);
Daniel Veillardecaba492002-12-30 10:55:29 +00003011 case XML_NAMESPACE_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003012 case XML_ATTRIBUTE_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003013 return(XML_READER_TYPE_ATTRIBUTE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003014 case XML_TEXT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003015 if (xmlIsBlankNode(reader->node)) {
3016 if (xmlNodeGetSpacePreserve(reader->node))
3017 return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3018 else
3019 return(XML_READER_TYPE_WHITESPACE);
3020 } else {
3021 return(XML_READER_TYPE_TEXT);
3022 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003023 case XML_CDATA_SECTION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003024 return(XML_READER_TYPE_CDATA);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003025 case XML_ENTITY_REF_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003026 return(XML_READER_TYPE_ENTITY_REFERENCE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003027 case XML_ENTITY_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003028 return(XML_READER_TYPE_ENTITY);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003029 case XML_PI_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003030 return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003031 case XML_COMMENT_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003032 return(XML_READER_TYPE_COMMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003033 case XML_DOCUMENT_NODE:
3034 case XML_HTML_DOCUMENT_NODE:
3035#ifdef LIBXML_DOCB_ENABLED
3036 case XML_DOCB_DOCUMENT_NODE:
3037#endif
Daniel Veillardd6038e02003-07-30 16:37:18 +00003038 return(XML_READER_TYPE_DOCUMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003039 case XML_DOCUMENT_FRAG_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003040 return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003041 case XML_NOTATION_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003042 return(XML_READER_TYPE_NOTATION);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003043 case XML_DOCUMENT_TYPE_NODE:
3044 case XML_DTD_NODE:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003045 return(XML_READER_TYPE_DOCUMENT_TYPE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003046
3047 case XML_ELEMENT_DECL:
3048 case XML_ATTRIBUTE_DECL:
3049 case XML_ENTITY_DECL:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003050 case XML_XINCLUDE_START:
3051 case XML_XINCLUDE_END:
Daniel Veillardd6038e02003-07-30 16:37:18 +00003052 return(XML_READER_TYPE_NONE);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003053 }
3054 return(-1);
3055}
3056
3057/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00003058 * xmlTextReaderIsEmptyElement:
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003059 * @reader: the xmlTextReaderPtr used
3060 *
3061 * Check if the current node is empty
3062 *
3063 * Returns 1 if empty, 0 if not and -1 in case of error
3064 */
3065int
3066xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3067 if ((reader == NULL) || (reader->node == NULL))
3068 return(-1);
Daniel Veillarddf512f42002-12-23 15:56:21 +00003069 if (reader->node->type != XML_ELEMENT_NODE)
3070 return(0);
Daniel Veillarde3c036e2003-01-01 15:11:05 +00003071 if (reader->curnode != NULL)
3072 return(0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003073 if (reader->node->children != NULL)
3074 return(0);
Daniel Veillarddab8ea92003-01-02 14:16:45 +00003075 if (reader->state == XML_TEXTREADER_END)
3076 return(0);
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003077 if (reader->doc != NULL)
3078 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003079#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard7899c5c2003-11-03 12:31:38 +00003080 if (reader->in_xinclude > 0)
3081 return(1);
Daniel Veillard96b6cd22004-01-08 16:49:50 +00003082#endif
Daniel Veillarde8039df2003-10-27 11:25:13 +00003083 return((reader->node->extra & NODE_IS_EMPTY) != 0);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003084}
3085
3086/**
3087 * xmlTextReaderLocalName:
3088 * @reader: the xmlTextReaderPtr used
3089 *
3090 * The local name of the node.
3091 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003092 * Returns the local name or NULL if not available,
3093 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003094 */
3095xmlChar *
3096xmlTextReaderLocalName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003097 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003098 if ((reader == NULL) || (reader->node == NULL))
3099 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003100 if (reader->curnode != NULL)
3101 node = reader->curnode;
3102 else
3103 node = reader->node;
3104 if (node->type == XML_NAMESPACE_DECL) {
3105 xmlNsPtr ns = (xmlNsPtr) node;
3106 if (ns->prefix == NULL)
3107 return(xmlStrdup(BAD_CAST "xmlns"));
3108 else
3109 return(xmlStrdup(ns->prefix));
3110 }
3111 if ((node->type != XML_ELEMENT_NODE) &&
3112 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003113 return(xmlTextReaderName(reader));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003114 return(xmlStrdup(node->name));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003115}
3116
3117/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003118 * xmlTextReaderConstLocalName:
3119 * @reader: the xmlTextReaderPtr used
3120 *
3121 * The local name of the node.
3122 *
3123 * Returns the local name or NULL if not available, the
3124 * string will be deallocated with the reader.
3125 */
3126const xmlChar *
3127xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3128 xmlNodePtr node;
3129 if ((reader == NULL) || (reader->node == NULL))
3130 return(NULL);
3131 if (reader->curnode != NULL)
3132 node = reader->curnode;
3133 else
3134 node = reader->node;
3135 if (node->type == XML_NAMESPACE_DECL) {
3136 xmlNsPtr ns = (xmlNsPtr) node;
3137 if (ns->prefix == NULL)
3138 return(CONSTSTR(BAD_CAST "xmlns"));
3139 else
3140 return(ns->prefix);
3141 }
3142 if ((node->type != XML_ELEMENT_NODE) &&
3143 (node->type != XML_ATTRIBUTE_NODE))
3144 return(xmlTextReaderConstName(reader));
3145 return(node->name);
3146}
3147
3148/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003149 * xmlTextReaderName:
3150 * @reader: the xmlTextReaderPtr used
3151 *
3152 * The qualified name of the node, equal to Prefix :LocalName.
3153 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003154 * Returns the local name or NULL if not available,
3155 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003156 */
3157xmlChar *
3158xmlTextReaderName(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003159 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003160 xmlChar *ret;
3161
3162 if ((reader == NULL) || (reader->node == NULL))
3163 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003164 if (reader->curnode != NULL)
3165 node = reader->curnode;
3166 else
3167 node = reader->node;
3168 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003169 case XML_ELEMENT_NODE:
3170 case XML_ATTRIBUTE_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003171 if ((node->ns == NULL) ||
3172 (node->ns->prefix == NULL))
3173 return(xmlStrdup(node->name));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003174
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003175 ret = xmlStrdup(node->ns->prefix);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003176 ret = xmlStrcat(ret, BAD_CAST ":");
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003177 ret = xmlStrcat(ret, node->name);
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003178 return(ret);
3179 case XML_TEXT_NODE:
3180 return(xmlStrdup(BAD_CAST "#text"));
3181 case XML_CDATA_SECTION_NODE:
3182 return(xmlStrdup(BAD_CAST "#cdata-section"));
3183 case XML_ENTITY_NODE:
3184 case XML_ENTITY_REF_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003185 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003186 case XML_PI_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003187 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003188 case XML_COMMENT_NODE:
3189 return(xmlStrdup(BAD_CAST "#comment"));
3190 case XML_DOCUMENT_NODE:
3191 case XML_HTML_DOCUMENT_NODE:
3192#ifdef LIBXML_DOCB_ENABLED
3193 case XML_DOCB_DOCUMENT_NODE:
3194#endif
3195 return(xmlStrdup(BAD_CAST "#document"));
3196 case XML_DOCUMENT_FRAG_NODE:
3197 return(xmlStrdup(BAD_CAST "#document-fragment"));
3198 case XML_NOTATION_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003199 return(xmlStrdup(node->name));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003200 case XML_DOCUMENT_TYPE_NODE:
3201 case XML_DTD_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003202 return(xmlStrdup(node->name));
3203 case XML_NAMESPACE_DECL: {
3204 xmlNsPtr ns = (xmlNsPtr) node;
3205
3206 ret = xmlStrdup(BAD_CAST "xmlns");
3207 if (ns->prefix == NULL)
3208 return(ret);
3209 ret = xmlStrcat(ret, BAD_CAST ":");
3210 ret = xmlStrcat(ret, ns->prefix);
3211 return(ret);
3212 }
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003213
3214 case XML_ELEMENT_DECL:
3215 case XML_ATTRIBUTE_DECL:
3216 case XML_ENTITY_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003217 case XML_XINCLUDE_START:
3218 case XML_XINCLUDE_END:
3219 return(NULL);
3220 }
3221 return(NULL);
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003222}
3223
3224/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003225 * xmlTextReaderConstName:
3226 * @reader: the xmlTextReaderPtr used
3227 *
3228 * The qualified name of the node, equal to Prefix :LocalName.
3229 *
3230 * Returns the local name or NULL if not available, the string is
3231 * deallocated with the reader.
3232 */
3233const xmlChar *
3234xmlTextReaderConstName(xmlTextReaderPtr reader) {
3235 xmlNodePtr node;
3236
3237 if ((reader == NULL) || (reader->node == NULL))
3238 return(NULL);
3239 if (reader->curnode != NULL)
3240 node = reader->curnode;
3241 else
3242 node = reader->node;
3243 switch (node->type) {
3244 case XML_ELEMENT_NODE:
3245 case XML_ATTRIBUTE_NODE:
3246 if ((node->ns == NULL) ||
3247 (node->ns->prefix == NULL))
3248 return(node->name);
3249 return(CONSTQSTR(node->ns->prefix, node->name));
3250 case XML_TEXT_NODE:
3251 return(CONSTSTR(BAD_CAST "#text"));
3252 case XML_CDATA_SECTION_NODE:
3253 return(CONSTSTR(BAD_CAST "#cdata-section"));
3254 case XML_ENTITY_NODE:
3255 case XML_ENTITY_REF_NODE:
3256 return(CONSTSTR(node->name));
3257 case XML_PI_NODE:
3258 return(CONSTSTR(node->name));
3259 case XML_COMMENT_NODE:
3260 return(CONSTSTR(BAD_CAST "#comment"));
3261 case XML_DOCUMENT_NODE:
3262 case XML_HTML_DOCUMENT_NODE:
3263#ifdef LIBXML_DOCB_ENABLED
3264 case XML_DOCB_DOCUMENT_NODE:
3265#endif
3266 return(CONSTSTR(BAD_CAST "#document"));
3267 case XML_DOCUMENT_FRAG_NODE:
3268 return(CONSTSTR(BAD_CAST "#document-fragment"));
3269 case XML_NOTATION_NODE:
3270 return(CONSTSTR(node->name));
3271 case XML_DOCUMENT_TYPE_NODE:
3272 case XML_DTD_NODE:
3273 return(CONSTSTR(node->name));
3274 case XML_NAMESPACE_DECL: {
3275 xmlNsPtr ns = (xmlNsPtr) node;
3276
3277 if (ns->prefix == NULL)
3278 return(CONSTSTR(BAD_CAST "xmlns"));
3279 return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3280 }
3281
3282 case XML_ELEMENT_DECL:
3283 case XML_ATTRIBUTE_DECL:
3284 case XML_ENTITY_DECL:
3285 case XML_XINCLUDE_START:
3286 case XML_XINCLUDE_END:
3287 return(NULL);
3288 }
3289 return(NULL);
3290}
3291
3292/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003293 * xmlTextReaderPrefix:
3294 * @reader: the xmlTextReaderPtr used
3295 *
3296 * A shorthand reference to the namespace associated with the node.
3297 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003298 * Returns the prefix or NULL if not available,
3299 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003300 */
3301xmlChar *
3302xmlTextReaderPrefix(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003303 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003304 if ((reader == NULL) || (reader->node == NULL))
3305 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003306 if (reader->curnode != NULL)
3307 node = reader->curnode;
3308 else
3309 node = reader->node;
3310 if (node->type == XML_NAMESPACE_DECL) {
3311 xmlNsPtr ns = (xmlNsPtr) node;
3312 if (ns->prefix == NULL)
3313 return(NULL);
3314 return(xmlStrdup(BAD_CAST "xmlns"));
3315 }
3316 if ((node->type != XML_ELEMENT_NODE) &&
3317 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003318 return(NULL);
Daniel Veillard952379b2003-03-17 15:37:12 +00003319 if ((node->ns != NULL) && (node->ns->prefix != NULL))
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003320 return(xmlStrdup(node->ns->prefix));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003321 return(NULL);
3322}
3323
3324/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003325 * xmlTextReaderConstPrefix:
3326 * @reader: the xmlTextReaderPtr used
3327 *
3328 * A shorthand reference to the namespace associated with the node.
3329 *
3330 * Returns the prefix or NULL if not available, the string is deallocated
3331 * with the reader.
3332 */
3333const xmlChar *
3334xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3335 xmlNodePtr node;
3336 if ((reader == NULL) || (reader->node == NULL))
3337 return(NULL);
3338 if (reader->curnode != NULL)
3339 node = reader->curnode;
3340 else
3341 node = reader->node;
3342 if (node->type == XML_NAMESPACE_DECL) {
3343 xmlNsPtr ns = (xmlNsPtr) node;
3344 if (ns->prefix == NULL)
3345 return(NULL);
3346 return(CONSTSTR(BAD_CAST "xmlns"));
3347 }
3348 if ((node->type != XML_ELEMENT_NODE) &&
3349 (node->type != XML_ATTRIBUTE_NODE))
3350 return(NULL);
3351 if ((node->ns != NULL) && (node->ns->prefix != NULL))
3352 return(CONSTSTR(node->ns->prefix));
3353 return(NULL);
3354}
3355
3356/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003357 * xmlTextReaderNamespaceUri:
3358 * @reader: the xmlTextReaderPtr used
3359 *
3360 * The URI defining the namespace associated with the node.
3361 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003362 * Returns the namespace URI or NULL if not available,
3363 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003364 */
3365xmlChar *
3366xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003367 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003368 if ((reader == NULL) || (reader->node == NULL))
3369 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003370 if (reader->curnode != NULL)
3371 node = reader->curnode;
3372 else
3373 node = reader->node;
Daniel Veillardecaba492002-12-30 10:55:29 +00003374 if (node->type == XML_NAMESPACE_DECL)
3375 return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003376 if ((node->type != XML_ELEMENT_NODE) &&
3377 (node->type != XML_ATTRIBUTE_NODE))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003378 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003379 if (node->ns != NULL)
3380 return(xmlStrdup(node->ns->href));
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003381 return(NULL);
3382}
3383
3384/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003385 * xmlTextReaderConstNamespaceUri:
3386 * @reader: the xmlTextReaderPtr used
3387 *
3388 * The URI defining the namespace associated with the node.
3389 *
3390 * Returns the namespace URI or NULL if not available, the string
3391 * will be deallocated with the reader
3392 */
3393const xmlChar *
3394xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3395 xmlNodePtr node;
3396 if ((reader == NULL) || (reader->node == NULL))
3397 return(NULL);
3398 if (reader->curnode != NULL)
3399 node = reader->curnode;
3400 else
3401 node = reader->node;
3402 if (node->type == XML_NAMESPACE_DECL)
3403 return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3404 if ((node->type != XML_ELEMENT_NODE) &&
3405 (node->type != XML_ATTRIBUTE_NODE))
3406 return(NULL);
3407 if (node->ns != NULL)
3408 return(CONSTSTR(node->ns->href));
3409 return(NULL);
3410}
3411
3412/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003413 * xmlTextReaderBaseUri:
3414 * @reader: the xmlTextReaderPtr used
3415 *
3416 * The base URI of the node.
3417 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003418 * Returns the base URI or NULL if not available,
3419 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003420 */
3421xmlChar *
3422xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3423 if ((reader == NULL) || (reader->node == NULL))
3424 return(NULL);
3425 return(xmlNodeGetBase(NULL, reader->node));
3426}
3427
3428/**
Daniel Veillarde72c5082003-09-19 12:44:05 +00003429 * xmlTextReaderConstBaseUri:
3430 * @reader: the xmlTextReaderPtr used
3431 *
3432 * The base URI of the node.
3433 *
3434 * Returns the base URI or NULL if not available, the string
3435 * will be deallocated with the reader
3436 */
3437const xmlChar *
3438xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3439 xmlChar *tmp;
3440 const xmlChar *ret;
3441
3442 if ((reader == NULL) || (reader->node == NULL))
3443 return(NULL);
3444 tmp = xmlNodeGetBase(NULL, reader->node);
3445 if (tmp == NULL)
3446 return(NULL);
3447 ret = CONSTSTR(tmp);
3448 xmlFree(tmp);
3449 return(ret);
3450}
3451
3452/**
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003453 * xmlTextReaderDepth:
3454 * @reader: the xmlTextReaderPtr used
3455 *
3456 * The depth of the node in the tree.
3457 *
3458 * Returns the depth or -1 in case of error
3459 */
3460int
3461xmlTextReaderDepth(xmlTextReaderPtr reader) {
3462 if (reader == NULL)
3463 return(-1);
3464 if (reader->node == NULL)
3465 return(0);
3466
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003467 if (reader->curnode != NULL) {
3468 if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3469 (reader->curnode->type == XML_NAMESPACE_DECL))
3470 return(reader->depth + 1);
3471 return(reader->depth + 2);
3472 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003473 return(reader->depth);
3474}
3475
3476/**
3477 * xmlTextReaderHasAttributes:
3478 * @reader: the xmlTextReaderPtr used
3479 *
3480 * Whether the node has attributes.
3481 *
3482 * Returns 1 if true, 0 if false, and -1 in case or error
3483 */
3484int
3485xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003486 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003487 if (reader == NULL)
3488 return(-1);
3489 if (reader->node == NULL)
3490 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003491 if (reader->curnode != NULL)
3492 node = reader->curnode;
3493 else
3494 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003495
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003496 if ((node->type == XML_ELEMENT_NODE) &&
Daniel Veillard6bb3e862004-11-24 12:39:00 +00003497 ((node->properties != NULL) || (node->nsDef != NULL)))
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003498 return(1);
3499 /* TODO: handle the xmlDecl */
3500 return(0);
3501}
3502
3503/**
3504 * xmlTextReaderHasValue:
3505 * @reader: the xmlTextReaderPtr used
3506 *
3507 * Whether the node can have a text value.
3508 *
3509 * Returns 1 if true, 0 if false, and -1 in case or error
3510 */
3511int
3512xmlTextReaderHasValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003513 xmlNodePtr node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003514 if (reader == NULL)
3515 return(-1);
3516 if (reader->node == NULL)
3517 return(0);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003518 if (reader->curnode != NULL)
3519 node = reader->curnode;
3520 else
3521 node = reader->node;
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003522
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003523 switch (node->type) {
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003524 case XML_ATTRIBUTE_NODE:
3525 case XML_TEXT_NODE:
3526 case XML_CDATA_SECTION_NODE:
3527 case XML_PI_NODE:
3528 case XML_COMMENT_NODE:
Daniel Veillard9e077102003-04-10 13:36:54 +00003529 case XML_NAMESPACE_DECL:
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003530 return(1);
3531 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003532 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003533 }
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003534 return(0);
3535}
3536
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003537/**
3538 * xmlTextReaderValue:
3539 * @reader: the xmlTextReaderPtr used
3540 *
3541 * Provides the text value of the node if present
3542 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003543 * Returns the string or NULL if not available. The result must be deallocated
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003544 * with xmlFree()
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003545 */
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003546xmlChar *
3547xmlTextReaderValue(xmlTextReaderPtr reader) {
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003548 xmlNodePtr node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003549 if (reader == NULL)
3550 return(NULL);
3551 if (reader->node == NULL)
3552 return(NULL);
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003553 if (reader->curnode != NULL)
3554 node = reader->curnode;
3555 else
3556 node = reader->node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003557
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003558 switch (node->type) {
3559 case XML_NAMESPACE_DECL:
3560 return(xmlStrdup(((xmlNsPtr) node)->href));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003561 case XML_ATTRIBUTE_NODE:{
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003562 xmlAttrPtr attr = (xmlAttrPtr) node;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003563
3564 if (attr->parent != NULL)
3565 return (xmlNodeListGetString
3566 (attr->parent->doc, attr->children, 1));
3567 else
3568 return (xmlNodeListGetString(NULL, attr->children, 1));
3569 break;
3570 }
3571 case XML_TEXT_NODE:
3572 case XML_CDATA_SECTION_NODE:
3573 case XML_PI_NODE:
3574 case XML_COMMENT_NODE:
Daniel Veillardda46d2d2002-12-15 23:36:49 +00003575 if (node->content != NULL)
3576 return (xmlStrdup(node->content));
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003577 default:
Daniel Veillard2cfd9df2003-03-22 22:39:16 +00003578 break;
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003579 }
3580 return(NULL);
3581}
3582
3583/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003584 * xmlTextReaderConstValue:
3585 * @reader: the xmlTextReaderPtr used
3586 *
3587 * Provides the text value of the node if present
3588 *
3589 * Returns the string or NULL if not available. The result will be
3590 * deallocated on the next Read() operation.
3591 */
3592const xmlChar *
3593xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3594 xmlNodePtr node;
3595 if (reader == NULL)
3596 return(NULL);
3597 if (reader->node == NULL)
3598 return(NULL);
3599 if (reader->curnode != NULL)
3600 node = reader->curnode;
3601 else
3602 node = reader->node;
3603
3604 switch (node->type) {
3605 case XML_NAMESPACE_DECL:
3606 return(((xmlNsPtr) node)->href);
3607 case XML_ATTRIBUTE_NODE:{
3608 xmlAttrPtr attr = (xmlAttrPtr) node;
3609
3610 if ((attr->children != NULL) &&
3611 (attr->children->type == XML_TEXT_NODE) &&
3612 (attr->children->next == NULL))
3613 return(attr->children->content);
3614 else {
Daniel Veillard8165a6b2004-07-01 11:20:33 +00003615 if (reader->buffer == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08003616 reader->buffer = xmlBufCreateSize(100);
3617 if (reader->buffer == NULL) {
3618 xmlGenericError(xmlGenericErrorContext,
3619 "xmlTextReaderSetup : malloc failed\n");
3620 return (NULL);
3621 }
3622 } else
3623 xmlBufEmpty(reader->buffer);
3624 xmlBufGetNodeContent(reader->buffer, node);
3625 return(xmlBufContent(reader->buffer));
Daniel Veillard198c1bf2003-10-20 17:07:41 +00003626 }
3627 break;
3628 }
3629 case XML_TEXT_NODE:
3630 case XML_CDATA_SECTION_NODE:
3631 case XML_PI_NODE:
3632 case XML_COMMENT_NODE:
3633 return(node->content);
3634 default:
3635 break;
3636 }
3637 return(NULL);
3638}
3639
3640/**
Daniel Veillard9b4bb4d2002-12-11 19:28:47 +00003641 * xmlTextReaderIsDefault:
3642 * @reader: the xmlTextReaderPtr used
3643 *
3644 * Whether an Attribute node was generated from the default value
3645 * defined in the DTD or schema.
3646 *
3647 * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3648 */
3649int
3650xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3651 if (reader == NULL)
3652 return(-1);
3653 return(0);
3654}
3655
3656/**
3657 * xmlTextReaderQuoteChar:
3658 * @reader: the xmlTextReaderPtr used
3659 *
3660 * The quotation mark character used to enclose the value of an attribute.
3661 *
3662 * Returns " or ' and -1 in case of error
3663 */
3664int
3665xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3666 if (reader == NULL)
3667 return(-1);
3668 /* TODO maybe lookup the attribute value for " first */
3669 return((int) '"');
3670}
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003671
3672/**
3673 * xmlTextReaderXmlLang:
3674 * @reader: the xmlTextReaderPtr used
3675 *
3676 * The xml:lang scope within which the node resides.
3677 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003678 * Returns the xml:lang value or NULL if none exists.,
3679 * if non NULL it need to be freed by the caller.
Daniel Veillarde1ca5032002-12-09 14:13:43 +00003680 */
3681xmlChar *
3682xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3683 if (reader == NULL)
3684 return(NULL);
3685 if (reader->node == NULL)
3686 return(NULL);
3687 return(xmlNodeGetLang(reader->node));
3688}
3689
Daniel Veillard67df8092002-12-16 22:04:11 +00003690/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00003691 * xmlTextReaderConstXmlLang:
Daniel Veillarde72c5082003-09-19 12:44:05 +00003692 * @reader: the xmlTextReaderPtr used
3693 *
3694 * The xml:lang scope within which the node resides.
3695 *
3696 * Returns the xml:lang value or NULL if none exists.
3697 */
3698const xmlChar *
3699xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3700 xmlChar *tmp;
3701 const xmlChar *ret;
3702
3703 if (reader == NULL)
3704 return(NULL);
3705 if (reader->node == NULL)
3706 return(NULL);
3707 tmp = xmlNodeGetLang(reader->node);
3708 if (tmp == NULL)
3709 return(NULL);
3710 ret = CONSTSTR(tmp);
3711 xmlFree(tmp);
3712 return(ret);
3713}
3714
3715/**
Daniel Veillardf85ce8e2003-09-22 10:24:45 +00003716 * xmlTextReaderConstString:
3717 * @reader: the xmlTextReaderPtr used
3718 * @str: the string to intern.
3719 *
3720 * Get an interned string from the reader, allows for example to
3721 * speedup string name comparisons
3722 *
3723 * Returns an interned copy of the string or NULL in case of error. The
3724 * string will be deallocated with the reader.
3725 */
3726const xmlChar *
3727xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3728 if (reader == NULL)
3729 return(NULL);
3730 return(CONSTSTR(str));
3731}
3732
3733/**
Daniel Veillard67df8092002-12-16 22:04:11 +00003734 * xmlTextReaderNormalization:
3735 * @reader: the xmlTextReaderPtr used
3736 *
3737 * The value indicating whether to normalize white space and attribute values.
3738 * Since attribute value and end of line normalizations are a MUST in the XML
3739 * specification only the value true is accepted. The broken bahaviour of
3740 * accepting out of range character entities like &#0; is of course not
3741 * supported either.
3742 *
3743 * Returns 1 or -1 in case of error.
3744 */
3745int
3746xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3747 if (reader == NULL)
3748 return(-1);
3749 return(1);
3750}
3751
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003752/************************************************************************
3753 * *
3754 * Extensions to the base APIs *
3755 * *
3756 ************************************************************************/
3757
3758/**
3759 * xmlTextReaderSetParserProp:
3760 * @reader: the xmlTextReaderPtr used
3761 * @prop: the xmlParserProperties to set
3762 * @value: usually 0 or 1 to (de)activate it
3763 *
3764 * Change the parser processing behaviour by changing some of its internal
3765 * properties. Note that some properties can only be changed before any
3766 * read has been done.
3767 *
3768 * Returns 0 if the call was successful, or -1 in case of error
3769 */
3770int
3771xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3772 xmlParserProperties p = (xmlParserProperties) prop;
3773 xmlParserCtxtPtr ctxt;
3774
3775 if ((reader == NULL) || (reader->ctxt == NULL))
3776 return(-1);
3777 ctxt = reader->ctxt;
3778
3779 switch (p) {
3780 case XML_PARSER_LOADDTD:
3781 if (value != 0) {
3782 if (ctxt->loadsubset == 0) {
3783 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3784 return(-1);
3785 ctxt->loadsubset = XML_DETECT_IDS;
3786 }
3787 } else {
3788 ctxt->loadsubset = 0;
3789 }
3790 return(0);
3791 case XML_PARSER_DEFAULTATTRS:
3792 if (value != 0) {
3793 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3794 } else {
3795 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3796 ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3797 }
3798 return(0);
3799 case XML_PARSER_VALIDATE:
3800 if (value != 0) {
3801 ctxt->validate = 1;
Daniel Veillardf4e55762003-04-15 23:32:22 +00003802 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003803 } else {
3804 ctxt->validate = 0;
3805 }
3806 return(0);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003807 case XML_PARSER_SUBST_ENTITIES:
3808 if (value != 0) {
3809 ctxt->replaceEntities = 1;
3810 } else {
3811 ctxt->replaceEntities = 0;
3812 }
3813 return(0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003814 }
3815 return(-1);
3816}
3817
3818/**
3819 * xmlTextReaderGetParserProp:
3820 * @reader: the xmlTextReaderPtr used
3821 * @prop: the xmlParserProperties to get
3822 *
3823 * Read the parser internal property.
3824 *
3825 * Returns the value, usually 0 or 1, or -1 in case of error.
3826 */
3827int
3828xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3829 xmlParserProperties p = (xmlParserProperties) prop;
3830 xmlParserCtxtPtr ctxt;
3831
3832 if ((reader == NULL) || (reader->ctxt == NULL))
3833 return(-1);
3834 ctxt = reader->ctxt;
3835
3836 switch (p) {
3837 case XML_PARSER_LOADDTD:
3838 if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3839 return(1);
3840 return(0);
3841 case XML_PARSER_DEFAULTATTRS:
3842 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3843 return(1);
3844 return(0);
3845 case XML_PARSER_VALIDATE:
Daniel Veillardf4e55762003-04-15 23:32:22 +00003846 return(reader->validate);
Daniel Veillarde18fc182002-12-28 22:56:33 +00003847 case XML_PARSER_SUBST_ENTITIES:
3848 return(ctxt->replaceEntities);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00003849 }
3850 return(-1);
3851}
3852
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003853
Daniel Veillarde18fc182002-12-28 22:56:33 +00003854/**
Aleksey Sanind671e282005-01-03 21:58:59 +00003855 * xmlTextReaderGetParserLineNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003856 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003857 *
3858 * Provide the line number of the current parsing point.
3859 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003860 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003861 */
3862int
3863xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3864{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003865 if ((reader == NULL) || (reader->ctxt == NULL) ||
3866 (reader->ctxt->input == NULL)) {
3867 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003868 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003869 return (reader->ctxt->input->line);
Aleksey Sanind671e282005-01-03 21:58:59 +00003870}
3871
3872/**
3873 * xmlTextReaderGetParserColumnNumber:
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003874 * @reader: the user data (XML reader context)
Aleksey Sanind671e282005-01-03 21:58:59 +00003875 *
3876 * Provide the column number of the current parsing point.
3877 *
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003878 * Returns an int or 0 if not available
Aleksey Sanind671e282005-01-03 21:58:59 +00003879 */
3880int
3881xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3882{
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003883 if ((reader == NULL) || (reader->ctxt == NULL) ||
3884 (reader->ctxt->input == NULL)) {
3885 return (0);
Aleksey Sanind671e282005-01-03 21:58:59 +00003886 }
Daniel Veillardf6b71bd2005-01-04 17:50:14 +00003887 return (reader->ctxt->input->col);
Aleksey Sanind671e282005-01-03 21:58:59 +00003888}
3889
3890/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00003891 * xmlTextReaderCurrentNode:
3892 * @reader: the xmlTextReaderPtr used
3893 *
3894 * Hacking interface allowing to get the xmlNodePtr correponding to the
3895 * current node being accessed by the xmlTextReader. This is dangerous
3896 * because the underlying node may be destroyed on the next Reads.
3897 *
3898 * Returns the xmlNodePtr or NULL in case of error.
3899 */
3900xmlNodePtr
3901xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3902 if (reader == NULL)
3903 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003904
Daniel Veillarde18fc182002-12-28 22:56:33 +00003905 if (reader->curnode != NULL)
3906 return(reader->curnode);
3907 return(reader->node);
3908}
3909
3910/**
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003911 * xmlTextReaderPreserve:
3912 * @reader: the xmlTextReaderPtr used
3913 *
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003914 * This tells the XML Reader to preserve the current node.
3915 * The caller must also use xmlTextReaderCurrentDoc() to
3916 * keep an handle on the resulting document once parsing has finished
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003917 *
3918 * Returns the xmlNodePtr or NULL in case of error.
3919 */
3920xmlNodePtr
3921xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3922 xmlNodePtr cur, parent;
3923
3924 if (reader == NULL)
3925 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003926
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003927 if (reader->curnode != NULL)
3928 cur = reader->curnode;
3929 else
3930 cur = reader->node;
3931 if (cur == NULL)
3932 return(NULL);
Daniel Veillard1e906612003-12-05 14:57:46 +00003933
Daniel Veillard4a14fb82004-06-14 19:58:20 +00003934 if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003935 cur->extra |= NODE_IS_PRESERVED;
3936 cur->extra |= NODE_IS_SPRESERVED;
3937 }
3938 reader->preserves++;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003939
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003940 parent = cur->parent;;
3941 while (parent != NULL) {
Daniel Veillard1e906612003-12-05 14:57:46 +00003942 if (parent->type == XML_ELEMENT_NODE)
3943 parent->extra |= NODE_IS_PRESERVED;
Daniel Veillard9ee35f32003-09-28 00:19:54 +00003944 parent = parent->parent;
3945 }
3946 return(cur);
3947}
3948
Daniel Veillard1e906612003-12-05 14:57:46 +00003949#ifdef LIBXML_PATTERN_ENABLED
3950/**
3951 * xmlTextReaderPreservePattern:
3952 * @reader: the xmlTextReaderPtr used
3953 * @pattern: an XPath subset pattern
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003954 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003955 *
Daniel Veillard1e906612003-12-05 14:57:46 +00003956 * This tells the XML Reader to preserve all nodes matched by the
3957 * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3958 * keep an handle on the resulting document once parsing has finished
3959 *
3960 * Returns a positive number in case of success and -1 in case of error
3961 */
3962int
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003963xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3964 const xmlChar **namespaces)
3965{
Daniel Veillard1e906612003-12-05 14:57:46 +00003966 xmlPatternPtr comp;
3967
3968 if ((reader == NULL) || (pattern == NULL))
3969 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02003970
Daniel Veillardffa7b7e2003-12-05 16:10:21 +00003971 comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
Daniel Veillard1e906612003-12-05 14:57:46 +00003972 if (comp == NULL)
3973 return(-1);
3974
3975 if (reader->patternMax <= 0) {
3976 reader->patternMax = 4;
3977 reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
3978 sizeof(reader->patternTab[0]));
3979 if (reader->patternTab == NULL) {
3980 xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
3981 return (-1);
3982 }
3983 }
3984 if (reader->patternNr >= reader->patternMax) {
3985 xmlPatternPtr *tmp;
3986 reader->patternMax *= 2;
3987 tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
3988 reader->patternMax *
3989 sizeof(reader->patternTab[0]));
3990 if (tmp == NULL) {
3991 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
3992 reader->patternMax /= 2;
3993 return (-1);
3994 }
3995 reader->patternTab = tmp;
3996 }
3997 reader->patternTab[reader->patternNr] = comp;
3998 return(reader->patternNr++);
3999}
4000#endif
4001
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004002/**
Daniel Veillarde18fc182002-12-28 22:56:33 +00004003 * xmlTextReaderCurrentDoc:
4004 * @reader: the xmlTextReaderPtr used
4005 *
4006 * Hacking interface allowing to get the xmlDocPtr correponding to the
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004007 * current document being accessed by the xmlTextReader.
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004008 * NOTE: as a result of this call, the reader will not destroy the
4009 * associated XML document and calling xmlFreeDoc() on the result
4010 * is needed once the reader parsing has finished.
Daniel Veillarde18fc182002-12-28 22:56:33 +00004011 *
4012 * Returns the xmlDocPtr or NULL in case of error.
4013 */
4014xmlDocPtr
4015xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00004016 if (reader == NULL)
4017 return(NULL);
4018 if (reader->doc != NULL)
4019 return(reader->doc);
Daniel Veillard14dad702008-03-14 14:29:40 +00004020 if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
Daniel Veillarde18fc182002-12-28 22:56:33 +00004021 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004022
Daniel Veillard9ee35f32003-09-28 00:19:54 +00004023 reader->preserve = 1;
Daniel Veillarde18fc182002-12-28 22:56:33 +00004024 return(reader->ctxt->myDoc);
4025}
4026
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004027#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004028static char *xmlTextReaderBuildMessage(const char *msg, va_list ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004029
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004030static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004031xmlTextReaderValidityError(void *ctxt, const char *msg, ...);
4032
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004033static void XMLCDECL
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004034xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...);
4035
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004036static void XMLCDECL
4037xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004038{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004039 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004040
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004041 char *str;
4042
4043 va_list ap;
4044
4045 va_start(ap, msg);
4046 str = xmlTextReaderBuildMessage(msg, ap);
4047 if (!reader->errorFunc) {
4048 xmlTextReaderValidityError(ctx, "%s", str);
4049 } else {
4050 reader->errorFunc(reader->errorFuncArg, str,
4051 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4052 NULL /* locator */ );
4053 }
4054 if (str != NULL)
4055 xmlFree(str);
4056 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004057}
4058
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004059static void XMLCDECL
4060xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004061{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004062 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004063
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004064 char *str;
4065
4066 va_list ap;
4067
4068 va_start(ap, msg);
4069 str = xmlTextReaderBuildMessage(msg, ap);
4070 if (!reader->errorFunc) {
4071 xmlTextReaderValidityWarning(ctx, "%s", str);
4072 } else {
4073 reader->errorFunc(reader->errorFuncArg, str,
4074 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4075 NULL /* locator */ );
4076 }
4077 if (str != NULL)
4078 xmlFree(str);
4079 va_end(ap);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004080}
4081
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004082static void
4083 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004084
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004085static void
4086xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004087{
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004088 xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004089
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004090 if (reader->sErrorFunc) {
4091 reader->sErrorFunc(reader->errorFuncArg, error);
4092 } else {
4093 xmlTextReaderStructuredError(reader, error);
4094 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004095}
Daniel Veillardf4e55762003-04-15 23:32:22 +00004096/**
Daniel Veillard33300b42003-04-17 09:09:19 +00004097 * xmlTextReaderRelaxNGSetSchema:
4098 * @reader: the xmlTextReaderPtr used
4099 * @schema: a precompiled RelaxNG schema
4100 *
4101 * Use RelaxNG to validate the document as it is processed.
4102 * Activation is only possible before the first Read().
4103 * if @schema is NULL, then RelaxNG validation is desactivated.
4104 @ The @schema should not be freed until the reader is deallocated
4105 * or its use has been deactivated.
4106 *
4107 * Returns 0 in case the RelaxNG validation could be (des)activated and
4108 * -1 in case of error.
4109 */
4110int
4111xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
Daniel Veillardce682bc2004-11-05 17:22:25 +00004112 if (reader == NULL)
4113 return(-1);
Daniel Veillard33300b42003-04-17 09:09:19 +00004114 if (schema == NULL) {
4115 if (reader->rngSchemas != NULL) {
4116 xmlRelaxNGFree(reader->rngSchemas);
4117 reader->rngSchemas = NULL;
4118 }
4119 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004120 if (! reader->rngPreserveCtxt)
4121 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004122 reader->rngValidCtxt = NULL;
4123 }
Noam Postavsky15794992012-03-19 16:08:16 +08004124 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004125 return(0);
4126 }
4127 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4128 return(-1);
4129 if (reader->rngSchemas != NULL) {
4130 xmlRelaxNGFree(reader->rngSchemas);
4131 reader->rngSchemas = NULL;
4132 }
4133 if (reader->rngValidCtxt != NULL) {
Noam Postavsky15794992012-03-19 16:08:16 +08004134 if (! reader->rngPreserveCtxt)
4135 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
Daniel Veillard33300b42003-04-17 09:09:19 +00004136 reader->rngValidCtxt = NULL;
4137 }
Noam Postavsky15794992012-03-19 16:08:16 +08004138 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004139 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4140 if (reader->rngValidCtxt == NULL)
4141 return(-1);
4142 if (reader->errorFunc != NULL) {
4143 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004144 xmlTextReaderValidityErrorRelay,
4145 xmlTextReaderValidityWarningRelay,
4146 reader);
4147 }
4148 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004149 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004150 xmlTextReaderValidityStructuredRelay,
4151 reader);
Daniel Veillard33300b42003-04-17 09:09:19 +00004152 }
4153 reader->rngValidErrors = 0;
4154 reader->rngFullNode = NULL;
4155 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4156 return(0);
4157}
4158
4159/**
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004160 * xmlTextReaderLocator:
4161 * @ctx: the xmlTextReaderPtr used
4162 * @file: returned file information
4163 * @line: returned line information
4164 *
4165 * Internal locator function for the readers
4166 *
4167 * Returns 0 in case the Schema validation could be (des)activated and
4168 * -1 in case of error.
4169 */
4170static int
4171xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4172 xmlTextReaderPtr reader;
4173
4174 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4175 return(-1);
4176
4177 if (file != NULL)
4178 *file = NULL;
4179 if (line != NULL)
4180 *line = 0;
4181
4182 reader = (xmlTextReaderPtr) ctx;
4183 if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4184 if (file != NULL)
4185 *file = reader->ctxt->input->filename;
4186 if (line != NULL)
4187 *line = reader->ctxt->input->line;
4188 return(0);
4189 }
4190 if (reader->node != NULL) {
4191 long res;
4192 int ret = 0;
4193
4194 if (line != NULL) {
4195 res = xmlGetLineNo(reader->node);
4196 if (res > 0)
4197 *line = (unsigned long) res;
4198 else
4199 ret = -1;
4200 }
4201 if (file != NULL) {
4202 xmlDocPtr doc = reader->node->doc;
4203 if ((doc != NULL) && (doc->URL != NULL))
4204 *file = (const char *) doc->URL;
4205 else
4206 ret = -1;
4207 }
4208 return(ret);
4209 }
4210 return(-1);
4211}
4212
4213/**
Daniel Veillardf10ae122005-07-10 19:03:16 +00004214 * xmlTextReaderSetSchema:
4215 * @reader: the xmlTextReaderPtr used
4216 * @schema: a precompiled Schema schema
4217 *
4218 * Use XSD Schema to validate the document as it is processed.
4219 * Activation is only possible before the first Read().
4220 * if @schema is NULL, then Schema validation is desactivated.
4221 @ The @schema should not be freed until the reader is deallocated
4222 * or its use has been deactivated.
4223 *
4224 * Returns 0 in case the Schema validation could be (des)activated and
4225 * -1 in case of error.
4226 */
4227int
4228xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4229 if (reader == NULL)
4230 return(-1);
4231 if (schema == NULL) {
4232 if (reader->xsdPlug != NULL) {
4233 xmlSchemaSAXUnplug(reader->xsdPlug);
4234 reader->xsdPlug = NULL;
4235 }
4236 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004237 if (! reader->xsdPreserveCtxt)
4238 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004239 reader->xsdValidCtxt = NULL;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004240 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004241 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004242 if (reader->xsdSchemas != NULL) {
4243 xmlSchemaFree(reader->xsdSchemas);
4244 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004245 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004246 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004247 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004248 if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4249 return(-1);
4250 if (reader->xsdPlug != NULL) {
4251 xmlSchemaSAXUnplug(reader->xsdPlug);
4252 reader->xsdPlug = NULL;
4253 }
4254 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004255 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004256 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004257 reader->xsdValidCtxt = NULL;
4258 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004259 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004260 if (reader->xsdSchemas != NULL) {
4261 xmlSchemaFree(reader->xsdSchemas);
4262 reader->xsdSchemas = NULL;
4263 }
4264 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4265 if (reader->xsdValidCtxt == NULL) {
4266 xmlSchemaFree(reader->xsdSchemas);
4267 reader->xsdSchemas = NULL;
4268 return(-1);
4269 }
4270 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4271 &(reader->ctxt->sax),
4272 &(reader->ctxt->userData));
4273 if (reader->xsdPlug == NULL) {
4274 xmlSchemaFree(reader->xsdSchemas);
4275 reader->xsdSchemas = NULL;
4276 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4277 reader->xsdValidCtxt = NULL;
4278 return(-1);
4279 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004280 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4281 xmlTextReaderLocator,
4282 (void *) reader);
4283
Daniel Veillardf10ae122005-07-10 19:03:16 +00004284 if (reader->errorFunc != NULL) {
4285 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004286 xmlTextReaderValidityErrorRelay,
4287 xmlTextReaderValidityWarningRelay,
4288 reader);
4289 }
4290 if (reader->sErrorFunc != NULL) {
4291 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4292 xmlTextReaderValidityStructuredRelay,
4293 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004294 }
4295 reader->xsdValidErrors = 0;
4296 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4297 return(0);
4298}
4299
4300/**
Noam Postavsky15794992012-03-19 16:08:16 +08004301 * xmlTextReaderRelaxNGValidateInternal:
Daniel Veillardf4e55762003-04-15 23:32:22 +00004302 * @reader: the xmlTextReaderPtr used
4303 * @rng: the path to a RelaxNG schema or NULL
Noam Postavsky15794992012-03-19 16:08:16 +08004304 * @ctxt: the RelaxNG schema validation context or NULL
4305 * @options: options (not yet used)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004306 *
4307 * Use RelaxNG to validate the document as it is processed.
4308 * Activation is only possible before the first Read().
Noam Postavsky15794992012-03-19 16:08:16 +08004309 * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004310 *
William M. Brackd46c1ca2007-02-08 23:34:34 +00004311 * Returns 0 in case the RelaxNG validation could be (de)activated and
Noam Postavsky15794992012-03-19 16:08:16 +08004312 * -1 in case of error.
Daniel Veillardf4e55762003-04-15 23:32:22 +00004313 */
Noam Postavsky15794992012-03-19 16:08:16 +08004314static int
4315xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4316 const char *rng,
4317 xmlRelaxNGValidCtxtPtr ctxt,
4318 int options ATTRIBUTE_UNUSED)
4319{
Daniel Veillardf4e55762003-04-15 23:32:22 +00004320 if (reader == NULL)
Daniel Veillardf4e55762003-04-15 23:32:22 +00004321 return(-1);
Noam Postavsky15794992012-03-19 16:08:16 +08004322
4323 if ((rng != NULL) && (ctxt != NULL))
4324 return (-1);
4325
4326 if (((rng != NULL) || (ctxt != NULL)) &&
4327 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4328 (reader->ctxt == NULL)))
4329 return(-1);
4330
4331 /* Cleanup previous validation stuff. */
4332 if (reader->rngValidCtxt != NULL) {
4333 if ( !reader->rngPreserveCtxt)
4334 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4335 reader->rngValidCtxt = NULL;
4336 }
4337 reader->rngPreserveCtxt = 0;
Daniel Veillard33300b42003-04-17 09:09:19 +00004338 if (reader->rngSchemas != NULL) {
4339 xmlRelaxNGFree(reader->rngSchemas);
4340 reader->rngSchemas = NULL;
4341 }
Noam Postavsky15794992012-03-19 16:08:16 +08004342
4343 if ((rng == NULL) && (ctxt == NULL)) {
4344 /* We just want to deactivate the validation, so get out. */
4345 return(0);
Daniel Veillard33300b42003-04-17 09:09:19 +00004346 }
Noam Postavsky15794992012-03-19 16:08:16 +08004347
4348
4349 if (rng != NULL) {
4350 xmlRelaxNGParserCtxtPtr pctxt;
4351 /* Parse the schema and create validation environment. */
4352
4353 pctxt = xmlRelaxNGNewParserCtxt(rng);
4354 if (reader->errorFunc != NULL) {
4355 xmlRelaxNGSetParserErrors(pctxt,
4356 xmlTextReaderValidityErrorRelay,
4357 xmlTextReaderValidityWarningRelay,
4358 reader);
4359 }
4360 if (reader->sErrorFunc != NULL) {
4361 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4362 xmlTextReaderValidityStructuredRelay,
4363 reader);
4364 }
4365 reader->rngSchemas = xmlRelaxNGParse(pctxt);
4366 xmlRelaxNGFreeParserCtxt(pctxt);
4367 if (reader->rngSchemas == NULL)
4368 return(-1);
4369 reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4370 if (reader->rngValidCtxt == NULL) {
4371 xmlRelaxNGFree(reader->rngSchemas);
4372 reader->rngSchemas = NULL;
4373 return(-1);
4374 }
4375 } else {
4376 /* Use the given validation context. */
4377 reader->rngValidCtxt = ctxt;
4378 reader->rngPreserveCtxt = 1;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004379 }
Noam Postavsky15794992012-03-19 16:08:16 +08004380 /*
4381 * Redirect the validation context's error channels to use
4382 * the reader channels.
4383 * TODO: In case the user provides the validation context we
4384 * could make this redirection optional.
4385 */
Daniel Veillardf4e55762003-04-15 23:32:22 +00004386 if (reader->errorFunc != NULL) {
4387 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004388 xmlTextReaderValidityErrorRelay,
4389 xmlTextReaderValidityWarningRelay,
4390 reader);
4391 }
4392 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004393 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004394 xmlTextReaderValidityStructuredRelay,
4395 reader);
Daniel Veillardf4e55762003-04-15 23:32:22 +00004396 }
4397 reader->rngValidErrors = 0;
4398 reader->rngFullNode = NULL;
4399 reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4400 return(0);
4401}
Daniel Veillardf10ae122005-07-10 19:03:16 +00004402
4403/**
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004404 * xmlTextReaderSchemaValidateInternal:
Daniel Veillardf10ae122005-07-10 19:03:16 +00004405 * @reader: the xmlTextReaderPtr used
4406 * @xsd: the path to a W3C XSD schema or NULL
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004407 * @ctxt: the XML Schema validation context or NULL
4408 * @options: options (not used yet)
Daniel Veillardf10ae122005-07-10 19:03:16 +00004409 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004410 * Validate the document as it is processed using XML Schema.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004411 * Activation is only possible before the first Read().
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004412 * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
Daniel Veillardf10ae122005-07-10 19:03:16 +00004413 *
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004414 * Returns 0 in case the schemas validation could be (de)activated and
Daniel Veillardf10ae122005-07-10 19:03:16 +00004415 * -1 in case of error.
4416 */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004417static int
4418xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4419 const char *xsd,
4420 xmlSchemaValidCtxtPtr ctxt,
4421 int options ATTRIBUTE_UNUSED)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004422{
Daniel Veillardf10ae122005-07-10 19:03:16 +00004423 if (reader == NULL)
4424 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004425
4426 if ((xsd != NULL) && (ctxt != NULL))
Daniel Veillardf10ae122005-07-10 19:03:16 +00004427 return(-1);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004428
4429 if (((xsd != NULL) || (ctxt != NULL)) &&
4430 ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4431 (reader->ctxt == NULL)))
4432 return(-1);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004433
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004434 /* Cleanup previous validation stuff. */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004435 if (reader->xsdPlug != NULL) {
4436 xmlSchemaSAXUnplug(reader->xsdPlug);
4437 reader->xsdPlug = NULL;
4438 }
4439 if (reader->xsdValidCtxt != NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004440 if (! reader->xsdPreserveCtxt)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004441 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004442 reader->xsdValidCtxt = NULL;
4443 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004444 reader->xsdPreserveCtxt = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +00004445 if (reader->xsdSchemas != NULL) {
4446 xmlSchemaFree(reader->xsdSchemas);
4447 reader->xsdSchemas = NULL;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004448 }
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004449
4450 if ((xsd == NULL) && (ctxt == NULL)) {
4451 /* We just want to deactivate the validation, so get out. */
4452 return(0);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004453 }
4454
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004455 if (xsd != NULL) {
4456 xmlSchemaParserCtxtPtr pctxt;
4457 /* Parse the schema and create validation environment. */
4458 pctxt = xmlSchemaNewParserCtxt(xsd);
4459 if (reader->errorFunc != NULL) {
4460 xmlSchemaSetParserErrors(pctxt,
4461 xmlTextReaderValidityErrorRelay,
4462 xmlTextReaderValidityWarningRelay,
4463 reader);
4464 }
4465 reader->xsdSchemas = xmlSchemaParse(pctxt);
4466 xmlSchemaFreeParserCtxt(pctxt);
4467 if (reader->xsdSchemas == NULL)
4468 return(-1);
4469 reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4470 if (reader->xsdValidCtxt == NULL) {
4471 xmlSchemaFree(reader->xsdSchemas);
4472 reader->xsdSchemas = NULL;
4473 return(-1);
4474 }
4475 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4476 &(reader->ctxt->sax),
4477 &(reader->ctxt->userData));
4478 if (reader->xsdPlug == NULL) {
4479 xmlSchemaFree(reader->xsdSchemas);
4480 reader->xsdSchemas = NULL;
4481 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4482 reader->xsdValidCtxt = NULL;
4483 return(-1);
4484 }
4485 } else {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004486 /* Use the given validation context. */
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004487 reader->xsdValidCtxt = ctxt;
4488 reader->xsdPreserveCtxt = 1;
4489 reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4490 &(reader->ctxt->sax),
4491 &(reader->ctxt->userData));
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004492 if (reader->xsdPlug == NULL) {
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004493 reader->xsdValidCtxt = NULL;
4494 reader->xsdPreserveCtxt = 0;
4495 return(-1);
4496 }
Daniel Veillardf10ae122005-07-10 19:03:16 +00004497 }
Daniel Veillard97fa5b32012-08-14 11:01:07 +08004498 xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4499 xmlTextReaderLocator,
4500 (void *) reader);
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004501 /*
4502 * Redirect the validation context's error channels to use
4503 * the reader channels.
4504 * TODO: In case the user provides the validation context we
4505 * could make this redirection optional.
4506 */
Daniel Veillardf10ae122005-07-10 19:03:16 +00004507 if (reader->errorFunc != NULL) {
4508 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004509 xmlTextReaderValidityErrorRelay,
4510 xmlTextReaderValidityWarningRelay,
4511 reader);
4512 }
4513 if (reader->sErrorFunc != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004514 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004515 xmlTextReaderValidityStructuredRelay,
4516 reader);
Daniel Veillardf10ae122005-07-10 19:03:16 +00004517 }
4518 reader->xsdValidErrors = 0;
4519 reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4520 return(0);
4521}
Kasimier T. Buchcikbdadaed2005-12-07 14:02:42 +00004522
4523/**
4524 * xmlTextReaderSchemaValidateCtxt:
4525 * @reader: the xmlTextReaderPtr used
4526 * @ctxt: the XML Schema validation context or NULL
4527 * @options: options (not used yet)
4528 *
4529 * Use W3C XSD schema context to validate the document as it is processed.
4530 * Activation is only possible before the first Read().
4531 * If @ctxt is NULL, then XML Schema validation is deactivated.
4532 *
4533 * Returns 0 in case the schemas validation could be (de)activated and
4534 * -1 in case of error.
4535 */
4536int
4537xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4538 xmlSchemaValidCtxtPtr ctxt,
4539 int options)
4540{
4541 return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4542}
4543
4544/**
4545 * xmlTextReaderSchemaValidate:
4546 * @reader: the xmlTextReaderPtr used
4547 * @xsd: the path to a W3C XSD schema or NULL
4548 *
4549 * Use W3C XSD schema to validate the document as it is processed.
4550 * Activation is only possible before the first Read().
4551 * If @xsd is NULL, then XML Schema validation is deactivated.
4552 *
4553 * Returns 0 in case the schemas validation could be (de)activated and
4554 * -1 in case of error.
4555 */
4556int
4557xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4558{
4559 return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4560}
Noam Postavsky15794992012-03-19 16:08:16 +08004561
4562/**
4563 * xmlTextReaderRelaxNGValidateCtxt:
4564 * @reader: the xmlTextReaderPtr used
4565 * @ctxt: the RelaxNG schema validation context or NULL
4566 * @options: options (not used yet)
4567 *
4568 * Use RelaxNG schema context to validate the document as it is processed.
4569 * Activation is only possible before the first Read().
4570 * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4571 *
4572 * Returns 0 in case the schemas validation could be (de)activated and
4573 * -1 in case of error.
4574 */
4575int
4576xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4577 xmlRelaxNGValidCtxtPtr ctxt,
4578 int options)
4579{
4580 return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4581}
4582
4583/**
4584 * xmlTextReaderRelaxNGValidate:
4585 * @reader: the xmlTextReaderPtr used
4586 * @rng: the path to a RelaxNG schema or NULL
4587 *
4588 * Use RelaxNG schema to validate the document as it is processed.
4589 * Activation is only possible before the first Read().
4590 * If @rng is NULL, then RelaxNG schema validation is deactivated.
4591 *
4592 * Returns 0 in case the schemas validation could be (de)activated and
4593 * -1 in case of error.
4594 */
4595int
4596xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4597{
4598 return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4599}
4600
Daniel Veillard37fc84d2003-05-09 19:38:15 +00004601#endif
Daniel Veillardf4e55762003-04-15 23:32:22 +00004602
Daniel Veillarde2811272004-10-19 09:04:23 +00004603/**
4604 * xmlTextReaderIsNamespaceDecl:
4605 * @reader: the xmlTextReaderPtr used
4606 *
4607 * Determine whether the current node is a namespace declaration
4608 * rather than a regular attribute.
4609 *
4610 * Returns 1 if the current node is a namespace declaration, 0 if it
4611 * is a regular attribute or other type of node, or -1 in case of
4612 * error.
4613 */
4614int
4615xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4616 xmlNodePtr node;
4617 if (reader == NULL)
4618 return(-1);
4619 if (reader->node == NULL)
4620 return(-1);
4621 if (reader->curnode != NULL)
4622 node = reader->curnode;
4623 else
4624 node = reader->node;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004625
Daniel Veillarde2811272004-10-19 09:04:23 +00004626 if (XML_NAMESPACE_DECL == node->type)
4627 return(1);
4628 else
4629 return(0);
4630}
4631
4632/**
4633 * xmlTextReaderConstXmlVersion:
4634 * @reader: the xmlTextReaderPtr used
4635 *
4636 * Determine the XML version of the document being read.
4637 *
4638 * Returns a string containing the XML version of the document or NULL
4639 * in case of error. The string is deallocated with the reader.
4640 */
4641const xmlChar *
4642xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4643 xmlDocPtr doc = NULL;
4644 if (reader == NULL)
4645 return(NULL);
4646 if (reader->doc != NULL)
4647 doc = reader->doc;
4648 else if (reader->ctxt != NULL)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004649 doc = reader->ctxt->myDoc;
Daniel Veillarde2811272004-10-19 09:04:23 +00004650 if (doc == NULL)
4651 return(NULL);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004652
Daniel Veillarde2811272004-10-19 09:04:23 +00004653 if (doc->version == NULL)
4654 return(NULL);
4655 else
4656 return(CONSTSTR(doc->version));
4657}
4658
4659/**
4660 * xmlTextReaderStandalone:
4661 * @reader: the xmlTextReaderPtr used
4662 *
4663 * Determine the standalone status of the document being read.
4664 *
4665 * Returns 1 if the document was declared to be standalone, 0 if it
4666 * was declared to be not standalone, or -1 if the document did not
4667 * specify its standalone status or in case of error.
4668 */
4669int
4670xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4671 xmlDocPtr doc = NULL;
4672 if (reader == NULL)
4673 return(-1);
4674 if (reader->doc != NULL)
4675 doc = reader->doc;
4676 else if (reader->ctxt != NULL)
4677 doc = reader->ctxt->myDoc;
4678 if (doc == NULL)
4679 return(-1);
4680
4681 return(doc->standalone);
4682}
4683
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00004684/************************************************************************
4685 * *
Daniel Veillard26f70262003-01-16 22:45:08 +00004686 * Error Handling Extensions *
4687 * *
4688 ************************************************************************/
4689
4690/* helper to build a xmlMalloc'ed string from a format and va_list */
4691static char *
4692xmlTextReaderBuildMessage(const char *msg, va_list ap) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004693 int size = 0;
Daniel Veillard26f70262003-01-16 22:45:08 +00004694 int chars;
4695 char *larger;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004696 char *str = NULL;
4697 va_list aq;
Daniel Veillard26f70262003-01-16 22:45:08 +00004698
4699 while (1) {
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004700 VA_COPY(aq, ap);
4701 chars = vsnprintf(str, size, msg, aq);
4702 va_end(aq);
4703 if (chars < 0) {
4704 xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004705 if (str)
4706 xmlFree(str);
4707 return NULL;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004708 }
4709 if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
Daniel Veillard26f70262003-01-16 22:45:08 +00004710 break;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004711 if (chars < MAX_ERR_MSG_SIZE)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004712 size = chars + 1;
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004713 else
4714 size = MAX_ERR_MSG_SIZE;
Daniel Veillard26f70262003-01-16 22:45:08 +00004715 if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4716 xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
Daniel Veillard7e65fad2008-09-25 14:55:21 +00004717 if (str)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004718 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004719 return NULL;
4720 }
4721 str = larger;
4722 }
4723
4724 return str;
4725}
4726
Daniel Veillard417be3a2003-01-20 21:26:34 +00004727/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004728 * xmlTextReaderLocatorLineNumber:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004729 * @locator: the xmlTextReaderLocatorPtr used
4730 *
4731 * Obtain the line number for the given locator.
4732 *
4733 * Returns the line number or -1 in case of error.
4734 */
4735int
4736xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4737 /* we know that locator is a xmlParserCtxtPtr */
4738 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4739 int ret = -1;
4740
Daniel Veillardce682bc2004-11-05 17:22:25 +00004741 if (locator == NULL)
4742 return(-1);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004743 if (ctx->node != NULL) {
4744 ret = xmlGetLineNo(ctx->node);
4745 }
4746 else {
4747 /* inspired from error.c */
4748 xmlParserInputPtr input;
4749 input = ctx->input;
4750 if ((input->filename == NULL) && (ctx->inputNr > 1))
4751 input = ctx->inputTab[ctx->inputNr - 2];
4752 if (input != NULL) {
4753 ret = input->line;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004754 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004755 else {
4756 ret = -1;
4757 }
4758 }
4759
4760 return ret;
4761}
4762
4763/**
Daniel Veillard540a31a2003-01-21 11:21:07 +00004764 * xmlTextReaderLocatorBaseURI:
Daniel Veillard417be3a2003-01-20 21:26:34 +00004765 * @locator: the xmlTextReaderLocatorPtr used
4766 *
4767 * Obtain the base URI for the given locator.
4768 *
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004769 * Returns the base URI or NULL in case of error,
4770 * if non NULL it need to be freed by the caller.
Daniel Veillard417be3a2003-01-20 21:26:34 +00004771 */
4772xmlChar *
4773xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4774 /* we know that locator is a xmlParserCtxtPtr */
4775 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4776 xmlChar *ret = NULL;
4777
Daniel Veillardce682bc2004-11-05 17:22:25 +00004778 if (locator == NULL)
4779 return(NULL);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004780 if (ctx->node != NULL) {
4781 ret = xmlNodeGetBase(NULL,ctx->node);
4782 }
4783 else {
4784 /* inspired from error.c */
4785 xmlParserInputPtr input;
4786 input = ctx->input;
4787 if ((input->filename == NULL) && (ctx->inputNr > 1))
4788 input = ctx->inputTab[ctx->inputNr - 2];
4789 if (input != NULL) {
Daniel Veillard580ced82003-03-21 21:22:48 +00004790 ret = xmlStrdup(BAD_CAST input->filename);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004791 }
Daniel Veillard417be3a2003-01-20 21:26:34 +00004792 else {
4793 ret = NULL;
4794 }
4795 }
4796
4797 return ret;
4798}
4799
Daniel Veillard26f70262003-01-16 22:45:08 +00004800static void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004801xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4802 char *str)
4803{
4804 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4805
4806 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
Daniel Veillard26f70262003-01-16 22:45:08 +00004807
William M. Bracka3215c72004-07-31 16:24:01 +00004808 if (str != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004809 if (reader->errorFunc)
4810 reader->errorFunc(reader->errorFuncArg, str, severity,
4811 (xmlTextReaderLocatorPtr) ctx);
4812 xmlFree(str);
Daniel Veillard26f70262003-01-16 22:45:08 +00004813 }
4814}
4815
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004816static void
4817xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4818{
4819 xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
William M. Brack93d004f2004-02-03 00:14:10 +00004820
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004821 xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4822
4823 if (error && reader->sErrorFunc) {
4824 reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4825 }
William M. Brack93d004f2004-02-03 00:14:10 +00004826}
4827
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004828static void XMLCDECL
4829xmlTextReaderError(void *ctxt, const char *msg, ...)
4830{
Daniel Veillard26f70262003-01-16 22:45:08 +00004831 va_list ap;
4832
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004833 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004834 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004835 XML_PARSER_SEVERITY_ERROR,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004836 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004837 va_end(ap);
4838
4839}
4840
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004841static void XMLCDECL
4842xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4843{
Daniel Veillard26f70262003-01-16 22:45:08 +00004844 va_list ap;
4845
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004846 va_start(ap, msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004847 xmlTextReaderGenericError(ctxt,
Daniel Veillard417be3a2003-01-20 21:26:34 +00004848 XML_PARSER_SEVERITY_WARNING,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004849 xmlTextReaderBuildMessage(msg, ap));
Daniel Veillard26f70262003-01-16 22:45:08 +00004850 va_end(ap);
4851}
4852
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004853static void XMLCDECL
4854xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4855{
Daniel Veillard26f70262003-01-16 22:45:08 +00004856 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004857
Daniel Veillard417be3a2003-01-20 21:26:34 +00004858 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004859
Daniel Veillard417be3a2003-01-20 21:26:34 +00004860 if ((len > 1) && (msg[len - 2] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004861 /*
4862 * some callbacks only report locator information:
4863 * skip them (mimicking behaviour in error.c)
4864 */
4865 va_start(ap, msg);
4866 xmlTextReaderGenericError(ctxt,
4867 XML_PARSER_SEVERITY_VALIDITY_ERROR,
4868 xmlTextReaderBuildMessage(msg, ap));
4869 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004870 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004871}
4872
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004873static void XMLCDECL
4874xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4875{
Daniel Veillard26f70262003-01-16 22:45:08 +00004876 va_list ap;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004877
Daniel Veillard417be3a2003-01-20 21:26:34 +00004878 int len = xmlStrlen((const xmlChar *) msg);
Daniel Veillard26f70262003-01-16 22:45:08 +00004879
Daniel Veillard417be3a2003-01-20 21:26:34 +00004880 if ((len != 0) && (msg[len - 1] != ':')) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004881 /*
4882 * some callbacks only report locator information:
4883 * skip them (mimicking behaviour in error.c)
4884 */
4885 va_start(ap, msg);
4886 xmlTextReaderGenericError(ctxt,
4887 XML_PARSER_SEVERITY_VALIDITY_WARNING,
4888 xmlTextReaderBuildMessage(msg, ap));
4889 va_end(ap);
Daniel Veillard417be3a2003-01-20 21:26:34 +00004890 }
Daniel Veillard26f70262003-01-16 22:45:08 +00004891}
4892
4893/**
4894 * xmlTextReaderSetErrorHandler:
4895 * @reader: the xmlTextReaderPtr used
4896 * @f: the callback function to call on error and warnings
4897 * @arg: a user argument to pass to the callback function
4898 *
Daniel Veillard417be3a2003-01-20 21:26:34 +00004899 * Register a callback function that will be called on error and warnings.
4900 *
Daniel Veillard26f70262003-01-16 22:45:08 +00004901 * If @f is NULL, the default error and warning handlers are restored.
4902 */
4903void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004904xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4905 xmlTextReaderErrorFunc f, void *arg)
4906{
Daniel Veillard26f70262003-01-16 22:45:08 +00004907 if (f != NULL) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004908 reader->ctxt->sax->error = xmlTextReaderError;
4909 reader->ctxt->sax->serror = NULL;
4910 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4911 reader->ctxt->sax->warning = xmlTextReaderWarning;
4912 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4913 reader->errorFunc = f;
4914 reader->sErrorFunc = NULL;
4915 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004916#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004917 if (reader->rngValidCtxt) {
4918 xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4919 xmlTextReaderValidityErrorRelay,
4920 xmlTextReaderValidityWarningRelay,
4921 reader);
4922 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4923 reader);
4924 }
4925 if (reader->xsdValidCtxt) {
4926 xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4927 xmlTextReaderValidityErrorRelay,
4928 xmlTextReaderValidityWarningRelay,
4929 reader);
4930 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4931 reader);
4932 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004933#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004934 } else {
4935 /* restore defaults */
4936 reader->ctxt->sax->error = xmlParserError;
4937 reader->ctxt->vctxt.error = xmlParserValidityError;
4938 reader->ctxt->sax->warning = xmlParserWarning;
4939 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4940 reader->errorFunc = NULL;
4941 reader->sErrorFunc = NULL;
4942 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004943#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004944 if (reader->rngValidCtxt) {
4945 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4946 reader);
4947 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4948 reader);
4949 }
4950 if (reader->xsdValidCtxt) {
4951 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4952 reader);
4953 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4954 reader);
4955 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004956#endif
Daniel Veillard26f70262003-01-16 22:45:08 +00004957 }
4958}
4959
Daniel Veillard417be3a2003-01-20 21:26:34 +00004960/**
William M. Brack93d004f2004-02-03 00:14:10 +00004961* xmlTextReaderSetStructuredErrorHandler:
4962 * @reader: the xmlTextReaderPtr used
4963 * @f: the callback function to call on error and warnings
4964 * @arg: a user argument to pass to the callback function
4965 *
4966 * Register a callback function that will be called on error and warnings.
4967 *
4968 * If @f is NULL, the default error and warning handlers are restored.
4969 */
4970void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004971xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
4972 xmlStructuredErrorFunc f, void *arg)
4973{
4974 if (f != NULL) {
4975 reader->ctxt->sax->error = NULL;
4976 reader->ctxt->sax->serror = xmlTextReaderStructuredError;
4977 reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4978 reader->ctxt->sax->warning = xmlTextReaderWarning;
4979 reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4980 reader->sErrorFunc = f;
4981 reader->errorFunc = NULL;
4982 reader->errorFuncArg = arg;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004983#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004984 if (reader->rngValidCtxt) {
4985 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4986 reader);
4987 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4988 xmlTextReaderValidityStructuredRelay,
4989 reader);
4990 }
4991 if (reader->xsdValidCtxt) {
4992 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4993 reader);
4994 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4995 xmlTextReaderValidityStructuredRelay,
4996 reader);
4997 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00004998#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02004999 } else {
5000 /* restore defaults */
5001 reader->ctxt->sax->error = xmlParserError;
5002 reader->ctxt->sax->serror = NULL;
5003 reader->ctxt->vctxt.error = xmlParserValidityError;
5004 reader->ctxt->sax->warning = xmlParserWarning;
5005 reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5006 reader->errorFunc = NULL;
5007 reader->sErrorFunc = NULL;
5008 reader->errorFuncArg = NULL;
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005009#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005010 if (reader->rngValidCtxt) {
5011 xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5012 reader);
5013 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5014 reader);
5015 }
5016 if (reader->xsdValidCtxt) {
5017 xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5018 reader);
5019 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5020 reader);
5021 }
Daniel Veillardda0aa4c2005-07-13 23:07:49 +00005022#endif
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005023 }
William M. Brack93d004f2004-02-03 00:14:10 +00005024}
5025
5026/**
Daniel Veillardf6bad792003-04-11 19:38:54 +00005027 * xmlTextReaderIsValid:
5028 * @reader: the xmlTextReaderPtr used
5029 *
5030 * Retrieve the validity status from the parser context
5031 *
5032 * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5033 */
5034int
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005035xmlTextReaderIsValid(xmlTextReaderPtr reader)
5036{
5037 if (reader == NULL)
5038 return (-1);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005039#ifdef LIBXML_SCHEMAS_ENABLED
5040 if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005041 return (reader->rngValidErrors == 0);
Daniel Veillardf10ae122005-07-10 19:03:16 +00005042 if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005043 return (reader->xsdValidErrors == 0);
Daniel Veillardf4e55762003-04-15 23:32:22 +00005044#endif
Daniel Veillard16ed5972003-11-20 18:22:31 +00005045 if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005046 return (reader->ctxt->valid);
5047 return (0);
Daniel Veillardf6bad792003-04-11 19:38:54 +00005048}
5049
5050/**
Daniel Veillard417be3a2003-01-20 21:26:34 +00005051 * xmlTextReaderGetErrorHandler:
5052 * @reader: the xmlTextReaderPtr used
5053 * @f: the callback function or NULL is no callback has been registered
5054 * @arg: a user argument
5055 *
5056 * Retrieve the error callback function and user argument.
5057 */
Daniel Veillard26f70262003-01-16 22:45:08 +00005058void
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005059xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5060 xmlTextReaderErrorFunc * f, void **arg)
5061{
5062 if (f != NULL)
5063 *f = reader->errorFunc;
5064 if (arg != NULL)
5065 *arg = reader->errorFuncArg;
Daniel Veillard26f70262003-01-16 22:45:08 +00005066}
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005067/************************************************************************
5068 * *
5069 * New set (2.6.0) of simpler and more flexible APIs *
5070 * *
5071 ************************************************************************/
5072
5073/**
5074 * xmlTextReaderSetup:
5075 * @reader: an XML reader
Daniel Veillarde96b47f2007-01-04 17:28:35 +00005076 * @input: xmlParserInputBufferPtr used to feed the reader, will
5077 * be destroyed with it.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005078 * @URL: the base URL to use for the document
5079 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005080 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005081 *
5082 * Setup an XML reader with new options
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005083 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005084 * Returns 0 in case of success and -1 in case of error.
5085 */
Aleksey Sanind8377642007-01-03 23:13:12 +00005086int
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005087xmlTextReaderSetup(xmlTextReaderPtr reader,
5088 xmlParserInputBufferPtr input, const char *URL,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005089 const char *encoding, int options)
5090{
William M. Brackd46c1ca2007-02-08 23:34:34 +00005091 if (reader == NULL) {
William M. Brackbf9a73d2007-02-09 00:07:07 +00005092 if (input != NULL)
William M. Brackd46c1ca2007-02-08 23:34:34 +00005093 xmlFreeParserInputBuffer(input);
William M. Brackbf9a73d2007-02-09 00:07:07 +00005094 return (-1);
William M. Brackd46c1ca2007-02-08 23:34:34 +00005095 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005096
Daniel Veillard8874b942005-08-25 13:19:21 +00005097 /*
5098 * we force the generation of compact text nodes on the reader
5099 * since usr applications should never modify the tree
5100 */
5101 options |= XML_PARSE_COMPACT;
5102
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005103 reader->doc = NULL;
5104 reader->entNr = 0;
Daniel Veillarde74d2e12003-12-09 11:35:37 +00005105 reader->parserFlags = options;
Daniel Veillardc36965d2003-12-02 10:28:48 +00005106 reader->validate = XML_TEXTREADER_NOT_VALIDATE;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005107 if ((input != NULL) && (reader->input != NULL) &&
5108 (reader->allocs & XML_TEXTREADER_INPUT)) {
5109 xmlFreeParserInputBuffer(reader->input);
5110 reader->input = NULL;
5111 reader->allocs -= XML_TEXTREADER_INPUT;
5112 }
5113 if (input != NULL) {
5114 reader->input = input;
5115 reader->allocs |= XML_TEXTREADER_INPUT;
5116 }
5117 if (reader->buffer == NULL)
Daniel Veillard8aebce32012-07-16 14:42:31 +08005118 reader->buffer = xmlBufCreateSize(100);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005119 if (reader->buffer == NULL) {
5120 xmlGenericError(xmlGenericErrorContext,
5121 "xmlTextReaderSetup : malloc failed\n");
5122 return (-1);
5123 }
5124 if (reader->sax == NULL)
5125 reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5126 if (reader->sax == NULL) {
5127 xmlGenericError(xmlGenericErrorContext,
5128 "xmlTextReaderSetup : malloc failed\n");
5129 return (-1);
5130 }
5131 xmlSAXVersion(reader->sax, 2);
5132 reader->startElement = reader->sax->startElement;
5133 reader->sax->startElement = xmlTextReaderStartElement;
5134 reader->endElement = reader->sax->endElement;
5135 reader->sax->endElement = xmlTextReaderEndElement;
5136#ifdef LIBXML_SAX1_ENABLED
5137 if (reader->sax->initialized == XML_SAX2_MAGIC) {
5138#endif /* LIBXML_SAX1_ENABLED */
5139 reader->startElementNs = reader->sax->startElementNs;
5140 reader->sax->startElementNs = xmlTextReaderStartElementNs;
5141 reader->endElementNs = reader->sax->endElementNs;
5142 reader->sax->endElementNs = xmlTextReaderEndElementNs;
5143#ifdef LIBXML_SAX1_ENABLED
5144 } else {
5145 reader->startElementNs = NULL;
5146 reader->endElementNs = NULL;
5147 }
5148#endif /* LIBXML_SAX1_ENABLED */
5149 reader->characters = reader->sax->characters;
5150 reader->sax->characters = xmlTextReaderCharacters;
5151 reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5152 reader->cdataBlock = reader->sax->cdataBlock;
5153 reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5154
5155 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5156 reader->node = NULL;
5157 reader->curnode = NULL;
5158 if (input != NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005159 if (xmlBufUse(reader->input->buffer) < 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005160 xmlParserInputBufferRead(input, 4);
5161 }
5162 if (reader->ctxt == NULL) {
Daniel Veillard8aebce32012-07-16 14:42:31 +08005163 if (xmlBufUse(reader->input->buffer) >= 4) {
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005164 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
Daniel Veillard8aebce32012-07-16 14:42:31 +08005165 (const char *) xmlBufContent(reader->input->buffer),
5166 4, URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005167 reader->base = 0;
5168 reader->cur = 4;
5169 } else {
5170 reader->ctxt =
5171 xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5172 reader->base = 0;
5173 reader->cur = 0;
5174 }
5175 } else {
5176 xmlParserInputPtr inputStream;
5177 xmlParserInputBufferPtr buf;
5178 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5179
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005180 xmlCtxtReset(reader->ctxt);
5181 buf = xmlAllocParserInputBuffer(enc);
5182 if (buf == NULL) return(-1);
5183 inputStream = xmlNewInputStream(reader->ctxt);
5184 if (inputStream == NULL) {
5185 xmlFreeParserInputBuffer(buf);
5186 return(-1);
5187 }
5188
5189 if (URL == NULL)
5190 inputStream->filename = NULL;
5191 else
5192 inputStream->filename = (char *)
5193 xmlCanonicPath((const xmlChar *) URL);
5194 inputStream->buf = buf;
Daniel Veillard61551a12012-07-16 16:28:47 +08005195 xmlBufResetInput(buf->buffer, inputStream);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005196
5197 inputPush(reader->ctxt, inputStream);
5198 reader->cur = 0;
5199 }
5200 if (reader->ctxt == NULL) {
5201 xmlGenericError(xmlGenericErrorContext,
5202 "xmlTextReaderSetup : malloc failed\n");
5203 return (-1);
5204 }
5205 }
5206 if (reader->dict != NULL) {
5207 if (reader->ctxt->dict != NULL) {
5208 if (reader->dict != reader->ctxt->dict) {
5209 xmlDictFree(reader->dict);
5210 reader->dict = reader->ctxt->dict;
5211 }
5212 } else {
5213 reader->ctxt->dict = reader->dict;
5214 }
5215 } else {
5216 if (reader->ctxt->dict == NULL)
5217 reader->ctxt->dict = xmlDictCreate();
5218 reader->dict = reader->ctxt->dict;
5219 }
5220 reader->ctxt->_private = reader;
5221 reader->ctxt->linenumbers = 1;
5222 reader->ctxt->dictNames = 1;
5223 /*
5224 * use the parser dictionnary to allocate all elements and attributes names
5225 */
5226 reader->ctxt->docdict = 1;
Daniel Veillard0df3bc32004-06-08 12:03:41 +00005227 reader->ctxt->parseMode = XML_PARSE_READER;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005228
Daniel Veillard7899c5c2003-11-03 12:31:38 +00005229#ifdef LIBXML_XINCLUDE_ENABLED
5230 if (reader->xincctxt != NULL) {
5231 xmlXIncludeFreeContext(reader->xincctxt);
5232 reader->xincctxt = NULL;
5233 }
5234 if (options & XML_PARSE_XINCLUDE) {
5235 reader->xinclude = 1;
5236 reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5237 options -= XML_PARSE_XINCLUDE;
5238 } else
5239 reader->xinclude = 0;
5240 reader->in_xinclude = 0;
5241#endif
Daniel Veillard1e906612003-12-05 14:57:46 +00005242#ifdef LIBXML_PATTERN_ENABLED
5243 if (reader->patternTab == NULL) {
5244 reader->patternNr = 0;
5245 reader->patternMax = 0;
5246 }
5247 while (reader->patternNr > 0) {
5248 reader->patternNr--;
5249 if (reader->patternTab[reader->patternNr] != NULL) {
5250 xmlFreePattern(reader->patternTab[reader->patternNr]);
5251 reader->patternTab[reader->patternNr] = NULL;
5252 }
5253 }
5254#endif
5255
Daniel Veillardc36965d2003-12-02 10:28:48 +00005256 if (options & XML_PARSE_DTDVALID)
5257 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5258
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005259 xmlCtxtUseOptions(reader->ctxt, options);
5260 if (encoding != NULL) {
5261 xmlCharEncodingHandlerPtr hdlr;
5262
5263 hdlr = xmlFindCharEncodingHandler(encoding);
5264 if (hdlr != NULL)
5265 xmlSwitchToEncoding(reader->ctxt, hdlr);
5266 }
5267 if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5268 (reader->ctxt->input->filename == NULL))
5269 reader->ctxt->input->filename = (char *)
5270 xmlStrdup((const xmlChar *) URL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005271
5272 reader->doc = NULL;
5273
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005274 return (0);
5275}
5276
5277/**
Daniel Veillard5e094142005-02-18 19:36:12 +00005278 * xmlTextReaderByteConsumed:
5279 * @reader: an XML reader
5280 *
5281 * This function provides the current index of the parser used
5282 * by the reader, relative to the start of the current entity.
5283 * This function actually just wraps a call to xmlBytesConsumed()
5284 * for the parser context associated with the reader.
5285 * See xmlBytesConsumed() for more information.
5286 *
5287 * Returns the index in bytes from the beginning of the entity or -1
5288 * in case the index could not be computed.
5289 */
5290long
5291xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5292 if ((reader == NULL) || (reader->ctxt == NULL))
5293 return(-1);
5294 return(xmlByteConsumed(reader->ctxt));
5295}
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005296
Daniel Veillard5e094142005-02-18 19:36:12 +00005297
5298/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005299 * xmlReaderWalker:
5300 * @doc: a preparsed document
5301 *
5302 * Create an xmltextReader for a preparsed document.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005303 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005304 * Returns the new reader or NULL in case of error.
5305 */
5306xmlTextReaderPtr
5307xmlReaderWalker(xmlDocPtr doc)
5308{
5309 xmlTextReaderPtr ret;
5310
5311 if (doc == NULL)
5312 return(NULL);
5313
5314 ret = xmlMalloc(sizeof(xmlTextReader));
5315 if (ret == NULL) {
5316 xmlGenericError(xmlGenericErrorContext,
5317 "xmlNewTextReader : malloc failed\n");
5318 return(NULL);
5319 }
5320 memset(ret, 0, sizeof(xmlTextReader));
5321 ret->entNr = 0;
5322 ret->input = NULL;
5323 ret->mode = XML_TEXTREADER_MODE_INITIAL;
5324 ret->node = NULL;
5325 ret->curnode = NULL;
5326 ret->base = 0;
5327 ret->cur = 0;
5328 ret->allocs = XML_TEXTREADER_CTXT;
5329 ret->doc = doc;
5330 ret->state = XML_TEXTREADER_START;
5331 ret->dict = xmlDictCreate();
5332 return(ret);
5333}
5334
5335/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005336 * xmlReaderForDoc:
5337 * @cur: a pointer to a zero terminated string
5338 * @URL: the base URL to use for the document
5339 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005340 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005341 *
5342 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005343 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005344 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005345 * Returns the new reader or NULL in case of error.
5346 */
5347xmlTextReaderPtr
5348xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5349 int options)
5350{
5351 int len;
5352
5353 if (cur == NULL)
5354 return (NULL);
5355 len = xmlStrlen(cur);
5356
5357 return (xmlReaderForMemory
5358 ((const char *) cur, len, URL, encoding, options));
5359}
5360
5361/**
5362 * xmlReaderForFile:
5363 * @filename: a file or URL
5364 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005365 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005366 *
5367 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005368 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005369 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005370 * Returns the new reader or NULL in case of error.
5371 */
5372xmlTextReaderPtr
5373xmlReaderForFile(const char *filename, const char *encoding, int options)
5374{
5375 xmlTextReaderPtr reader;
5376
5377 reader = xmlNewTextReaderFilename(filename);
5378 if (reader == NULL)
5379 return (NULL);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005380 xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005381 return (reader);
5382}
5383
5384/**
5385 * xmlReaderForMemory:
5386 * @buffer: a pointer to a char array
5387 * @size: the size of the array
5388 * @URL: the base URL to use for the document
5389 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005390 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005391 *
5392 * Create an xmltextReader for an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005393 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005394 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005395 * Returns the new reader or NULL in case of error.
5396 */
5397xmlTextReaderPtr
5398xmlReaderForMemory(const char *buffer, int size, const char *URL,
5399 const char *encoding, int options)
5400{
5401 xmlTextReaderPtr reader;
5402 xmlParserInputBufferPtr buf;
5403
Daniel Veillard21924522004-02-19 16:37:07 +00005404 buf = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005405 XML_CHAR_ENCODING_NONE);
5406 if (buf == NULL) {
5407 return (NULL);
5408 }
5409 reader = xmlNewTextReader(buf, URL);
5410 if (reader == NULL) {
5411 xmlFreeParserInputBuffer(buf);
5412 return (NULL);
5413 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005414 reader->allocs |= XML_TEXTREADER_INPUT;
5415 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005416 return (reader);
5417}
5418
5419/**
5420 * xmlReaderForFd:
5421 * @fd: an open file descriptor
5422 * @URL: the base URL to use for the document
5423 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005424 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005425 *
5426 * Create an xmltextReader for an XML from a file descriptor.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005427 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005428 * NOTE that the file descriptor will not be closed when the
5429 * reader is closed or reset.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005430 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005431 * Returns the new reader or NULL in case of error.
5432 */
5433xmlTextReaderPtr
5434xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5435{
5436 xmlTextReaderPtr reader;
5437 xmlParserInputBufferPtr input;
5438
5439 if (fd < 0)
5440 return (NULL);
5441
5442 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5443 if (input == NULL)
5444 return (NULL);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005445 input->closecallback = NULL;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005446 reader = xmlNewTextReader(input, URL);
5447 if (reader == NULL) {
5448 xmlFreeParserInputBuffer(input);
5449 return (NULL);
5450 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005451 reader->allocs |= XML_TEXTREADER_INPUT;
5452 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005453 return (reader);
5454}
5455
5456/**
5457 * xmlReaderForIO:
5458 * @ioread: an I/O read function
5459 * @ioclose: an I/O close function
5460 * @ioctx: an I/O handler
5461 * @URL: the base URL to use for the document
5462 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005463 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005464 *
5465 * Create an xmltextReader for an XML document from I/O functions and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005466 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005467 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005468 * Returns the new reader or NULL in case of error.
5469 */
5470xmlTextReaderPtr
5471xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5472 void *ioctx, const char *URL, const char *encoding,
5473 int options)
5474{
5475 xmlTextReaderPtr reader;
5476 xmlParserInputBufferPtr input;
5477
5478 if (ioread == NULL)
5479 return (NULL);
5480
5481 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5482 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005483 if (input == NULL) {
5484 if (ioclose != NULL)
5485 ioclose(ioctx);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005486 return (NULL);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005487 }
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005488 reader = xmlNewTextReader(input, URL);
5489 if (reader == NULL) {
5490 xmlFreeParserInputBuffer(input);
5491 return (NULL);
5492 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005493 reader->allocs |= XML_TEXTREADER_INPUT;
5494 xmlTextReaderSetup(reader, NULL, URL, encoding, options);
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005495 return (reader);
5496}
5497
5498/**
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005499 * xmlReaderNewWalker:
5500 * @reader: an XML reader
5501 * @doc: a preparsed document
5502 *
5503 * Setup an xmltextReader to parse a preparsed XML document.
5504 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005505 *
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005506 * Returns 0 in case of success and -1 in case of error
5507 */
5508int
5509xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5510{
5511 if (doc == NULL)
5512 return (-1);
5513 if (reader == NULL)
5514 return (-1);
5515
Daniel Veillarddd6d3002004-11-03 14:20:29 +00005516 if (reader->input != NULL) {
5517 xmlFreeParserInputBuffer(reader->input);
5518 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005519 if (reader->ctxt != NULL) {
5520 xmlCtxtReset(reader->ctxt);
5521 }
5522
5523 reader->entNr = 0;
5524 reader->input = NULL;
5525 reader->mode = XML_TEXTREADER_MODE_INITIAL;
5526 reader->node = NULL;
5527 reader->curnode = NULL;
5528 reader->base = 0;
5529 reader->cur = 0;
5530 reader->allocs = XML_TEXTREADER_CTXT;
5531 reader->doc = doc;
5532 reader->state = XML_TEXTREADER_START;
5533 if (reader->dict == NULL) {
5534 if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5535 reader->dict = reader->ctxt->dict;
5536 else
5537 reader->dict = xmlDictCreate();
5538 }
5539 return(0);
5540}
5541
5542/**
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005543 * xmlReaderNewDoc:
5544 * @reader: an XML reader
5545 * @cur: a pointer to a zero terminated string
5546 * @URL: the base URL to use for the document
5547 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005548 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005549 *
5550 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005551 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005552 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005553 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005554 * Returns 0 in case of success and -1 in case of error
5555 */
5556int
5557xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5558 const char *URL, const char *encoding, int options)
5559{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005560
5561 int len;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005562
5563 if (cur == NULL)
5564 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005565 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005566 return (-1);
5567
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005568 len = xmlStrlen(cur);
5569 return (xmlReaderNewMemory(reader, (const char *)cur, len,
5570 URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005571}
5572
5573/**
5574 * xmlReaderNewFile:
5575 * @reader: an XML reader
5576 * @filename: a file or URL
5577 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005578 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005579 *
5580 * parse an XML file from the filesystem or the network.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005581 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005582 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005583 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005584 * Returns 0 in case of success and -1 in case of error
5585 */
5586int
5587xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5588 const char *encoding, int options)
5589{
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005590 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005591
5592 if (filename == NULL)
5593 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005594 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005595 return (-1);
5596
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005597 input =
5598 xmlParserInputBufferCreateFilename(filename,
5599 XML_CHAR_ENCODING_NONE);
5600 if (input == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005601 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005602 return (xmlTextReaderSetup(reader, input, filename, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005603}
5604
5605/**
5606 * xmlReaderNewMemory:
5607 * @reader: an XML reader
5608 * @buffer: a pointer to a char array
5609 * @size: the size of the array
5610 * @URL: the base URL to use for the document
5611 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005612 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005613 *
5614 * Setup an xmltextReader to parse an XML in-memory document.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005615 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005616 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005617 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005618 * Returns 0 in case of success and -1 in case of error
5619 */
5620int
5621xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5622 const char *URL, const char *encoding, int options)
5623{
5624 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005625
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005626 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005627 return (-1);
5628 if (buffer == NULL)
5629 return (-1);
5630
Daniel Veillard21924522004-02-19 16:37:07 +00005631 input = xmlParserInputBufferCreateStatic(buffer, size,
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005632 XML_CHAR_ENCODING_NONE);
5633 if (input == NULL) {
5634 return (-1);
5635 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005636 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005637}
5638
5639/**
5640 * xmlReaderNewFd:
5641 * @reader: an XML reader
5642 * @fd: an open file descriptor
5643 * @URL: the base URL to use for the document
5644 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005645 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005646 *
5647 * Setup an xmltextReader to parse an XML from a file descriptor.
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005648 * NOTE that the file descriptor will not be closed when the
5649 * reader is closed or reset.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005650 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005651 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005652 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005653 * Returns 0 in case of success and -1 in case of error
5654 */
5655int
5656xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5657 const char *URL, const char *encoding, int options)
5658{
5659 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005660
5661 if (fd < 0)
5662 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005663 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005664 return (-1);
5665
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005666 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5667 if (input == NULL)
5668 return (-1);
Daniel Veillard4bc5f432003-12-22 18:13:12 +00005669 input->closecallback = NULL;
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005670 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005671}
5672
5673/**
5674 * xmlReaderNewIO:
5675 * @reader: an XML reader
5676 * @ioread: an I/O read function
5677 * @ioclose: an I/O close function
5678 * @ioctx: an I/O handler
5679 * @URL: the base URL to use for the document
5680 * @encoding: the document encoding, or NULL
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005681 * @options: a combination of xmlParserOption
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005682 *
5683 * Setup an xmltextReader to parse an XML document from I/O functions
5684 * and source.
Daniel Veillard87ab1c12003-12-21 13:01:56 +00005685 * The parsing flags @options are a combination of xmlParserOption.
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005686 * This reuses the existing @reader xmlTextReader.
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005687 *
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005688 * Returns 0 in case of success and -1 in case of error
5689 */
5690int
5691xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5692 xmlInputCloseCallback ioclose, void *ioctx,
5693 const char *URL, const char *encoding, int options)
5694{
5695 xmlParserInputBufferPtr input;
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005696
5697 if (ioread == NULL)
5698 return (-1);
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005699 if (reader == NULL)
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005700 return (-1);
5701
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005702 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5703 XML_CHAR_ENCODING_NONE);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005704 if (input == NULL) {
5705 if (ioclose != NULL)
5706 ioclose(ioctx);
Daniel Veillard2c437da2012-05-11 12:08:15 +08005707 return (-1);
Lin Yi-Li24464be2012-05-10 16:14:55 +08005708 }
Daniel Veillard198c1bf2003-10-20 17:07:41 +00005709 return (xmlTextReaderSetup(reader, input, URL, encoding, options));
Daniel Veillardfc8dc352003-10-18 09:07:46 +00005710}
Lin Yi-Li24464be2012-05-10 16:14:55 +08005711
Daniel Veillard26f70262003-01-16 22:45:08 +00005712/************************************************************************
5713 * *
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005714 * Utilities *
5715 * *
5716 ************************************************************************/
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005717#ifdef NOT_USED_YET
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005718
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005719/**
5720 * xmlBase64Decode:
5721 * @in: the input buffer
5722 * @inlen: the size of the input (in), the size read from it (out)
5723 * @to: the output buffer
5724 * @tolen: the size of the output (in), the size written to (out)
5725 *
5726 * Base64 decoder, reads from @in and save in @to
Daniel Veillardd4310742003-02-18 21:12:46 +00005727 * TODO: tell jody when this is actually exported
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005728 *
5729 * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5730 * 2 if there wasn't enough space on the output or -1 in case of error.
5731 */
5732static int
5733xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005734 unsigned char *to, unsigned long *tolen)
5735{
5736 unsigned long incur; /* current index in in[] */
5737
5738 unsigned long inblk; /* last block index in in[] */
5739
5740 unsigned long outcur; /* current index in out[] */
5741
5742 unsigned long inmax; /* size of in[] */
5743
5744 unsigned long outmax; /* size of out[] */
5745
5746 unsigned char cur; /* the current value read from in[] */
5747
5748 unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */
5749
5750 int nbintmp; /* number of byte in intmp[] */
5751
5752 int is_ignore; /* cur should be ignored */
5753
5754 int is_end = 0; /* the end of the base64 was found */
5755
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005756 int retval = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005757
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005758 int i;
5759
5760 if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005761 return (-1);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005762
5763 incur = 0;
5764 inblk = 0;
5765 outcur = 0;
5766 inmax = *inlen;
5767 outmax = *tolen;
5768 nbintmp = 0;
5769
5770 while (1) {
5771 if (incur >= inmax)
5772 break;
5773 cur = in[incur++];
5774 is_ignore = 0;
5775 if ((cur >= 'A') && (cur <= 'Z'))
5776 cur = cur - 'A';
5777 else if ((cur >= 'a') && (cur <= 'z'))
5778 cur = cur - 'a' + 26;
5779 else if ((cur >= '0') && (cur <= '9'))
5780 cur = cur - '0' + 52;
5781 else if (cur == '+')
5782 cur = 62;
5783 else if (cur == '/')
5784 cur = 63;
5785 else if (cur == '.')
5786 cur = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005787 else if (cur == '=') /*no op , end of the base64 stream */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005788 is_end = 1;
5789 else {
5790 is_ignore = 1;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005791 if (nbintmp == 0)
5792 inblk = incur;
5793 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005794
5795 if (!is_ignore) {
5796 int nbouttmp = 3;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005797
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005798 int is_break = 0;
5799
5800 if (is_end) {
5801 if (nbintmp == 0)
5802 break;
5803 if ((nbintmp == 1) || (nbintmp == 2))
5804 nbouttmp = 1;
5805 else
5806 nbouttmp = 2;
5807 nbintmp = 3;
5808 is_break = 1;
5809 }
5810 intmp[nbintmp++] = cur;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005811 /*
5812 * if intmp is full, push the 4byte sequence as a 3 byte
5813 * sequence out
5814 */
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005815 if (nbintmp == 4) {
5816 nbintmp = 0;
5817 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5818 outtmp[1] =
5819 ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5820 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005821 if (outcur + 3 >= outmax) {
5822 retval = 2;
5823 break;
5824 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005825
5826 for (i = 0; i < nbouttmp; i++)
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005827 to[outcur++] = outtmp[i];
5828 inblk = incur;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005829 }
5830
5831 if (is_break) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005832 retval = 0;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005833 break;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005834 }
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005835 }
5836 }
5837
5838 *tolen = outcur;
5839 *inlen = inblk;
5840 return (retval);
5841}
5842
5843/*
5844 * Test routine for the xmlBase64Decode function
5845 */
5846#if 0
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005847int
5848main(int argc, char **argv)
5849{
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005850 char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005851
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005852 char output[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005853
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005854 char output2[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005855
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005856 char output3[100];
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005857
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005858 unsigned long inlen = strlen(input);
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005859
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005860 unsigned long outlen = 100;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005861
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005862 int ret;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005863
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005864 unsigned long cons, tmp, tmp2, prod;
5865
5866 /*
5867 * Direct
5868 */
5869 ret = xmlBase64Decode(input, &inlen, output, &outlen);
5870
5871 output[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005872 printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5873 outlen, output)indent: Standard input:179: Error:Unmatched #endif
5874;
5875
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005876 /*
5877 * output chunking
5878 */
5879 cons = 0;
5880 prod = 0;
5881 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005882 tmp = 5;
5883 tmp2 = inlen - cons;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005884
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005885 printf("%ld %ld\n", cons, prod);
5886 ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5887 cons += tmp2;
5888 prod += tmp;
5889 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005890 }
5891 output2[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005892 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5893 prod, output2);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005894
5895 /*
5896 * input chunking
5897 */
5898 cons = 0;
5899 prod = 0;
5900 while (cons < inlen) {
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005901 tmp = 100 - prod;
5902 tmp2 = inlen - cons;
5903 if (tmp2 > 5)
5904 tmp2 = 5;
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005905
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005906 printf("%ld %ld\n", cons, prod);
5907 ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5908 cons += tmp2;
5909 prod += tmp;
5910 printf("%ld %ld\n", cons, prod);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005911 }
5912 output3[outlen] = 0;
Daniel Veillardaacc2a22009-08-11 18:31:42 +02005913 printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5914 prod, output3);
5915 return (0);
Daniel Veillardbeb70bd2002-12-18 14:53:54 +00005916
5917}
5918#endif
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00005919#endif /* NOT_USED_YET */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00005920#define bottom_xmlreader
5921#include "elfgcchack.h"
Daniel Veillard81273902003-09-30 00:43:48 +00005922#endif /* LIBXML_READER_ENABLED */